import { test } from '@japa/runner' import db from '@adonisjs/lucid/services/db' import testUtils from '@adonisjs/core/services/test_utils' import BatchStore from '#services/batch_store' import SearchService from '#services/search_service' import { RangeIndexer } from '#lib/edge/index' import { DEFAULT_RULES } from '#lib/rules/index' import type { Overview } from '#lib/nntp/index' const GROUP = 'alt.binaries.posters' test.group('Poster search', (group) => { group.each.setup(() => testUtils.db().withGlobalTransaction()) test('the batch store keeps each poster once; a poster search finds releases by part of the name', async ({ assert }) => { const [g] = await db.table('groups').insert({ name: GROUP, priority: 1 }).returning('id') const [node] = await db.table('nodes').insert({ name: 'poster-node' }).returning('id') const [range] = await db .table('ranges') .insert({ group_id: g.id, start_id: 1, end_id: 1000, next_id: 1, status: 'leased', node_id: node.id, rule_version: 1 }) .returning('id') const post = (n: number, from: string, name: string): Overview => [ n, { 'subject': `[1/1] - "${name}" yEnc (1/1)`, 'from': from, 'date': 'Mon, 05 Oct 2026 10:00:00 +0000', 'message-id': ``, ':bytes': '1000', 'xref': `x ${GROUP}:${n}` }, ] const ix = new RangeIndexer({ group: GROUP, start: 1, end: 1000, rules: { ...DEFAULT_RULES, samplePercent: 0, droppedSignatures: [], priorities: { [GROUP]: 1 } } }) ix.add([post(1, 'Kitchen Cook ', 'Soup.Recipes.2026.rar'), post(2, 'Kitchen Cook ', 'Bread.Recipes.2026.rar'), post(3, 'Gardener ', 'Roses.2026.rar'), post(4, 'Kitchen Helper ', 'Cake.2026.rar')], 5) ix.finish() await BatchStore.store(Number(range.id), Number(node.id), ix.take()) assert.sameMembers((await db.from('posters').select('poster')).map((p) => p.poster), ['Kitchen Cook ', 'Gardener ', 'Kitchen Helper ']) const found = await SearchService.search({ poster: 'kitchen' }) assert.equal(found.total, 3) assert.isTrue(found.releases.every((r) => r.poster?.startsWith('Kitchen'))) // Pages over the posters found, merged in the order asked. const second = await SearchService.search({ poster: 'kitchen', perPage: 2, page: 2 }) assert.equal(second.total, 3) assert.equal(second.releases.length, 1) const all = [...(await SearchService.search({ poster: 'kitchen', perPage: 2, page: 1 })).releases, ...second.releases].map((r) => r.id) assert.sameMembers(all, found.releases.map((r) => r.id)) assert.equal((await SearchService.search({ poster: 'cook', q: 'Bread' })).total, 1) assert.equal((await SearchService.search({ poster: 'nobody' })).total, 0) }) })