220 lines
6.3 KiB
TypeScript
220 lines
6.3 KiB
TypeScript
import { AppBskyFeedSearchPosts, AtpAgent, ids } from '@atproto/api'
|
|
import { SeedClient, TestNetwork, basicSeed } from '@atproto/dev-env'
|
|
import { DatabaseSchema } from '../../src'
|
|
|
|
const TAG_HIDE = 'hide'
|
|
|
|
describe('appview search', () => {
|
|
let network: TestNetwork
|
|
let agent: AtpAgent
|
|
let ozoneAgent: AtpAgent
|
|
let sc: SeedClient
|
|
let post0: Awaited<ReturnType<SeedClient['post']>>
|
|
let post1: Awaited<ReturnType<SeedClient['post']>>
|
|
let post2: Awaited<ReturnType<SeedClient['post']>>
|
|
let allResults: string[]
|
|
let nonTaggedResults: string[]
|
|
|
|
// account dids, for convenience
|
|
let alice: string
|
|
let bob: string
|
|
let carol: string
|
|
|
|
beforeAll(async () => {
|
|
network = await TestNetwork.create({
|
|
dbPostgresSchema: 'bsky_views_search',
|
|
bsky: {
|
|
searchTagsHide: new Set([TAG_HIDE]),
|
|
},
|
|
})
|
|
agent = network.bsky.getAgent()
|
|
sc = network.getSeedClient()
|
|
ozoneAgent = network.ozone.getAgent()
|
|
await basicSeed(sc)
|
|
|
|
alice = sc.dids.alice
|
|
bob = sc.dids.bob
|
|
carol = sc.dids.carol
|
|
|
|
post0 = await sc.post(alice, 'good doggo')
|
|
post1 = await sc.post(alice, 'bad doggo')
|
|
post2 = await sc.post(alice, 'cute doggo')
|
|
await network.processAll()
|
|
|
|
await createTag(network.bsky.db.db, {
|
|
uri: post1.ref.uriStr,
|
|
val: TAG_HIDE,
|
|
})
|
|
|
|
allResults = [post2.ref.uriStr, post1.ref.uriStr, post0.ref.uriStr]
|
|
nonTaggedResults = [post2.ref.uriStr, post0.ref.uriStr]
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await deleteTags(network.bsky.db.db, {
|
|
uri: post1.ref.uriStr,
|
|
})
|
|
|
|
await network.close()
|
|
})
|
|
|
|
describe(`post search with 'top' sort`, () => {
|
|
type TestCase = {
|
|
name: string
|
|
viewer: () => string
|
|
queryParams: () => AppBskyFeedSearchPosts.QueryParams
|
|
expectedPostUris: () => string[]
|
|
}
|
|
|
|
const tests: TestCase[] = [
|
|
// 'top' cases
|
|
{
|
|
name: `with 'top' sort, finds only non-tagged posts`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({ q: 'doggo', sort: 'top' }),
|
|
expectedPostUris: () => nonTaggedResults,
|
|
},
|
|
{
|
|
name: `with 'top' sort, includes tagged posts from the viewer`,
|
|
viewer: () => alice,
|
|
queryParams: () => ({ q: 'doggo', sort: 'top' }),
|
|
expectedPostUris: () => allResults,
|
|
},
|
|
{
|
|
name: `with 'top' sort, finds only non-tagged posts, even specifying author`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({ q: `doggo`, author: alice, sort: 'top' }),
|
|
expectedPostUris: () => nonTaggedResults,
|
|
},
|
|
{
|
|
name: `with 'top' sort, finds only non-tagged posts, even specifying from:`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({
|
|
q: `doggo from:${sc.accounts[alice].handle}`,
|
|
sort: 'top',
|
|
}),
|
|
expectedPostUris: () => nonTaggedResults,
|
|
},
|
|
{
|
|
name: `with 'top' sort, finds only non-tagged posts, even specifying DID`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({ q: `doggo ${alice}`, sort: 'top' }),
|
|
expectedPostUris: () => nonTaggedResults,
|
|
},
|
|
{
|
|
name: `with 'top' sort, finds no posts if specifying user who didn't post the term`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({ q: `doggo ${bob}`, sort: 'top' }),
|
|
expectedPostUris: () => [],
|
|
},
|
|
|
|
// 'latest' cases
|
|
{
|
|
name: `with 'latest' sort, finds only non-tagged posts`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({ q: 'doggo', sort: 'latest' }),
|
|
expectedPostUris: () => nonTaggedResults,
|
|
},
|
|
{
|
|
name: `with 'latest' sort, includes tagged posts from the viewer`,
|
|
viewer: () => alice,
|
|
queryParams: () => ({ q: 'doggo', sort: 'latest' }),
|
|
expectedPostUris: () => allResults,
|
|
},
|
|
{
|
|
name: `with 'latest' sort, finds all posts if specifying author`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({
|
|
q: `doggo`,
|
|
author: alice,
|
|
sort: 'latest',
|
|
}),
|
|
expectedPostUris: () => allResults,
|
|
},
|
|
{
|
|
name: `with 'latest' sort, finds all posts if specifying from:`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({
|
|
q: `doggo from:${sc.accounts[alice].handle}`,
|
|
sort: 'latest',
|
|
}),
|
|
expectedPostUris: () => allResults,
|
|
},
|
|
{
|
|
name: `with 'latest' sort, finds all posts if specifying DID`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({ q: `doggo ${alice}`, sort: 'latest' }),
|
|
expectedPostUris: () => allResults,
|
|
},
|
|
{
|
|
name: `with 'latest' sort, finds no posts if specifying user who didn't post the term`,
|
|
viewer: () => carol,
|
|
queryParams: () => ({ q: `doggo ${bob}`, sort: 'latest' }),
|
|
expectedPostUris: () => [],
|
|
},
|
|
]
|
|
|
|
it.each(tests)(
|
|
'$name',
|
|
async ({ viewer, queryParams, expectedPostUris }) => {
|
|
const res = await agent.app.bsky.feed.searchPosts(queryParams(), {
|
|
headers: await network.serviceHeaders(
|
|
viewer(),
|
|
ids.AppBskyFeedSearchPosts,
|
|
),
|
|
})
|
|
expect(res.data.posts.map((p) => p.uri)).toStrictEqual(
|
|
expectedPostUris(),
|
|
)
|
|
},
|
|
)
|
|
|
|
it('mod service finds even tagged posts', async () => {
|
|
const resTop = await ozoneAgent.app.bsky.feed.searchPosts(
|
|
{ q: 'doggo', sort: 'top' },
|
|
{ headers: await network.ozone.modHeaders(ids.AppBskyFeedSearchPosts) },
|
|
)
|
|
const resLatest = await ozoneAgent.app.bsky.feed.searchPosts(
|
|
{ q: 'doggo', sort: 'latest' },
|
|
{ headers: await network.ozone.modHeaders(ids.AppBskyFeedSearchPosts) },
|
|
)
|
|
|
|
expect(resTop.data.posts.map((p) => p.uri)).toStrictEqual(allResults)
|
|
expect(resLatest.data.posts.map((p) => p.uri)).toStrictEqual(allResults)
|
|
})
|
|
})
|
|
})
|
|
|
|
const createTag = async (
|
|
db: DatabaseSchema,
|
|
opts: {
|
|
uri: string
|
|
val: string
|
|
},
|
|
) => {
|
|
await db
|
|
.updateTable('record')
|
|
.set({
|
|
tags: JSON.stringify([opts.val]),
|
|
})
|
|
.where('uri', '=', opts.uri)
|
|
.returningAll()
|
|
.execute()
|
|
}
|
|
|
|
const deleteTags = async (
|
|
db: DatabaseSchema,
|
|
opts: {
|
|
uri: string
|
|
},
|
|
) => {
|
|
await db
|
|
.updateTable('record')
|
|
.set({
|
|
tags: JSON.stringify([]),
|
|
})
|
|
.where('uri', '=', opts.uri)
|
|
.returningAll()
|
|
.execute()
|
|
}
|