From 2185693dc1557b723c4f4dfd03d5de2c20f49466 Mon Sep 17 00:00:00 2001 From: mefellows Date: Fri, 2 Dec 2022 11:12:40 +1100 Subject: [PATCH] feat: add support for rendering plugin content mismatches --- .../v4/plugins/test/matt.consumer.spec.ts | 6 +- src/v3/display.ts | 74 +++++++++++++++++-- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/examples/v4/plugins/test/matt.consumer.spec.ts b/examples/v4/plugins/test/matt.consumer.spec.ts index 753baae4d..be0c9830e 100644 --- a/examples/v4/plugins/test/matt.consumer.spec.ts +++ b/examples/v4/plugins/test/matt.consumer.spec.ts @@ -30,7 +30,7 @@ describe('Plugins - Matt Protocol', () => { .uponReceiving('an HTTP request to /matt') .usingPlugin({ plugin: 'matt', - version: '0.0.2', + version: '0.0.5', }) .withRequest('POST', '/matt', (builder) => { builder.pluginContents('application/matt', mattRequest); @@ -73,12 +73,12 @@ describe('Plugins - Matt Protocol', () => { .addSynchronousInteraction('a MATT message') .usingPlugin({ plugin: 'matt', - version: '0.0.2', + version: '0.0.5', }) .withPluginContents(mattMessage, 'application/matt') .startTransport('matt', HOST) .executeTest(async (tc) => { - const message = await sendMattMessageTCP('hello', HOST, tc.port); + const message = await sendMattMessageTCP('hellotcp', HOST, tc.port); expect(message).to.eq('tcpworld'); }); }); diff --git a/src/v3/display.ts b/src/v3/display.ts index 75d2f3ef2..db943d044 100644 --- a/src/v3/display.ts +++ b/src/v3/display.ts @@ -6,6 +6,8 @@ import { RequestMismatch, MatchingResultRequestNotFound, MatchingResultMissingRequest, + MatchingResultPlugin, + PluginContentMismatch, } from '@pact-foundation/pact-core/src/consumer/index'; export function displayQuery(query: Record): string { @@ -60,12 +62,29 @@ export function filterMissingFeatureFlag( mismatches: MatchingResult[] ): MatchingResult[] { if (process.env.PACT_EXPERIMENTAL_FEATURE_ALLOW_MISSING_REQUESTS) { - return mismatches.filter((m) => m.type !== 'request-mismatch'); + return mismatches.filter( + (m) => !isMismatchingResultPlugin(m) && m.type !== 'request-mismatch' + ); } return mismatches; } export function printMismatch(m: Mismatch): string { + if (isPluginContentMismatch(m)) { + const s = [ + `\t${m.path}: ${m.mismatch}\n`, + m.mismatch + ? '' + : `\t\tExpected '${m.expected}', got: '${m.actual}${m.diff}'`, + ]; + if (m.diff) { + s.push(`\t\tDiff:`); + s.push(`\t\t\t${m.diff}`); + } + + return s.join('\n\n'); + } + switch (m.type) { case 'MethodMismatch': return `Expected ${m.expected}, got: ${m.actual}`; @@ -74,6 +93,11 @@ export function printMismatch(m: Mismatch): string { } } +export function printMismatches(mismatches: Mismatch[]): string { + const errors = mismatches.map((m) => printMismatch(m)); + return errors.join('\n'); +} + export function generateMockServerError( mismatches: MatchingResult[], indent: string @@ -81,15 +105,18 @@ export function generateMockServerError( return [ 'Mock server failed with the following mismatches:', ...mismatches.map((mismatch, i) => { + if (isMismatchingResultPlugin(mismatch)) { + return printMismatches(mismatch.mismatches); + } if (mismatch.type === 'request-mismatch') { return `\n${indent}${i}) The following request was incorrect: \n - ${indent}${mismatch.method} ${mismatch.path} - ${mismatch.mismatches - ?.map( - (d, j) => - `\n${indent}${indent}${indent} 1.${j} ${printMismatch(d)}` - ) - .join('')}`; + ${indent}${mismatch.method} ${mismatch.path} + ${mismatch.mismatches + ?.map( + (d, j) => + `\n${indent}${indent}${indent} 1.${j} ${printMismatch(d)}` + ) + .join('')}`; } if (mismatch.type === 'request-not-found') { return `\n${indent}${i}) The following request was not expected: ${displayRequest( @@ -107,3 +134,34 @@ export function generateMockServerError( }), ].join('\n'); } + +// TODO: update Matching in the rust core to have a `type` property +// to avoid having to do this check! + +const isMismatchingResultPlugin = ( + obj: MatchingResult +): obj is MatchingResultPlugin => { + if ( + (obj as MatchingResultPlugin).error !== undefined && + (obj as MatchingResultPlugin).mismatches + ) + return true; + return false; +}; + +const isPluginContentMismatch = ( + obj: Mismatch +): obj is PluginContentMismatch => { + const cast = obj as PluginContentMismatch; + + if ( + cast.diff !== undefined || + (cast.expected !== undefined && + cast.actual !== undefined && + cast.mismatch !== undefined && + cast.path !== undefined) + ) + return true; + + return false; +};