v0.3.2
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user