abuse.test.ts72 lines · main
| 1 | import { describe, expect, test } from 'bun:test'; |
| 2 | |
| 3 | import { |
| 4 | ABUSE_RESOLUTION, |
| 5 | ABUSE_SEVERITY, |
| 6 | type AbuseResolution, |
| 7 | type AbuseSeverity, |
| 8 | } from './abuse.js'; |
| 9 | |
| 10 | describe('ABUSE_SEVERITY', () => { |
| 11 | test('includes the standard set, in a stable order', () => { |
| 12 | // Order is the dropdown order in the dashboard surface; fixing it |
| 13 | // here keeps a refactor from silently re-ordering UI options. |
| 14 | expect([...ABUSE_SEVERITY]).toEqual([ |
| 15 | 'spam', |
| 16 | 'phishing', |
| 17 | 'malware', |
| 18 | 'csam', |
| 19 | 'tos', |
| 20 | 'other', |
| 21 | ]); |
| 22 | }); |
| 23 | |
| 24 | test('every value is a valid AbuseSeverity', () => { |
| 25 | for (const v of ABUSE_SEVERITY) { |
| 26 | const _check: AbuseSeverity = v; |
| 27 | expect(_check).toBe(v); |
| 28 | } |
| 29 | }); |
| 30 | }); |
| 31 | |
| 32 | describe('ABUSE_RESOLUTION', () => { |
| 33 | test('escalates from no-action to banned', () => { |
| 34 | expect([...ABUSE_RESOLUTION]).toEqual(['no_action', 'warned', 'suspended', 'banned']); |
| 35 | }); |
| 36 | |
| 37 | test('every value is a valid AbuseResolution', () => { |
| 38 | for (const v of ABUSE_RESOLUTION) { |
| 39 | const _check: AbuseResolution = v; |
| 40 | expect(_check).toBe(v); |
| 41 | } |
| 42 | }); |
| 43 | }); |
| 44 | |
| 45 | describe('auto-suspension decision', () => { |
| 46 | // Mirrors the rule in resolveAbuseReport — keep them in lock-step so a |
| 47 | // future change to escalation policy surfaces here. |
| 48 | function shouldAutoSuspend(resolution: AbuseResolution, projectId: string | undefined): boolean { |
| 49 | const isEscalation = resolution === 'suspended' || resolution === 'banned'; |
| 50 | return isEscalation && Boolean(projectId); |
| 51 | } |
| 52 | |
| 53 | test('no_action never suspends, even with a projectId', () => { |
| 54 | expect(shouldAutoSuspend('no_action', 'p_abc')).toBe(false); |
| 55 | }); |
| 56 | |
| 57 | test('warned never suspends, even with a projectId', () => { |
| 58 | expect(shouldAutoSuspend('warned', 'p_abc')).toBe(false); |
| 59 | }); |
| 60 | |
| 61 | test('suspended without a projectId is a no-op (admin will set later)', () => { |
| 62 | expect(shouldAutoSuspend('suspended', undefined)).toBe(false); |
| 63 | }); |
| 64 | |
| 65 | test('suspended with a projectId triggers the auto-suspend', () => { |
| 66 | expect(shouldAutoSuspend('suspended', 'p_abc')).toBe(true); |
| 67 | }); |
| 68 | |
| 69 | test('banned with a projectId triggers the auto-suspend', () => { |
| 70 | expect(shouldAutoSuspend('banned', 'p_abc')).toBe(true); |
| 71 | }); |
| 72 | }); |