BlueSky & more on desktop lazurite.stormlightlabs.org/
tauri rust typescript bluesky appview atproto solid
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 115 lines 3.6 kB view raw
1import { describe, expect, it } from "vitest"; 2import { filterProfileFeed, parseActorList, parseProfileResult } from "../profile"; 3import type { FeedViewPost } from "../types"; 4 5function createFeedItem(overrides: Partial<FeedViewPost> = {}): FeedViewPost { 6 return { 7 post: { 8 author: { did: "did:plc:alice", handle: "alice.test" }, 9 cid: "cid-1", 10 indexedAt: "2026-03-28T12:00:00.000Z", 11 record: { createdAt: "2026-03-28T12:00:00.000Z", text: "hello world" }, 12 uri: "at://did:plc:alice/app.bsky.feed.post/1", 13 }, 14 ...overrides, 15 }; 16} 17 18describe("profile helpers", () => { 19 it("parses actor lists with bios and follow state", () => { 20 const response = parseActorList({ 21 cursor: "cursor-1", 22 followers: [{ 23 avatar: "https://example.com/avatar.png", 24 description: "Writes about protocol design.", 25 did: "did:plc:bob", 26 displayName: "Bob", 27 handle: "bob.test", 28 viewer: { following: "at://did:plc:alice/app.bsky.graph.follow/1" }, 29 }], 30 }, "followers"); 31 32 expect(response).toEqual({ 33 cursor: "cursor-1", 34 actors: [{ 35 avatar: "https://example.com/avatar.png", 36 description: "Writes about protocol design.", 37 did: "did:plc:bob", 38 displayName: "Bob", 39 handle: "bob.test", 40 labels: [], 41 viewer: { following: "at://did:plc:alice/app.bsky.graph.follow/1" }, 42 }], 43 }); 44 }); 45 46 it("filters profile feeds by tab semantics", () => { 47 const base = createFeedItem(); 48 const reply = createFeedItem({ 49 post: { ...base.post, uri: "at://did:plc:alice/app.bsky.feed.post/2" }, 50 reply: { 51 parent: { $type: "app.bsky.feed.defs#postView", ...base.post }, 52 root: { $type: "app.bsky.feed.defs#postView", ...base.post }, 53 }, 54 }); 55 const media = createFeedItem({ 56 post: { 57 ...base.post, 58 embed: { $type: "app.bsky.embed.images#view", images: [{ thumb: "https://example.com/thumb.png" }] }, 59 uri: "at://did:plc:alice/app.bsky.feed.post/3", 60 }, 61 }); 62 63 expect(filterProfileFeed([base, reply, media], "posts")).toEqual([base, media]); 64 expect(filterProfileFeed([base, reply, media], "replies")).toEqual([reply]); 65 expect(filterProfileFeed([base, reply, media], "media")).toEqual([media]); 66 expect(filterProfileFeed([base, reply, media], "likes")).toEqual([base, reply, media]); 67 }); 68 69 it("parses available and unavailable profile results", () => { 70 expect( 71 parseProfileResult({ 72 status: "available", 73 profile: { did: "did:plc:bob", handle: "bob.test", displayName: "Bob" }, 74 }), 75 ).toEqual({ 76 status: "available", 77 profile: { 78 avatar: null, 79 banner: null, 80 createdAt: null, 81 description: null, 82 descriptionFacets: null, 83 did: "did:plc:bob", 84 displayName: "Bob", 85 followersCount: null, 86 followsCount: null, 87 handle: "bob.test", 88 indexedAt: null, 89 labels: [], 90 pinnedPost: null, 91 postsCount: null, 92 pronouns: null, 93 viewer: null, 94 website: null, 95 }, 96 }); 97 98 expect( 99 parseProfileResult({ 100 status: "unavailable", 101 requestedActor: "missing.test", 102 handle: "missing.test", 103 reason: "notFound", 104 message: "This profile could not be found.", 105 }), 106 ).toEqual({ 107 status: "unavailable", 108 requestedActor: "missing.test", 109 did: null, 110 handle: "missing.test", 111 reason: "notFound", 112 message: "This profile could not be found.", 113 }); 114 }); 115});