Files
shd.build/src/lib/server/community-moderation.test.ts
T
jb dd84dff055
Validate and deploy production / validate (push) Successful in 23s
Validate and deploy staging / validate (push) Successful in 50s
Validate and deploy production / deploy (push) Failing after 40s
Validate and deploy staging / deploy (push) Failing after 7s
feat: add community publishing and news syndication
2026-08-01 21:42:09 -04:00

207 lines
5.6 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
assessCommunityModeration,
findLocalModerationMatches,
normalizeModerationTerm,
parseModerationTermBatch,
type CommunityModerationPolicy,
} from './community-moderation';
const policy = (
overrides: Partial<CommunityModerationPolicy> = {},
): CommunityModerationPolicy => ({
automatedEnabled: true,
autoPublishClean: true,
holdOnProviderError: true,
scanComments: true,
scanProfiles: true,
scanGuides: true,
scanAvatars: true,
providerModel: 'omni-moderation-latest',
detectPii: true,
maxLinks: 1,
duplicateWindowSeconds: 300,
policyVersion: 1,
thresholds: [
{
category: 'harassment',
enabled: true,
reviewThreshold: 0.5,
priorityThreshold: 0.85,
},
],
terms: [],
...overrides,
});
describe('community moderation policy', () => {
it('holds provider-required Guide content when classification fails', () => {
expect(
assessCommunityModeration({
policy: policy({ automatedEnabled: false, holdOnProviderError: false }),
contentType: 'guide',
providerFlagged: false,
categoryScores: {},
ruleMatches: [],
providerError: 'unavailable',
providerRequired: true,
}).decision,
).toBe('error');
});
it('normalizes configured terms consistently', () => {
expect(normalizeModerationTerm(' Rogue\u00a0Agent ')).toBe('rogue agent');
});
it('parses pasted terms with automatic word and phrase matching', () => {
expect(
parseModerationTermBatch('weapon\nkill, machine gun; assault rifle'),
).toEqual({
terms: [
{ value: 'weapon', normalizedValue: 'weapon', matchMode: 'word' },
{ value: 'kill', normalizedValue: 'kill', matchMode: 'word' },
{
value: 'machine gun',
normalizedValue: 'machine gun',
matchMode: 'phrase',
},
{
value: 'assault rifle',
normalizedValue: 'assault rifle',
matchMode: 'phrase',
},
],
duplicateCount: 0,
});
});
it('deduplicates pasted terms after compatibility and case normalization', () => {
const parsed = parseModerationTermBatch(
'Weapon\nweapon\nMACHINE GUN\nmachine gun',
);
expect(parsed.terms).toEqual([
{ value: 'Weapon', normalizedValue: 'weapon', matchMode: 'word' },
{
value: 'MACHINE GUN',
normalizedValue: 'machine gun',
matchMode: 'phrase',
},
]);
expect(parsed.duplicateCount).toBe(2);
});
it('allows an exact local exception to suppress a matching banned term', () => {
const matches = findLocalModerationMatches(
'Rogue Agent tactics',
'comment',
policy({
detectPii: false,
terms: [
{
id: 'ban',
listType: 'ban',
matchMode: 'phrase',
value: 'Rogue Agent',
normalizedValue: 'rogue agent',
scopes: ['comment'],
enabled: true,
},
{
id: 'allow',
listType: 'allow',
matchMode: 'phrase',
value: 'Rogue Agent',
normalizedValue: 'rogue agent',
scopes: ['comment'],
enabled: true,
},
],
}),
);
expect(matches).toEqual([]);
});
it('finds scoped banned terms, PII, and excessive links', () => {
const matches = findLocalModerationMatches(
'Contact test@example.com about forbidden plans at https://one.test and https://two.test',
'comment',
policy({
terms: [
{
id: 'ban',
listType: 'ban',
matchMode: 'word',
value: 'forbidden',
normalizedValue: 'forbidden',
scopes: ['comment'],
enabled: true,
},
],
}),
);
expect(matches.map((match) => match.kind)).toEqual([
'banned_term',
'pii',
'link_limit',
]);
});
it('routes priority scores ahead of ordinary review scores', () => {
expect(
assessCommunityModeration({
policy: policy(),
contentType: 'comment',
providerFlagged: true,
categoryScores: { harassment: 0.9 },
ruleMatches: [],
}).decision,
).toBe('priority_review');
});
it('holds provider failures under the default fail-closed policy', () => {
expect(
assessCommunityModeration({
policy: policy(),
contentType: 'profile_bio',
providerFlagged: false,
categoryScores: {},
ruleMatches: [],
providerError: 'timeout',
}).decision,
).toBe('error');
});
it('publishes clean content only when auto publication is enabled', () => {
expect(
assessCommunityModeration({
policy: policy(),
contentType: 'comment',
providerFlagged: false,
categoryScores: { harassment: 0.01 },
ruleMatches: [],
}).decision,
).toBe('approved');
expect(
assessCommunityModeration({
policy: policy({ autoPublishClean: false }),
contentType: 'comment',
providerFlagged: false,
categoryScores: { harassment: 0.01 },
ruleMatches: [],
}).decision,
).toBe('review');
});
it('publishes locally clean content when provider scanning is disabled', () => {
expect(
assessCommunityModeration({
policy: policy({ automatedEnabled: false }),
contentType: 'comment',
providerFlagged: false,
categoryScores: {},
ruleMatches: [],
}).decision,
).toBe('approved');
});
});