From 77a479b58a777a436de1a937054be4fb8246e471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 22 Jun 2020 16:19:33 +0200 Subject: [PATCH 1/2] test(cli): add debug logs to snapshot-matcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make it easier to troubleshoot snapshot-matcher related problems, especially when running the tests in parallel. Signed-off-by: Miroslav Bajtoš --- packages/cli/test/snapshot-matcher.js | 31 ++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/cli/test/snapshot-matcher.js b/packages/cli/test/snapshot-matcher.js index 17b841d3f6a5..6351e20339fe 100644 --- a/packages/cli/test/snapshot-matcher.js +++ b/packages/cli/test/snapshot-matcher.js @@ -16,8 +16,11 @@ move this file to a standalone package so that all Mocha users can use it. const chalk = require('chalk'); const assert = require('assert'); +const debug = require('debug')('test:snapshot-matcher'); const path = require('path'); +const root = process.cwd(); + module.exports = { initializeSnapshots, }; @@ -43,6 +46,22 @@ module.exports = { * ``` */ function initializeSnapshots(snapshotDir) { + if (debug.enabled) { + const stack = new Error().stack + .split(/\n/g) + // Remove the error message and the top stack frame pointing to ourselves + // and pick three frames (max), that should be enough to identify + // which test file called us. + .slice(2, 5) + .map(f => `\n${f}`) + .join(); + debug( + 'Initializing snapshot matcher, storing snapshots in %s%s', + snapshotDir, + stack, + ); + } + let currentTest; let snapshotErrors = false; @@ -101,8 +120,10 @@ function matchSnapshot(snapshotDir, currentTest, actualValue) { const key = buildSnapshotKey(currentTest); if (!(key in snapshotData)) { + const shortFile = path.relative(root, snapshotFile); throw new Error( - `No snapshot found for ${JSON.stringify(key)}.\n` + + `No snapshot found in ${JSON.stringify(shortFile)} ` + + `for ${JSON.stringify(key)}.\n` + 'Run the tests with `UPDATE_SNAPSHOTS=1` environment variable ' + 'to create and update snapshot files.', ); @@ -129,6 +150,13 @@ function recordSnapshot(snapshots, currentTest, actualValue) { const key = buildSnapshotKey(currentTest); const testFile = currentTest.file; + if (debug.enabled) { + debug( + 'Recording snapshot %j for test file %j', + key, + path.relative(root, testFile), + ); + } if (!snapshots[testFile]) snapshots[testFile] = Object.create(null); snapshots[testFile][key] = actualValue; } @@ -211,6 +239,7 @@ function writeSnapshotData(snapshotFile, snapshots) { const content = header + entries.join('\n'); mkdirp.sync(path.dirname(snapshotFile)); + debug('Updating snapshot file %j', path.relative(root, snapshotFile)); return writeFileAtomic(snapshotFile, content, {encoding: 'utf-8'}); } From b0d4fe1e842978f54d4ad4ddfea988e44085b0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 22 Jun 2020 16:24:37 +0200 Subject: [PATCH 2/2] test(cli): add a test suite for snapshot-matcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test suite with a shared test suite to verify snapshot-matcher's support for this advanced test organization. This scenario is tricky to get right when running tests in parallel. Signed-off-by: Miroslav Bajtoš --- .../suite-first-run.integration.snapshots.js | 17 +++++++++++++++ .../suite-second-run.integration.snapshots.js | 17 +++++++++++++++ .../snapshot-matcher/common.suite.js | 21 +++++++++++++++++++ .../suite-first-run.integration.js | 17 +++++++++++++++ .../suite-second-run.integration.js | 17 +++++++++++++++ 5 files changed, 89 insertions(+) create mode 100644 packages/cli/snapshots/integration/snapshot-matcher/suite-first-run.integration.snapshots.js create mode 100644 packages/cli/snapshots/integration/snapshot-matcher/suite-second-run.integration.snapshots.js create mode 100644 packages/cli/test/integration/snapshot-matcher/common.suite.js create mode 100644 packages/cli/test/integration/snapshot-matcher/suite-first-run.integration.js create mode 100644 packages/cli/test/integration/snapshot-matcher/suite-second-run.integration.js diff --git a/packages/cli/snapshots/integration/snapshot-matcher/suite-first-run.integration.snapshots.js b/packages/cli/snapshots/integration/snapshot-matcher/suite-first-run.integration.snapshots.js new file mode 100644 index 000000000000..e8f724f91d11 --- /dev/null +++ b/packages/cli/snapshots/integration/snapshot-matcher/suite-first-run.integration.snapshots.js @@ -0,0 +1,17 @@ +// IMPORTANT +// This snapshot file is auto-generated, but designed for humans. +// It should be checked into source control and tracked carefully. +// Re-generate by setting UPDATE_SNAPSHOTS=1 and running tests. +// Make sure to inspect the changes in the snapshots below. +// Do not ignore changes! + +'use strict'; + +exports[`snapshot-matcher first case matches snapshot 1`] = ` +first case +`; + + +exports[`snapshot-matcher first case shared test matches snapshot 1`] = ` +common result +`; diff --git a/packages/cli/snapshots/integration/snapshot-matcher/suite-second-run.integration.snapshots.js b/packages/cli/snapshots/integration/snapshot-matcher/suite-second-run.integration.snapshots.js new file mode 100644 index 000000000000..c16c599ebdc5 --- /dev/null +++ b/packages/cli/snapshots/integration/snapshot-matcher/suite-second-run.integration.snapshots.js @@ -0,0 +1,17 @@ +// IMPORTANT +// This snapshot file is auto-generated, but designed for humans. +// It should be checked into source control and tracked carefully. +// Re-generate by setting UPDATE_SNAPSHOTS=1 and running tests. +// Make sure to inspect the changes in the snapshots below. +// Do not ignore changes! + +'use strict'; + +exports[`snapshot-matcher second case matches snapshot 1`] = ` +second case +`; + + +exports[`snapshot-matcher second case shared test matches snapshot 1`] = ` +common result +`; diff --git a/packages/cli/test/integration/snapshot-matcher/common.suite.js b/packages/cli/test/integration/snapshot-matcher/common.suite.js new file mode 100644 index 000000000000..5c346fff2929 --- /dev/null +++ b/packages/cli/test/integration/snapshot-matcher/common.suite.js @@ -0,0 +1,21 @@ +// Copyright IBM Corp. 2018,2020. All Rights Reserved. +// Node module: @loopback/cli +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; + +// A shared test suite executed by "suite-first-run.integration.js" +// and "suite-second-run.integration.js" +const {expectToMatchSnapshot} = require('../../snapshots'); + +/** + * Execute this method from inside a `describe()` block in your test file. + */ +exports.commonTestSuite = function () { + describe('shared test', () => { + it('matches snapshot', function () { + expectToMatchSnapshot('common result'); + }); + }); +}; diff --git a/packages/cli/test/integration/snapshot-matcher/suite-first-run.integration.js b/packages/cli/test/integration/snapshot-matcher/suite-first-run.integration.js new file mode 100644 index 000000000000..42dcde6000b2 --- /dev/null +++ b/packages/cli/test/integration/snapshot-matcher/suite-first-run.integration.js @@ -0,0 +1,17 @@ +// Copyright IBM Corp. 2018,2020. All Rights Reserved. +// Node module: @loopback/cli +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; + +const {expectToMatchSnapshot} = require('../../snapshots'); +const {commonTestSuite} = require('./common.suite'); + +describe('snapshot-matcher first case', () => { + commonTestSuite(); + + it('matches snapshot', () => { + expectToMatchSnapshot('first case'); + }); +}); diff --git a/packages/cli/test/integration/snapshot-matcher/suite-second-run.integration.js b/packages/cli/test/integration/snapshot-matcher/suite-second-run.integration.js new file mode 100644 index 000000000000..019c8c018c64 --- /dev/null +++ b/packages/cli/test/integration/snapshot-matcher/suite-second-run.integration.js @@ -0,0 +1,17 @@ +// Copyright IBM Corp. 2018,2020. All Rights Reserved. +// Node module: @loopback/cli +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; + +const {expectToMatchSnapshot} = require('../../snapshots'); +const {commonTestSuite} = require('./common.suite'); + +describe('snapshot-matcher second case', () => { + commonTestSuite(); + + it('matches snapshot', () => { + expectToMatchSnapshot('second case'); + }); +});