fix(test runner): allow multiple missing snapshots per test (#10621)
Instead of failing right away, continue test execution but mark the test as failed.
This commit is contained in:
parent
056d0cb5c1
commit
729da65eba
|
|
@ -26,7 +26,7 @@ import { TestInfoImpl, UpdateSnapshots } from '../types';
|
||||||
import { addSuffixToFilePath } from '../util';
|
import { addSuffixToFilePath } from '../util';
|
||||||
|
|
||||||
// Note: we require the pngjs version of pixelmatch to avoid version mismatches.
|
// Note: we require the pngjs version of pixelmatch to avoid version mismatches.
|
||||||
const { PNG } = require(require.resolve('pngjs', { paths: [require.resolve('pixelmatch')] }));
|
const { PNG } = require(require.resolve('pngjs', { paths: [require.resolve('pixelmatch')] })) as typeof import('pngjs');
|
||||||
|
|
||||||
const extensionToMimeType: { [key: string]: string } = {
|
const extensionToMimeType: { [key: string]: string } = {
|
||||||
'dat': 'application/octet-string',
|
'dat': 'application/octet-string',
|
||||||
|
|
@ -36,14 +36,15 @@ const extensionToMimeType: { [key: string]: string } = {
|
||||||
'txt': 'text/plain',
|
'txt': 'text/plain',
|
||||||
};
|
};
|
||||||
|
|
||||||
const GoldenComparators: { [key: string]: any } = {
|
type Comparator = (actualBuffer: Buffer | string, expectedBuffer: Buffer, mimeType: string, options?: any) => { diff?: Buffer; errorMessage?: string; } | null;
|
||||||
|
const GoldenComparators: { [key: string]: Comparator } = {
|
||||||
'application/octet-string': compareBuffersOrStrings,
|
'application/octet-string': compareBuffersOrStrings,
|
||||||
'image/png': compareImages,
|
'image/png': compareImages,
|
||||||
'image/jpeg': compareImages,
|
'image/jpeg': compareImages,
|
||||||
'text/plain': compareText,
|
'text/plain': compareText,
|
||||||
};
|
};
|
||||||
|
|
||||||
function compareBuffersOrStrings(actualBuffer: Buffer | string, expectedBuffer: Buffer, mimeType: string): { diff?: object; errorMessage?: string; } | null {
|
function compareBuffersOrStrings(actualBuffer: Buffer | string, expectedBuffer: Buffer, mimeType: string): { diff?: Buffer; errorMessage?: string; } | null {
|
||||||
if (typeof actualBuffer === 'string')
|
if (typeof actualBuffer === 'string')
|
||||||
return compareText(actualBuffer, expectedBuffer);
|
return compareText(actualBuffer, expectedBuffer);
|
||||||
if (!actualBuffer || !(actualBuffer instanceof Buffer))
|
if (!actualBuffer || !(actualBuffer instanceof Buffer))
|
||||||
|
|
@ -53,7 +54,7 @@ function compareBuffersOrStrings(actualBuffer: Buffer | string, expectedBuffer:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareImages(actualBuffer: Buffer | string, expectedBuffer: Buffer, mimeType: string, options = {}): { diff?: object; errorMessage?: string; } | null {
|
function compareImages(actualBuffer: Buffer | string, expectedBuffer: Buffer, mimeType: string, options = {}): { diff?: Buffer; errorMessage?: string; } | null {
|
||||||
if (!actualBuffer || !(actualBuffer instanceof Buffer))
|
if (!actualBuffer || !(actualBuffer instanceof Buffer))
|
||||||
return { errorMessage: 'Actual result should be a Buffer.' };
|
return { errorMessage: 'Actual result should be a Buffer.' };
|
||||||
|
|
||||||
|
|
@ -69,7 +70,7 @@ function compareImages(actualBuffer: Buffer | string, expectedBuffer: Buffer, mi
|
||||||
return count > 0 ? { diff: PNG.sync.write(diff) } : null;
|
return count > 0 ? { diff: PNG.sync.write(diff) } : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareText(actual: Buffer | string, expectedBuffer: Buffer): { diff?: object; errorMessage?: string; diffExtension?: string; } | null {
|
function compareText(actual: Buffer | string, expectedBuffer: Buffer): { diff?: Buffer; errorMessage?: string; diffExtension?: string; } | null {
|
||||||
if (typeof actual !== 'string')
|
if (typeof actual !== 'string')
|
||||||
return { errorMessage: 'Actual result should be a string' };
|
return { errorMessage: 'Actual result should be a string' };
|
||||||
const expected = expectedBuffer.toString('utf-8');
|
const expected = expectedBuffer.toString('utf-8');
|
||||||
|
|
@ -86,14 +87,13 @@ function compareText(actual: Buffer | string, expectedBuffer: Buffer): { diff?:
|
||||||
export function compare(
|
export function compare(
|
||||||
actual: Buffer | string,
|
actual: Buffer | string,
|
||||||
pathSegments: string[],
|
pathSegments: string[],
|
||||||
snapshotPath: TestInfoImpl['snapshotPath'],
|
testInfo: TestInfoImpl,
|
||||||
outputPath: TestInfoImpl['outputPath'],
|
|
||||||
updateSnapshots: UpdateSnapshots,
|
updateSnapshots: UpdateSnapshots,
|
||||||
withNegateComparison: boolean,
|
withNegateComparison: boolean,
|
||||||
options?: { threshold?: number }
|
options?: { threshold?: number }
|
||||||
): { pass: boolean; message?: string; expectedPath?: string, actualPath?: string, diffPath?: string, mimeType?: string } {
|
): { pass: boolean; message?: string; expectedPath?: string, actualPath?: string, diffPath?: string, mimeType?: string } {
|
||||||
const snapshotFile = snapshotPath(...pathSegments);
|
const snapshotFile = testInfo.snapshotPath(...pathSegments);
|
||||||
const outputFile = outputPath(...pathSegments);
|
const outputFile = testInfo.outputPath(...pathSegments);
|
||||||
const expectedPath = addSuffixToFilePath(outputFile, '-expected');
|
const expectedPath = addSuffixToFilePath(outputFile, '-expected');
|
||||||
const actualPath = addSuffixToFilePath(outputFile, '-actual');
|
const actualPath = addSuffixToFilePath(outputFile, '-actual');
|
||||||
const diffPath = addSuffixToFilePath(outputFile, '-diff');
|
const diffPath = addSuffixToFilePath(outputFile, '-diff');
|
||||||
|
|
@ -116,6 +116,15 @@ export function compare(
|
||||||
console.log(message);
|
console.log(message);
|
||||||
return { pass: true, message };
|
return { pass: true, message };
|
||||||
}
|
}
|
||||||
|
if (updateSnapshots === 'missing') {
|
||||||
|
if (testInfo.status === 'passed')
|
||||||
|
testInfo.status = 'failed';
|
||||||
|
if (!('error' in testInfo))
|
||||||
|
testInfo.error = { value: 'Error: ' + message };
|
||||||
|
else if (testInfo.error?.value)
|
||||||
|
testInfo.error.value += '\nError: ' + message;
|
||||||
|
return { pass: true, message };
|
||||||
|
}
|
||||||
return { pass: false, message };
|
return { pass: false, message };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,7 @@ export function toMatchSnapshot(this: ReturnType<Expect['getState']>, received:
|
||||||
const { pass, message, expectedPath, actualPath, diffPath, mimeType } = compare(
|
const { pass, message, expectedPath, actualPath, diffPath, mimeType } = compare(
|
||||||
received,
|
received,
|
||||||
pathSegments,
|
pathSegments,
|
||||||
testInfo.snapshotPath,
|
testInfo,
|
||||||
testInfo.outputPath,
|
|
||||||
updateSnapshots,
|
updateSnapshots,
|
||||||
withNegateComparison,
|
withNegateComparison,
|
||||||
options
|
options
|
||||||
|
|
|
||||||
|
|
@ -155,22 +155,31 @@ test('should fail on same snapshots with negate matcher', async ({ runInlineTest
|
||||||
expect(result.output).toContain('Expected result should be different from the actual one.');
|
expect(result.output).toContain('Expected result should be different from the actual one.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should write missing expectations locally', async ({ runInlineTest }, testInfo) => {
|
test('should write missing expectations locally twice and continue', async ({ runInlineTest }, testInfo) => {
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
...files,
|
...files,
|
||||||
'a.spec.js': `
|
'a.spec.js': `
|
||||||
const { test } = require('./helper');
|
const { test } = require('./helper');
|
||||||
test('is a test', ({}) => {
|
test('is a test', ({}) => {
|
||||||
expect('Hello world').toMatchSnapshot('snapshot.txt');
|
expect('Hello world').toMatchSnapshot('snapshot.txt');
|
||||||
|
expect('Hello world2').toMatchSnapshot('snapshot2.txt');
|
||||||
|
console.log('Here we are!');
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
}, {}, { CI: '' });
|
});
|
||||||
|
|
||||||
expect(result.exitCode).toBe(1);
|
expect(result.exitCode).toBe(1);
|
||||||
const snapshotOutputPath = testInfo.outputPath('a.spec.js-snapshots/snapshot.txt');
|
expect(result.failed).toBe(1);
|
||||||
expect(result.output).toContain(`${snapshotOutputPath} is missing in snapshots, writing actual`);
|
|
||||||
const data = fs.readFileSync(snapshotOutputPath);
|
const snapshot1OutputPath = testInfo.outputPath('a.spec.js-snapshots/snapshot.txt');
|
||||||
expect(data.toString()).toBe('Hello world');
|
expect(result.output).toContain(`${snapshot1OutputPath} is missing in snapshots, writing actual`);
|
||||||
|
expect(fs.readFileSync(snapshot1OutputPath, 'utf-8')).toBe('Hello world');
|
||||||
|
|
||||||
|
const snapshot2OutputPath = testInfo.outputPath('a.spec.js-snapshots/snapshot2.txt');
|
||||||
|
expect(result.output).toContain(`${snapshot2OutputPath} is missing in snapshots, writing actual`);
|
||||||
|
expect(fs.readFileSync(snapshot2OutputPath, 'utf-8')).toBe('Hello world2');
|
||||||
|
|
||||||
|
expect(result.output).toContain('Here we are!');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('shouldn\'t write missing expectations locally for negated matcher', async ({ runInlineTest }, testInfo) => {
|
test('shouldn\'t write missing expectations locally for negated matcher', async ({ runInlineTest }, testInfo) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue