atproto/packages/ozone/tests/get-reporter-stats.test.ts
Foysal Ahamed b41ff4b4e3
Add reporter_stats materialized view and endpoint to fetch reporter stats (#3509)
*  Add reporter_stats materialized view and endpoint to fetch reporter stats

* 🚨 Fix linter issues

*  Change reporter stats query from materialized view to on demand select

* Add "createdAt" as part of the index

---------

Co-authored-by: Matthieu Sieben <matthieu.sieben@gmail.com>
Co-authored-by: Matthieu Sieben <matthieusieben@users.noreply.github.com>
2025-02-17 22:17:43 +01:00

118 lines
3.1 KiB
TypeScript

import {
ComAtprotoModerationDefs,
ToolsOzoneModerationDefs,
} from '@atproto/api'
import {
ModeratorClient,
SeedClient,
TestNetwork,
basicSeed,
} from '@atproto/dev-env'
describe('reporter-stats', () => {
let network: TestNetwork
let sc: SeedClient
let modClient: ModeratorClient
beforeAll(async () => {
network = await TestNetwork.create({
dbPostgresSchema: 'ozone_reporter_stats',
ozone: {
dbMaterializedViewRefreshIntervalMs: 1000,
},
})
sc = network.getSeedClient()
modClient = network.ozone.getModClient()
await basicSeed(sc)
await network.processAll()
})
afterAll(async () => {
await network.close()
})
const getReporterStats = async (
did: string,
): Promise<ToolsOzoneModerationDefs.ReporterStats | undefined> => {
const { stats } = await modClient.getReporterStats([did])
return stats[0]
}
it('updates reporter stats based on actions', async () => {
const bobsPostSubject = {
$type: 'com.atproto.repo.strongRef',
uri: sc.posts[sc.dids.bob][1].ref.uriStr,
cid: sc.posts[sc.dids.bob][1].ref.cidStr,
}
const carolsAccountSubject = {
$type: 'com.atproto.admin.defs#repoRef',
did: sc.dids.carol,
}
await Promise.all([
sc.createReport({
reportedBy: sc.dids.alice,
reasonType: ComAtprotoModerationDefs.REASONMISLEADING,
reason: 'misleading',
subject: bobsPostSubject,
}),
sc.createReport({
reportedBy: sc.dids.alice,
reasonType: ComAtprotoModerationDefs.REASONOTHER,
reason: 'test',
subject: bobsPostSubject,
}),
sc.createReport({
reportedBy: sc.dids.alice,
reasonType: ComAtprotoModerationDefs.REASONMISLEADING,
reason: 'misleading',
subject: carolsAccountSubject,
}),
])
await network.processAll()
const statsAfterReport = await getReporterStats(sc.dids.alice)
expect(statsAfterReport).toMatchObject({
did: sc.dids.alice,
accountReportCount: 1,
recordReportCount: 2,
reportedAccountCount: 1,
reportedRecordCount: 1,
takendownAccountCount: 0,
takendownRecordCount: 0,
labeledAccountCount: 0,
labeledRecordCount: 0,
})
await Promise.all([
modClient.performTakedown({
subject: bobsPostSubject,
policies: ['trolling'],
}),
modClient.emitEvent({
subject: carolsAccountSubject,
event: {
$type: 'tools.ozone.moderation.defs#modEventLabel',
createLabelVals: ['spam'],
negateLabelVals: [],
},
}),
])
await network.processAll()
await new Promise((resolve) => setTimeout(resolve, 1000))
const statsAfterAction = await getReporterStats(sc.dids.alice)
expect(statsAfterAction).toMatchObject({
did: sc.dids.alice,
accountReportCount: 1,
recordReportCount: 2,
reportedAccountCount: 1,
reportedRecordCount: 1,
takendownAccountCount: 0,
takendownRecordCount: 1,
labeledAccountCount: 1,
labeledRecordCount: 0,
})
})
})