b15dec2f4f
* first pass/port * reworking * authenticated commit parsing * authenticate identity evts * some testing * tidy & add firehose to queue * error handling * fix test * refactor sync queue + some tests * fix race in sync queue * rm firehose from syncqueue * add tests for queue utils * README * lint readme * filter before parsing * pr feedback * small fix * changesets * fix type * Rework dataplane subscription (#2766) * working sync package into appview subscription * add restart method to subscription for tests * fix another test * tidy subscription utils/files * remove dupe property * tidy after merge * fix start cursor on subscription * tweak process full subscription logic * fixes
257 lines
7.6 KiB
TypeScript
257 lines
7.6 KiB
TypeScript
import { AtpAgent } from '@atproto/api'
|
|
import { wait } from '@atproto/common'
|
|
import { TestNetwork, SeedClient, usersBulkSeed } from '@atproto/dev-env'
|
|
import { forSnapshot, paginateAll, stripViewer } from '../_util'
|
|
import { ids } from '../../src/lexicon/lexicons'
|
|
|
|
// @NOTE skipped to help with CI failures
|
|
// The search code is not used in production & we should switch it out for tests on the search proxy interface
|
|
describe.skip('pds actor search views', () => {
|
|
let network: TestNetwork
|
|
let agent: AtpAgent
|
|
let sc: SeedClient
|
|
let headers: { [s: string]: string }
|
|
|
|
beforeAll(async () => {
|
|
network = await TestNetwork.create({
|
|
dbPostgresSchema: 'bsky_views_actor_search',
|
|
})
|
|
agent = network.bsky.getClient()
|
|
sc = network.getSeedClient()
|
|
|
|
await wait(50) // allow pending sub to be established
|
|
await network.bsky.sub.destroy()
|
|
await usersBulkSeed(sc)
|
|
|
|
// Skip did/handle resolution for expediency
|
|
const { db } = network.bsky
|
|
const now = new Date().toISOString()
|
|
await db.db
|
|
.insertInto('actor')
|
|
.values(
|
|
Object.entries(sc.dids).map(([handle, did]) => ({
|
|
did,
|
|
handle,
|
|
indexedAt: now,
|
|
})),
|
|
)
|
|
.onConflict((oc) => oc.doNothing())
|
|
.execute()
|
|
|
|
// Process remaining profiles
|
|
await network.bsky.sub.restart()
|
|
await network.processAll(50000)
|
|
headers = await network.serviceHeaders(
|
|
Object.values(sc.dids)[0],
|
|
ids.AppBskyActorSearchActorsTypeahead,
|
|
)
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await network.close()
|
|
})
|
|
|
|
it('typeahead gives relevant results', async () => {
|
|
const result = await agent.api.app.bsky.actor.searchActorsTypeahead(
|
|
{ term: 'car' },
|
|
{ headers },
|
|
)
|
|
|
|
const handles = result.data.actors.map((u) => u.handle)
|
|
|
|
const shouldContain = [
|
|
'cara-wiegand69.test',
|
|
'eudora-dietrich4.test', // Carol Littel
|
|
'shane-torphy52.test', // Sadie Carter
|
|
'aliya-hodkiewicz.test', // Carlton Abernathy IV
|
|
'carlos6.test',
|
|
'carolina-mcderm77.test',
|
|
]
|
|
|
|
shouldContain.forEach((handle) => expect(handles).toContain(handle))
|
|
expect(handles).toContain('cayla-marquardt39.test') // Fuzzy match
|
|
|
|
const shouldNotContain = [
|
|
'sven70.test',
|
|
'hilario84.test',
|
|
'santa-hermann78.test',
|
|
'dylan61.test',
|
|
'preston-harris.test',
|
|
'loyce95.test',
|
|
'melyna-zboncak.test',
|
|
]
|
|
|
|
shouldNotContain.forEach((handle) => expect(handles).not.toContain(handle))
|
|
|
|
const sorted = result.data.actors.sort((a, b) =>
|
|
a.handle > b.handle ? 1 : -1,
|
|
)
|
|
expect(forSnapshot(sorted)).toMatchSnapshot()
|
|
})
|
|
|
|
it('typeahead gives empty result set when provided empty term', async () => {
|
|
const result = await agent.api.app.bsky.actor.searchActorsTypeahead(
|
|
{ term: '' },
|
|
{ headers },
|
|
)
|
|
|
|
expect(result.data.actors).toEqual([])
|
|
})
|
|
|
|
it('typeahead applies limit', async () => {
|
|
const full = await agent.api.app.bsky.actor.searchActorsTypeahead(
|
|
{ term: 'p' },
|
|
{ headers },
|
|
)
|
|
|
|
expect(full.data.actors.length).toBeGreaterThan(5)
|
|
|
|
const limited = await agent.api.app.bsky.actor.searchActorsTypeahead(
|
|
{ term: 'p', limit: 5 },
|
|
{ headers },
|
|
)
|
|
|
|
// @NOTE it's expected that searchActorsTypeahead doesn't have stable pagination
|
|
|
|
const limitedIndexInFull = limited.data.actors.map((needle) => {
|
|
return full.data.actors.findIndex(
|
|
(haystack) => needle.did === haystack.did,
|
|
)
|
|
})
|
|
|
|
// subset exists in full and is monotonic
|
|
expect(limitedIndexInFull.every((idx) => idx !== -1)).toEqual(true)
|
|
expect(limitedIndexInFull).toEqual(
|
|
[...limitedIndexInFull].sort((a, b) => a - b),
|
|
)
|
|
})
|
|
|
|
it('typeahead gives results unauthed', async () => {
|
|
const { data: authed } =
|
|
await agent.api.app.bsky.actor.searchActorsTypeahead(
|
|
{ term: 'car' },
|
|
{ headers },
|
|
)
|
|
const { data: unauthed } =
|
|
await agent.api.app.bsky.actor.searchActorsTypeahead({
|
|
term: 'car',
|
|
})
|
|
expect(unauthed.actors.length).toBeGreaterThan(0)
|
|
expect(unauthed.actors).toEqual(authed.actors.map(stripViewer))
|
|
})
|
|
|
|
it('search gives relevant results', async () => {
|
|
const result = await agent.api.app.bsky.actor.searchActors(
|
|
{ term: 'car' },
|
|
{ headers },
|
|
)
|
|
|
|
const handles = result.data.actors.map((u) => u.handle)
|
|
|
|
const shouldContain = [
|
|
'cara-wiegand69.test',
|
|
'eudora-dietrich4.test', // Carol Littel
|
|
'shane-torphy52.test', // Sadie Carter
|
|
'aliya-hodkiewicz.test', // Carlton Abernathy IV
|
|
'carlos6.test',
|
|
'carolina-mcderm77.test',
|
|
]
|
|
|
|
shouldContain.forEach((handle) => expect(handles).toContain(handle))
|
|
expect(handles).toContain('cayla-marquardt39.test') // Fuzzy match
|
|
|
|
const shouldNotContain = [
|
|
'sven70.test',
|
|
'hilario84.test',
|
|
'santa-hermann78.test',
|
|
'dylan61.test',
|
|
'preston-harris.test',
|
|
'loyce95.test',
|
|
'melyna-zboncak.test',
|
|
]
|
|
|
|
shouldNotContain.forEach((handle) => expect(handles).not.toContain(handle))
|
|
|
|
const sorted = result.data.actors.sort((a, b) =>
|
|
a.handle > b.handle ? 1 : -1,
|
|
)
|
|
expect(forSnapshot(sorted)).toMatchSnapshot()
|
|
})
|
|
|
|
it('search gives empty result set when provided empty term', async () => {
|
|
const result = await agent.api.app.bsky.actor.searchActors(
|
|
{ term: '' },
|
|
{ headers },
|
|
)
|
|
|
|
expect(result.data.actors).toEqual([])
|
|
})
|
|
|
|
it('paginates', async () => {
|
|
const results = (results) => results.flatMap((res) => res.users)
|
|
const paginator = async (cursor?: string) => {
|
|
const res = await agent.api.app.bsky.actor.searchActors(
|
|
{ term: 'p', cursor, limit: 3 },
|
|
{ headers },
|
|
)
|
|
return res.data
|
|
}
|
|
|
|
const paginatedAll = await paginateAll(paginator)
|
|
paginatedAll.forEach((res) =>
|
|
expect(res.actors.length).toBeLessThanOrEqual(3),
|
|
)
|
|
|
|
const full = await agent.api.app.bsky.actor.searchActors(
|
|
{ term: 'p' },
|
|
{ headers },
|
|
)
|
|
|
|
expect(full.data.actors.length).toBeGreaterThan(5)
|
|
const sortedFull = results([full.data]).sort((a, b) =>
|
|
a.handle > b.handle ? 1 : -1,
|
|
)
|
|
const sortedPaginated = results(paginatedAll).sort((a, b) =>
|
|
a.handle > b.handle ? 1 : -1,
|
|
)
|
|
expect(sortedPaginated).toEqual(sortedFull)
|
|
})
|
|
|
|
it('search handles bad input', async () => {
|
|
// Mostly for sqlite's benefit, since it uses LIKE and these are special characters that will
|
|
// get stripped. This input triggers a special case where there are no "safe" words for sqlite to search on.
|
|
const result = await agent.api.app.bsky.actor.searchActors(
|
|
{ term: ' % _ ' },
|
|
{ headers },
|
|
)
|
|
|
|
expect(result.data.actors).toEqual([])
|
|
})
|
|
|
|
it('search gives results unauthed', async () => {
|
|
const { data: authed } = await agent.api.app.bsky.actor.searchActors(
|
|
{ term: 'car' },
|
|
{ headers },
|
|
)
|
|
const { data: unauthed } = await agent.api.app.bsky.actor.searchActors({
|
|
term: 'car',
|
|
})
|
|
expect(unauthed.actors.length).toBeGreaterThan(0)
|
|
expect(unauthed.actors).toEqual(authed.actors.map(stripViewer))
|
|
})
|
|
|
|
it('search blocks by actor takedown', async () => {
|
|
await network.bsky.server.ctx.dataplane.takedownActor({
|
|
did: sc.dids['cara-wiegand69.test'],
|
|
})
|
|
const result = await agent.api.app.bsky.actor.searchActorsTypeahead(
|
|
{ term: 'car' },
|
|
{ headers },
|
|
)
|
|
const handles = result.data.actors.map((u) => u.handle)
|
|
expect(handles).toContain('carlos6.test')
|
|
expect(handles).toContain('carolina-mcderm77.test')
|
|
expect(handles).not.toContain('cara-wiegand69.test')
|
|
})
|
|
})
|