a4b528e5f5
* Add app.bsky.graph.searchStarterPacks lexicon * Codegen for app.bsky.graph.searchStarterPacks * Add app.bsky.unspecced.searchStarterPacksSkeleton * Gen app.bsky.unspecced.searchStarterPacksSkeleton * Add SearchStarterPacks rpc to bsky.proto * Implement searchStarterPacks endpoint * @atproto/api changeset * Add starter pack search by term to dataplane
264 lines
7.8 KiB
TypeScript
264 lines
7.8 KiB
TypeScript
import { AtpAgent } from '@atproto/api'
|
|
import { TestNetwork, SeedClient, RecordRef, basicSeed } from '@atproto/dev-env'
|
|
import { isRecord as isProfile } from '../../src/lexicon/types/app/bsky/actor/profile'
|
|
import { forSnapshot } from '../_util'
|
|
import assert from 'assert'
|
|
import { ids } from '../../src/lexicon/lexicons'
|
|
|
|
describe('starter packs', () => {
|
|
let network: TestNetwork
|
|
let agent: AtpAgent
|
|
let sc: SeedClient
|
|
let sp1: RecordRef
|
|
let sp2: RecordRef
|
|
let sp3: RecordRef
|
|
let sp4: RecordRef
|
|
|
|
beforeAll(async () => {
|
|
network = await TestNetwork.create({
|
|
dbPostgresSchema: 'bsky_views_starter_packs',
|
|
})
|
|
agent = network.bsky.getClient()
|
|
sc = network.getSeedClient()
|
|
await basicSeed(sc)
|
|
await network.processAll()
|
|
})
|
|
|
|
beforeAll(async () => {
|
|
const feedgen = await sc.createFeedGen(
|
|
sc.dids.alice,
|
|
'did:web:example.com',
|
|
"alice's feedgen",
|
|
)
|
|
sp1 = await sc.createStarterPack(
|
|
sc.dids.alice,
|
|
"alice's starter pack",
|
|
[sc.dids.bob, sc.dids.carol, sc.dids.dan],
|
|
[feedgen.uriStr],
|
|
)
|
|
sp2 = await sc.createStarterPack(
|
|
sc.dids.alice,
|
|
"alice's empty starter pack",
|
|
[],
|
|
[],
|
|
)
|
|
for (const n of [1, 2, 3]) {
|
|
const { did } = await sc.createAccount(`newskie${n}`, {
|
|
handle: `newskie${n}.test`,
|
|
email: `newskie${n}@test.com`,
|
|
password: `newskie${n}-pass`,
|
|
})
|
|
await sc.createProfile(did, `Newskie ${n}`, 'New here', [], sp1)
|
|
}
|
|
|
|
await sc.createAccount('frankie', {
|
|
handle: 'frankie.test',
|
|
email: 'frankie@frankie.com',
|
|
password: 'password',
|
|
})
|
|
await sc.createAccount('greta', {
|
|
handle: 'greta.test',
|
|
email: 'greta@greta.com',
|
|
password: 'password',
|
|
})
|
|
sp3 = await sc.createStarterPack(
|
|
sc.dids.alice,
|
|
"alice's about to get blocked starter pack",
|
|
[sc.dids.alice, sc.dids.frankie, sc.dids.greta],
|
|
[],
|
|
)
|
|
await sc.block(sc.dids.frankie, sc.dids.alice)
|
|
|
|
sp4 = await sc.createStarterPack(
|
|
sc.dids.bob,
|
|
"bob's starter pack in case you block alice",
|
|
[sc.dids.alice, sc.dids.frankie],
|
|
[],
|
|
)
|
|
|
|
await network.processAll()
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await network.close()
|
|
})
|
|
|
|
it('gets actor starter packs.', async () => {
|
|
const { data } = await agent.api.app.bsky.graph.getActorStarterPacks({
|
|
actor: sc.dids.alice,
|
|
})
|
|
expect(data.starterPacks).toHaveLength(3)
|
|
expect(forSnapshot(data.starterPacks)).toMatchSnapshot()
|
|
})
|
|
|
|
it('gets starter pack used on profile detail', async () => {
|
|
const { data: profile } = await agent.api.app.bsky.actor.getProfile({
|
|
actor: sc.dids.newskie1,
|
|
})
|
|
expect(forSnapshot(profile.joinedViaStarterPack)).toMatchSnapshot()
|
|
})
|
|
|
|
it('gets starter pack details', async () => {
|
|
const {
|
|
data: { starterPack },
|
|
} = await agent.api.app.bsky.graph.getStarterPack({
|
|
// resolve w/ handle in uri
|
|
starterPack: sp1.uriStr,
|
|
})
|
|
expect(forSnapshot(starterPack)).toMatchSnapshot()
|
|
})
|
|
|
|
it('gets starter pack details with handle in uri', async () => {
|
|
const {
|
|
data: { starterPack },
|
|
} = await agent.api.app.bsky.graph.getStarterPack({
|
|
// resolve w/ handle in uri
|
|
starterPack: sp1.uriStr.replace(
|
|
sc.dids.alice,
|
|
sc.accounts[sc.dids.alice].handle,
|
|
),
|
|
})
|
|
expect(starterPack.uri).toBe(sp1.uriStr)
|
|
})
|
|
|
|
it('gets starter pack details', async () => {
|
|
const {
|
|
data: { starterPacks },
|
|
} = await agent.api.app.bsky.graph.getStarterPacks({
|
|
uris: [sp2.uriStr, sp1.uriStr],
|
|
})
|
|
expect(forSnapshot(starterPacks)).toMatchSnapshot()
|
|
})
|
|
|
|
it('generates notifications', async () => {
|
|
const {
|
|
data: { notifications },
|
|
} = await agent.api.app.bsky.notification.listNotifications(
|
|
{ limit: 3 }, // three most recent
|
|
{
|
|
headers: await network.serviceHeaders(
|
|
sc.dids.alice,
|
|
ids.AppBskyNotificationListNotifications,
|
|
),
|
|
},
|
|
)
|
|
expect(notifications).toHaveLength(3)
|
|
notifications.forEach((notif) => {
|
|
expect(notif.reason).toBe('starterpack-joined')
|
|
expect(notif.reasonSubject).toBe(sp1.uriStr)
|
|
expect(notif.uri).toMatch(/\/app\.bsky\.actor\.profile\/self$/)
|
|
assert(isProfile(notif.record), 'record is not profile')
|
|
expect(notif.record.joinedViaStarterPack?.uri).toBe(sp1.uriStr)
|
|
})
|
|
expect(forSnapshot(notifications)).toMatchSnapshot()
|
|
})
|
|
|
|
it('does not include users with creator block relationship in list sample for non-creator, in-list viewers', async () => {
|
|
const view = await agent.api.app.bsky.graph.getStarterPack(
|
|
{
|
|
starterPack: sp3.uriStr,
|
|
},
|
|
{
|
|
headers: await network.serviceHeaders(
|
|
sc.dids.frankie,
|
|
ids.AppBskyGraphGetStarterPack,
|
|
),
|
|
},
|
|
)
|
|
expect(view.data.starterPack.listItemsSample?.length).toBe(2)
|
|
expect(forSnapshot(view.data.starterPack.listItemsSample)).toMatchSnapshot()
|
|
})
|
|
|
|
it('does not include users with creator block relationship in list sample for non-creator, not-in-list viewers', async () => {
|
|
const view = await agent.api.app.bsky.graph.getStarterPack(
|
|
{
|
|
starterPack: sp3.uriStr,
|
|
},
|
|
{
|
|
headers: await network.serviceHeaders(
|
|
sc.dids.bob,
|
|
ids.AppBskyGraphGetStarterPack,
|
|
),
|
|
},
|
|
)
|
|
expect(view.data.starterPack.listItemsSample?.length).toBe(2)
|
|
expect(forSnapshot(view.data.starterPack.listItemsSample)).toMatchSnapshot()
|
|
})
|
|
|
|
it('does not include users with creator block relationship in list sample for signed-out viewers', async () => {
|
|
const view = await agent.api.app.bsky.graph.getStarterPack({
|
|
starterPack: sp3.uriStr,
|
|
})
|
|
expect(view.data.starterPack.listItemsSample?.length).toBe(2)
|
|
expect(forSnapshot(view.data.starterPack.listItemsSample)).toMatchSnapshot()
|
|
})
|
|
|
|
it('does include users with creator block relationship in list sample for creator', async () => {
|
|
const view = await agent.api.app.bsky.graph.getStarterPack(
|
|
{ starterPack: sp3.uriStr },
|
|
{
|
|
headers: await network.serviceHeaders(
|
|
sc.dids.alice,
|
|
ids.AppBskyGraphGetStarterPack,
|
|
),
|
|
},
|
|
)
|
|
expect(view.data.starterPack.listItemsSample?.length).toBe(3)
|
|
expect(forSnapshot(view.data.starterPack.listItemsSample)).toMatchSnapshot()
|
|
})
|
|
|
|
describe('searchStarterPacks', () => {
|
|
it('searches starter packs and returns paginated', async () => {
|
|
const { data: page0 } = await agent.app.bsky.graph.searchStarterPacks({
|
|
q: 'starter',
|
|
limit: 3,
|
|
})
|
|
|
|
expect(page0.starterPacks).toMatchObject([
|
|
expect.objectContaining({ uri: sp4.uriStr }),
|
|
expect.objectContaining({ uri: sp3.uriStr }),
|
|
expect.objectContaining({ uri: sp2.uriStr }),
|
|
])
|
|
|
|
const { data: page1 } = await agent.api.app.bsky.graph.searchStarterPacks(
|
|
{
|
|
q: 'starter',
|
|
limit: 3,
|
|
cursor: page0.cursor,
|
|
},
|
|
)
|
|
|
|
expect(page1.starterPacks).toMatchObject([
|
|
expect.objectContaining({ uri: sp1.uriStr }),
|
|
])
|
|
})
|
|
|
|
it('filters by the search term', async () => {
|
|
const { data } = await agent.app.bsky.graph.searchStarterPacks({
|
|
q: 'In CaSe',
|
|
limit: 3,
|
|
})
|
|
|
|
expect(data.starterPacks).toMatchObject([
|
|
expect.objectContaining({ uri: sp4.uriStr }),
|
|
])
|
|
})
|
|
|
|
it('does not include starter packs with creator block relationship for non-creator viewers', async () => {
|
|
const { data } = await agent.app.bsky.graph.searchStarterPacks(
|
|
{ q: 'starter', limit: 3 },
|
|
{
|
|
headers: await network.serviceHeaders(
|
|
sc.dids.frankie,
|
|
ids.AppBskyGraphSearchStarterPacks,
|
|
),
|
|
},
|
|
)
|
|
|
|
expect(data.starterPacks).toMatchObject([
|
|
expect.objectContaining({ uri: sp4.uriStr }),
|
|
])
|
|
})
|
|
})
|
|
})
|