Files
Slop-detect/tests/status.test.ts
T
2026-09-02 20:38:45 +02:00

75 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { aggregateSummary, createAssetResult, strongestEvidence, verdictFromEvidence } from '../src/shared/status';
import type { Evidence } from '../src/shared/types';
const evidence = (overrides: Partial<Evidence>): Evidence => ({
id: crypto.randomUUID(),
kind: 'c2pa',
strength: 'none',
verdict: 'unknown',
title: 'Evidence',
detail: 'Test evidence',
...overrides
});
describe('evidence precedence', () => {
it('treats invalid credentials as stronger than positive evidence', () => {
const items = [
evidence({ strength: 'verified', verdict: 'ai' }),
evidence({ strength: 'invalid', verdict: 'invalid' })
];
expect(strongestEvidence(items)).toBe('invalid');
expect(verdictFromEvidence(items)).toBe('invalid');
});
it('never turns empty evidence into a human-origin assertion', () => {
const result = createAssetResult('one', 'image', 'Unsigned image', []);
expect(result.verdict).toBe('unknown');
expect(result.strength).toBe('none');
});
});
describe('page aggregation', () => {
const unknownPage = createAssetResult('page', 'page', 'Page', []);
it('reports verified AI when a trusted AI credential is present', () => {
const image = createAssetResult('image', 'image', 'Image', [
evidence({ strength: 'verified', verdict: 'ai' })
]);
expect(aggregateSummary(unknownPage, [image], [], 1, 0).status).toBe('verified-ai');
});
it('reports mixed provenance when AI and non-AI assertions coexist', () => {
const ai = createAssetResult('ai', 'image', 'AI', [evidence({ strength: 'verified', verdict: 'ai' })]);
const camera = createAssetResult('camera', 'image', 'Camera', [
evidence({ strength: 'verified', verdict: 'not-ai-asserted' })
]);
expect(aggregateSummary(unknownPage, [ai, camera], [], 2, 0).status).toBe('mixed-provenance');
});
it('prioritises invalid credentials', () => {
const invalid = createAssetResult('bad', 'image', 'Invalid', [
evidence({ strength: 'invalid', verdict: 'invalid' })
]);
expect(aggregateSummary(unknownPage, [invalid], [], 1, 0).status).toBe('invalid-credential');
});
it('reports suspicion without asserting AI authorship when heuristic clues cross the threshold', () => {
const suspectedPage = createAssetResult('page', 'page', 'Page', [
evidence({ kind: 'heuristic', strength: 'clue', category: 'visual', score: 3 }),
evidence({ kind: 'heuristic', strength: 'clue', category: 'layout', score: 2 })
]);
const summary = aggregateSummary(suspectedPage, [], [], 0, 0, 6);
expect(summary.status).toBe('heuristic-suspected');
expect(suspectedPage.verdict).toBe('unknown');
expect(summary.heuristicScore).toBe(6);
});
it('does not elevate a single weak style clue', () => {
const page = createAssetResult('page', 'page', 'Page', [
evidence({ kind: 'heuristic', strength: 'clue', category: 'visual', score: 2 })
]);
expect(aggregateSummary(page, [], [], 0, 0, 6).status).toBe('no-supported-evidence');
});
});