From 64da2820d83d071770be4e5ddb43c2f30cce2720 Mon Sep 17 00:00:00 2001 From: Tobias Elod-Zoltan Date: Sun, 15 Nov 2020 19:07:54 +0200 Subject: [PATCH] feat: add basic plugin --- .../src/plugins/FailedTestsInteractive.ts | 52 +++++++++++++++++++ .../__tests__/FailedTestsInteractive.test.js | 28 ++++++++++ packages/jest-core/src/watch.ts | 2 + packages/jest-watcher/src/BaseWatchPlugin.ts | 2 +- 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 packages/jest-core/src/plugins/FailedTestsInteractive.ts create mode 100644 packages/jest-core/src/plugins/__tests__/FailedTestsInteractive.test.js diff --git a/packages/jest-core/src/plugins/FailedTestsInteractive.ts b/packages/jest-core/src/plugins/FailedTestsInteractive.ts new file mode 100644 index 000000000000..5a6f5d8bfa32 --- /dev/null +++ b/packages/jest-core/src/plugins/FailedTestsInteractive.ts @@ -0,0 +1,52 @@ +import type {AggregatedResult, AssertionLocation} from '@jest/test-result'; +import {BaseWatchPlugin, JestHookSubscriber, UsageData} from 'jest-watcher'; + +export default class FailedTestsInteractivePlugin extends BaseWatchPlugin { + private _failedSnapshotTestAssertions?: Array; + + apply(hooks: JestHookSubscriber): void { + hooks.onTestRunComplete(results => { + this._failedSnapshotTestAssertions = this.getFailedSnapshotTestAssertions( + results, + ); + }); + } + + getUsageInfo(): UsageData | null { + if (this._failedSnapshotTestAssertions?.length) { + return {key: 'i', prompt: 'run failing tests interactively'}; + } + + return null; + } + + private getFailedSnapshotTestAssertions( + results: AggregatedResult, + ): Array { + const failedTestPaths: Array = []; + + if ( + // skip if no failed tests + results.numFailedTests === 0 || + // skip if missing test results + !results.testResults || + // skip if unmatched snapshots are present + results.snapshot.unmatched + ) { + return failedTestPaths; + } + + results.testResults.forEach(testResult => { + testResult.testResults.forEach(result => { + if (result.status === 'failed') { + failedTestPaths.push({ + fullName: result.fullName, + path: testResult.testFilePath, + }); + } + }); + }); + + return failedTestPaths; + } +} diff --git a/packages/jest-core/src/plugins/__tests__/FailedTestsInteractive.test.js b/packages/jest-core/src/plugins/__tests__/FailedTestsInteractive.test.js new file mode 100644 index 000000000000..c4fb953eebf7 --- /dev/null +++ b/packages/jest-core/src/plugins/__tests__/FailedTestsInteractive.test.js @@ -0,0 +1,28 @@ +import FailedTestsInteractivePlugin from '../FailedTestsInteractive'; + +const MockFailedResults = { + snapshot: {}, + testResults: [{testResults: [{status: 'failed'}]}], +}; + +describe('FailtedTestsInteractive', () => { + it('returns usage info when failing tests are present', () => { + expect(new FailedTestsInteractivePlugin({}).getUsageInfo()).toBeNull(); + + const activateablePlugin = new FailedTestsInteractivePlugin({}); + let mockCallback; + + activateablePlugin.apply({ + onTestRunComplete: callback => { + mockCallback = callback; + }, + }); + + mockCallback(MockFailedResults); + + expect(activateablePlugin.getUsageInfo()).toEqual({ + key: 'i', + prompt: 'run failing tests interactively', + }); + }); +}); diff --git a/packages/jest-core/src/watch.ts b/packages/jest-core/src/watch.ts index b36c3a0b1332..729526780d53 100644 --- a/packages/jest-core/src/watch.ts +++ b/packages/jest-core/src/watch.ts @@ -36,6 +36,7 @@ import { filterInteractivePlugins, getSortedUsageRows, } from './lib/watchPluginsHelpers'; +import FailedTestsInteractivePlugin from './plugins/FailedTestsInteractive'; import QuitPlugin from './plugins/Quit'; import TestNamePatternPlugin from './plugins/TestNamePattern'; import TestPathPatternPlugin from './plugins/TestPathPattern'; @@ -58,6 +59,7 @@ const {print: preRunMessagePrint} = preRunMessage; let hasExitListener = false; const INTERNAL_PLUGINS = [ + FailedTestsInteractivePlugin, TestPathPatternPlugin, TestNamePatternPlugin, UpdateSnapshotsPlugin, diff --git a/packages/jest-watcher/src/BaseWatchPlugin.ts b/packages/jest-watcher/src/BaseWatchPlugin.ts index 5f59a98a249e..99d3c9e331ac 100644 --- a/packages/jest-watcher/src/BaseWatchPlugin.ts +++ b/packages/jest-watcher/src/BaseWatchPlugin.ts @@ -13,7 +13,7 @@ import type { WatchPlugin, } from './types'; -class BaseWatchPlugin implements WatchPlugin { +abstract class BaseWatchPlugin implements WatchPlugin { protected _stdin: NodeJS.ReadStream; protected _stdout: NodeJS.WriteStream;