diff --git a/test/contract/p4-schema.test.ts b/test/contract/p4-schema.test.ts index b255b574..aaec2f0c 100644 --- a/test/contract/p4-schema.test.ts +++ b/test/contract/p4-schema.test.ts @@ -83,6 +83,8 @@ const LATEST_RESULT_REQUIRED = [ 'targetUrl', 'failedStepIndex', 'failureKind', + 'verdict', + 'executionStatus', 'summary', ] as const; // `targetUrlSource` (D1) is OPTIONAL — present on backends that shipped the D1 @@ -109,6 +111,15 @@ const FAILURE_KINDS = new Set([ 'unknown', null, ]); +const VERDICTS = new Set(['passed', 'failed', 'blocked', 'cancelled', 'unknown', null]); +const EXECUTION_STATUSES = new Set([ + 'queued', + 'running', + 'completed', + 'cancelled', + 'error', + 'unknown', +]); function expectKeysMatch(value: Record, allowed: Set, label: string) { for (const key of Object.keys(value)) { @@ -178,17 +189,6 @@ function validateTestStepList(value: unknown, label = 'TestStepList'): void { } } -function validateResultSummary(value: unknown, label: string): void { - expect(value, label).toBeTypeOf('object'); - expect(value, label).not.toBeNull(); - const obj = value as Record; - expectKeysMatch(obj, new Set(['passed', 'failed', 'skipped']), label); - for (const k of ['passed', 'failed', 'skipped']) { - expect(typeof obj[k], `${label}.${k}`).toBe('number'); - expect((obj[k] as number) >= 0, `${label}.${k} >= 0`).toBe(true); - } -} - function validateLatestResult(value: unknown, label = 'LatestResult'): void { expect(value, `${label}: must be an object`).toBeTypeOf('object'); expect(value, `${label}: must not be null`).not.toBeNull(); @@ -215,7 +215,9 @@ function validateLatestResult(value: unknown, label = 'LatestResult'): void { expect((obj.failedStepIndex as number) >= 1, `${label}.failedStepIndex >= 1`).toBe(true); } expect(FAILURE_KINDS.has(obj.failureKind), `${label}.failureKind`).toBe(true); - validateResultSummary(obj.summary, `${label}.summary`); + expect(VERDICTS.has(obj.verdict), `${label}.verdict`).toBe(true); + expect(EXECUTION_STATUSES.has(obj.executionStatus), `${label}.executionStatus`).toBe(true); + expect(typeof obj.summary, `${label}.summary`).toBe('string'); } describe('P4 schema contract — fixtures match the OpenAPI shapes', () => { diff --git a/test/mock-backend/fixtures.ts b/test/mock-backend/fixtures.ts index 07225492..0457c54a 100644 --- a/test/mock-backend/fixtures.ts +++ b/test/mock-backend/fixtures.ts @@ -243,7 +243,9 @@ export const latestResultRunningFixture = { targetUrl: FIXTURE_TARGET_URL, failedStepIndex: null, failureKind: null, - summary: { passed: 0, failed: 0, skipped: 0 }, + verdict: null, + executionStatus: 'running' as const, + summary: 'Run is still in progress.', }; export const latestResultPassedFixture = { @@ -260,7 +262,9 @@ export const latestResultPassedFixture = { targetUrlSource: 'run' as const, failedStepIndex: null, failureKind: null, - summary: { passed: 8, failed: 0, skipped: 0 }, + verdict: 'passed' as const, + executionStatus: 'completed' as const, + summary: 'Passed all 8 steps.', }; export const latestResultFailedFixture = { @@ -277,7 +281,9 @@ export const latestResultFailedFixture = { targetUrlSource: 'run' as const, failedStepIndex: 5, failureKind: 'assertion' as const, - summary: { passed: 4, failed: 1, skipped: 0 }, + verdict: 'failed' as const, + executionStatus: 'completed' as const, + summary: 'Failed (assertion) on step 5: expected cart badge to show 1 item, but it was empty.', }; export const failureContextFixture = { @@ -351,7 +357,9 @@ export const failureContextNoAnalysisFixture = { targetUrl: 'https://staging.example.com/', failedStepIndex: 2, failureKind: 'unknown' as const, - summary: { passed: 1, failed: 1, skipped: 0 }, + verdict: 'failed' as const, + executionStatus: 'completed' as const, + summary: 'Failed with no detailed analysis available.', }, steps: [], code: {