test(16-01): add failing tests for selectOriginalMessage (EVID-02)
RED: covers all three selection tiers plus ambiguous/no-eml/empty edge cases. lib/services/eml-parser.ts does not exist yet — tests fail to resolve the module import.
This commit is contained in:
parent
0f4dc1fc20
commit
2fde1156da
2 changed files with 128 additions and 0 deletions
71
lib/services/eml-parser.fixtures.ts
Normal file
71
lib/services/eml-parser.fixtures.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Synthetic fixtures for eml-parser.test.ts. Nothing here is real customer
|
||||
* content — all addresses, subjects, and bodies are invented for testing
|
||||
* only (per this milestone's explicit synthetic-fixture-only constraint).
|
||||
*/
|
||||
|
||||
import type { Attachment } from '@/lib/types/autotask';
|
||||
|
||||
function makeAttachment(overrides: Partial<Attachment> & { id: number }): Attachment {
|
||||
return {
|
||||
attachmentType: 'FILE_ATTACHMENT',
|
||||
fullPath: '',
|
||||
title: '',
|
||||
publish: 1,
|
||||
contentType: 'message/rfc822',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
/** Tier 1: exact `rfc.eml` present among message/rfc822 attachments (Microsoft "Report Message" flow). */
|
||||
export const RFC_EML_TIER_ATTACHMENTS: Attachment[] = [
|
||||
makeAttachment({ id: 1, title: 'rfc.eml', fullPath: 'rfc.eml' }),
|
||||
makeAttachment({ id: 2, title: 'OriginatingEmail.eml', fullPath: 'OriginatingEmail.eml' }),
|
||||
];
|
||||
|
||||
/** Same tier, but with mixed case to verify case-insensitive matching. */
|
||||
export const RFC_EML_TIER_ATTACHMENTS_UPPERCASE: Attachment[] = [
|
||||
makeAttachment({ id: 1, title: 'RFC.EML', fullPath: 'RFC.EML' }),
|
||||
makeAttachment({ id: 2, title: 'OriginatingEmail.EML', fullPath: 'OriginatingEmail.EML' }),
|
||||
];
|
||||
|
||||
/** Tier 2: KnowBe4 PhishER flow — versioned filename, no literal rfc.eml. */
|
||||
export const KNOWBE4_TIER_ATTACHMENTS: Attachment[] = [
|
||||
makeAttachment({
|
||||
id: 10,
|
||||
title: 'phish_alert_sp2_2.0.0.0.eml',
|
||||
fullPath: 'phish_alert_sp2_2.0.0.0.eml',
|
||||
}),
|
||||
makeAttachment({ id: 11, title: 'OriginatingEmail.eml', fullPath: 'OriginatingEmail.eml' }),
|
||||
];
|
||||
|
||||
/** Tier 3: only OriginatingEmail.eml present (older tickets, majority-case fallback). */
|
||||
export const ORIGINATING_ONLY_ATTACHMENTS: Attachment[] = [
|
||||
makeAttachment({ id: 20, title: 'OriginatingEmail.eml', fullPath: 'OriginatingEmail.eml' }),
|
||||
];
|
||||
|
||||
/** Ambiguous: two non-OriginatingEmail message/rfc822 candidates, no rfc.eml — falls back to OriginatingEmail.eml. */
|
||||
export const AMBIGUOUS_WITH_FALLBACK_ATTACHMENTS: Attachment[] = [
|
||||
makeAttachment({ id: 30, title: 'weird_name_1.eml', fullPath: 'weird_name_1.eml' }),
|
||||
makeAttachment({ id: 31, title: 'weird_name_2.eml', fullPath: 'weird_name_2.eml' }),
|
||||
makeAttachment({ id: 32, title: 'OriginatingEmail.eml', fullPath: 'OriginatingEmail.eml' }),
|
||||
];
|
||||
|
||||
/** Ambiguous with no fallback available — selectOriginalMessage should return null. */
|
||||
export const AMBIGUOUS_NO_FALLBACK_ATTACHMENTS: Attachment[] = [
|
||||
makeAttachment({ id: 40, title: 'weird_name_1.eml', fullPath: 'weird_name_1.eml' }),
|
||||
makeAttachment({ id: 41, title: 'weird_name_2.eml', fullPath: 'weird_name_2.eml' }),
|
||||
];
|
||||
|
||||
/** No .eml attachments at all — selectOriginalMessage should return null. */
|
||||
export const NO_EML_ATTACHMENTS: Attachment[] = [
|
||||
makeAttachment({
|
||||
id: 50,
|
||||
title: 'screenshot.png',
|
||||
fullPath: 'screenshot.png',
|
||||
contentType: 'image/png',
|
||||
}),
|
||||
];
|
||||
|
||||
/** Empty attachment list. */
|
||||
export const EMPTY_ATTACHMENTS: Attachment[] = [];
|
||||
57
lib/services/eml-parser.test.ts
Normal file
57
lib/services/eml-parser.test.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { selectOriginalMessage } from './eml-parser';
|
||||
import {
|
||||
RFC_EML_TIER_ATTACHMENTS,
|
||||
RFC_EML_TIER_ATTACHMENTS_UPPERCASE,
|
||||
KNOWBE4_TIER_ATTACHMENTS,
|
||||
ORIGINATING_ONLY_ATTACHMENTS,
|
||||
AMBIGUOUS_WITH_FALLBACK_ATTACHMENTS,
|
||||
AMBIGUOUS_NO_FALLBACK_ATTACHMENTS,
|
||||
NO_EML_ATTACHMENTS,
|
||||
EMPTY_ATTACHMENTS,
|
||||
} from './eml-parser.fixtures';
|
||||
|
||||
describe('selectOriginalMessage', () => {
|
||||
it('selects rfc.eml over OriginatingEmail.eml when both are present', () => {
|
||||
const result = selectOriginalMessage(RFC_EML_TIER_ATTACHMENTS);
|
||||
expect(result?.id).toBe(1);
|
||||
expect(result?.title).toBe('rfc.eml');
|
||||
});
|
||||
|
||||
it('selects rfc.eml case-insensitively (RFC.EML / OriginatingEmail.EML)', () => {
|
||||
const result = selectOriginalMessage(RFC_EML_TIER_ATTACHMENTS_UPPERCASE);
|
||||
expect(result?.id).toBe(1);
|
||||
});
|
||||
|
||||
it('selects the KnowBe4-named attachment when OriginatingEmail.eml is also present', () => {
|
||||
const result = selectOriginalMessage(KNOWBE4_TIER_ATTACHMENTS);
|
||||
expect(result?.id).toBe(10);
|
||||
expect(result?.title).toBe('phish_alert_sp2_2.0.0.0.eml');
|
||||
});
|
||||
|
||||
it('falls back to OriginatingEmail.eml when it is the only attachment', () => {
|
||||
const result = selectOriginalMessage(ORIGINATING_ONLY_ATTACHMENTS);
|
||||
expect(result?.id).toBe(20);
|
||||
expect(result?.title).toBe('OriginatingEmail.eml');
|
||||
});
|
||||
|
||||
it('falls back to OriginatingEmail.eml when there are 2+ ambiguous non-OriginatingEmail candidates', () => {
|
||||
const result = selectOriginalMessage(AMBIGUOUS_WITH_FALLBACK_ATTACHMENTS);
|
||||
expect(result?.id).toBe(32);
|
||||
expect(result?.title).toBe('OriginatingEmail.eml');
|
||||
});
|
||||
|
||||
it('returns null when candidates are ambiguous and no OriginatingEmail.eml fallback exists', () => {
|
||||
const result = selectOriginalMessage(AMBIGUOUS_NO_FALLBACK_ATTACHMENTS);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null (not throws) for a list with no .eml / message-rfc822 attachments', () => {
|
||||
expect(() => selectOriginalMessage(NO_EML_ATTACHMENTS)).not.toThrow();
|
||||
expect(selectOriginalMessage(NO_EML_ATTACHMENTS)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for an empty attachment list', () => {
|
||||
expect(selectOriginalMessage(EMPTY_ATTACHMENTS)).toBeNull();
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue