90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { validateEvent } from '@main/services/telemetryEvents.js';
|
|
|
|
describe('validateEvent — happy path', () => {
|
|
it('accepts capture event', () => {
|
|
const e = validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'capture',
|
|
payload: { noteId: 'n1', rawTextLength: 12, hasMedia: false }
|
|
});
|
|
expect(e.kind).toBe('capture');
|
|
});
|
|
|
|
it('accepts ai_succeeded event', () => {
|
|
const e = validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'ai_succeeded',
|
|
payload: { noteId: 'n1', durationMs: 1234, attempts: 0 }
|
|
});
|
|
expect(e.kind).toBe('ai_succeeded');
|
|
});
|
|
|
|
it('accepts ai_failed event with reason enum', () => {
|
|
const e = validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'ai_failed',
|
|
payload: { noteId: 'n1', reason: 'unreachable', attempts: 3 }
|
|
});
|
|
expect(e.kind).toBe('ai_failed');
|
|
});
|
|
});
|
|
|
|
describe('validateEvent — privacy invariant', () => {
|
|
it('rejects payload with rawText leak', () => {
|
|
expect(() => validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'capture',
|
|
payload: { noteId: 'n1', rawTextLength: 5, hasMedia: false, rawText: 'leak' }
|
|
})).toThrow();
|
|
});
|
|
|
|
it('rejects payload with title leak', () => {
|
|
expect(() => validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'ai_succeeded',
|
|
payload: { noteId: 'n1', durationMs: 1, attempts: 0, title: 'leak' }
|
|
})).toThrow();
|
|
});
|
|
|
|
it('rejects payload with summary leak', () => {
|
|
expect(() => validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'ai_succeeded',
|
|
payload: { noteId: 'n1', durationMs: 1, attempts: 0, summary: 'leak' }
|
|
})).toThrow();
|
|
});
|
|
|
|
it('rejects payload with userIntent leak', () => {
|
|
expect(() => validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'capture',
|
|
payload: { noteId: 'n1', rawTextLength: 5, hasMedia: false, userIntent: 'leak' }
|
|
})).toThrow();
|
|
});
|
|
|
|
it('rejects payload with tag name leak', () => {
|
|
expect(() => validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'capture',
|
|
payload: { noteId: 'n1', rawTextLength: 5, hasMedia: false, tagNames: ['일정'] }
|
|
})).toThrow();
|
|
});
|
|
|
|
it('rejects unknown reason in ai_failed', () => {
|
|
expect(() => validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'ai_failed',
|
|
payload: { noteId: 'n1', reason: 'unicorn', attempts: 1 }
|
|
})).toThrow();
|
|
});
|
|
|
|
it('rejects unknown event kind', () => {
|
|
expect(() => validateEvent({
|
|
ts: '2026-05-01T00:00:00.000Z',
|
|
kind: 'mystery',
|
|
payload: {}
|
|
})).toThrow();
|
|
});
|
|
});
|