From 378a2b306eab94352b29e17cc83a7a30ab129d89 Mon Sep 17 00:00:00 2001 From: Ari Perkkio Date: Tue, 12 Jan 2021 16:56:28 +0200 Subject: [PATCH] feat(result-comparator): include comparison results in config.onComplete --- README.md | 7 +- eslint-remote-tester.config.js | 5 + lib/config/config-templates.ts | 9 +- lib/config/types.d.ts | 7 +- lib/progress-logger/exit-handler.ts | 12 +- test/integration/integration.test.ts | 178 +++++++++++++++++++++++++++ 6 files changed, 210 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ded1f1d8..89f76d13 100644 --- a/README.md +++ b/README.md @@ -111,9 +111,14 @@ module.exports = { * source: string, * error: (string|undefined), * }[]} results Results of the scan, if any + * + * @param {{ + * added: {}[], + * removed: {}[] + * }} comparisonResults Comparison results of the scan, if any * @returns {Promise|void} */ - onComplete: async function onComplete(results) { + onComplete: async function onComplete(results, comparisonResults) { // Extend the process with custom features, e.g. send results to email, create issues to Github... }, }; diff --git a/eslint-remote-tester.config.js b/eslint-remote-tester.config.js index 043c6c07..281b7f0c 100644 --- a/eslint-remote-tester.config.js +++ b/eslint-remote-tester.config.js @@ -49,6 +49,11 @@ module.exports = { * source: string, * error: (string|undefined), * }[]} results Results of the scan, if any + * + * @param {{ + * added: {}[], + * removed: {}[] + * }} comparisonResults Comparison results of the scan, if any * @returns {Promise|void} */ onComplete: undefined, diff --git a/lib/config/config-templates.ts b/lib/config/config-templates.ts index 03041c52..69b55bd8 100644 --- a/lib/config/config-templates.ts +++ b/lib/config/config-templates.ts @@ -81,9 +81,14 @@ export const CONFIGURATION_FILE_TEMPLATE = * source: string, * error: (string|undefined), * }[]} results Results of the scan, if any + * + * @param {{ + * added: {}[], + * removed: {}[] + * }} comparisonResults Comparison results of the scan, if any * @returns {Promise|void} */ - onComplete: async function onComplete(results) { - + onComplete: async function onComplete(results, comparisonResults) { + // Extend the process with custom features, e.g. send results to email, create issues to Github... }, }`; diff --git a/lib/config/types.d.ts b/lib/config/types.d.ts index d1ff117f..8dd7c7b3 100644 --- a/lib/config/types.d.ts +++ b/lib/config/types.d.ts @@ -1,6 +1,6 @@ import { Linter } from 'eslint'; -import { Result } from '@file-client/result-templates'; +import { ComparisonResults, Result } from '@file-client/result-templates'; type AllKeysOptional = { [K in keyof T]?: T[K]; @@ -27,7 +27,10 @@ export interface Config { cache: boolean; timeLimit: number; compare: boolean; - onComplete?: (results: Result[]) => Promise | void; + onComplete?: ( + results: Result[], + comparisonResults: ComparisonResults | null + ) => Promise | void; } type RequiredFields = Pick; diff --git a/lib/progress-logger/exit-handler.ts b/lib/progress-logger/exit-handler.ts index e40ffe2f..5409f1bb 100644 --- a/lib/progress-logger/exit-handler.ts +++ b/lib/progress-logger/exit-handler.ts @@ -4,6 +4,7 @@ import { compareResults, writeComparisonResults, } from '@file-client'; +import { ComparisonResults } from '@file-client/result-templates'; import { RESULT_COMPARISON_FINISHED } from './log-templates'; import { LogMessage } from './types'; @@ -12,12 +13,14 @@ import { LogMessage } from './types'; */ export default async function onExit(): Promise { const messages: LogMessage[] = []; - const results = ResultsStore.getResults(); const errors = []; + const results = ResultsStore.getResults(); + let comparisonResults: ComparisonResults | null = null; + if (config.compare) { try { - const comparisonResults = compareResults(results); + comparisonResults = compareResults(results); ResultsStore.setComparisonResults(comparisonResults); messages.push({ @@ -38,7 +41,10 @@ export default async function onExit(): Promise { if (config.onComplete) { try { - const onCompletePromise = config.onComplete(results); + const onCompletePromise = config.onComplete( + results, + comparisonResults + ); if (onCompletePromise instanceof Promise) { await onCompletePromise; diff --git a/test/integration/integration.test.ts b/test/integration/integration.test.ts index ab2e41a4..4eb97939 100644 --- a/test/integration/integration.test.ts +++ b/test/integration/integration.test.ts @@ -763,4 +763,182 @@ describe('integration', () => { " `); }); + + test('calls onComplete hook with the comparison results', async () => { + await runProductionBuild({ + compare: true, + CI: true, + rulesUnderTesting: [ + 'no-compare-neg-zero', // Used in initial scan, not in second + // 'no-undef', // Used in second scan, not in first + 'no-empty', // Used in both scans + ], + eslintrc: { + root: true, + extends: ['eslint:all'], + }, + }); + + const { output } = await runProductionBuild({ + compare: true, + CI: true, + rulesUnderTesting: [ + // 'no-compare-neg-zero', // Used in initial scan, not in second + 'no-undef', // Used in second scan, not in first + 'no-empty', // Used in both scans + ], + eslintrc: { + root: true, + extends: ['eslint:all'], + }, + onComplete: function onComplete(_, comparisonResults) { + console.log('[TEST-ON-COMPLETE-START]'); + + for (const type of ['added', 'removed']) { + console.log(`[${type.toUpperCase()}]`); + // @ts-ignore + comparisonResults[type].forEach(result => { + Object.entries(result).forEach(([key, value]) => { + const block = `[${key.toUpperCase()}]`; + + console.log('.'); + console.log(block); + console.log(value); + console.log(block); + }); + }); + console.log(`[${type.toUpperCase()}]`); + } + + console.log('[TEST-ON-COMPLETE-END]'); + }, + }); + + const [onCompleteCall] = output + .join('\n') + .match( + /\[TEST-ON-COMPLETE-START\]([\s|\S]*)\[TEST-ON-COMPLETE-END\]/ + )!; + + expect(onCompleteCall).toMatchInlineSnapshot(` + "[TEST-ON-COMPLETE-START] + [ADDED] + . + [REPOSITORY] + eslint-remote-tester-integration-test-target + [REPOSITORY] + . + [REPOSITORYOWNER] + AriPerkkio + [REPOSITORYOWNER] + . + [RULE] + no-undef + [RULE] + . + [MESSAGE] + 'window' is not defined. + [MESSAGE] + . + [PATH] + AriPerkkio/eslint-remote-tester-integration-test-target/expected-to-crash-linter.js + [PATH] + . + [LINK] + https://github.com/AriPerkkio/eslint-remote-tester-integration-test-target/blob/HEAD/expected-to-crash-linter.js#L2-L2 + [LINK] + . + [EXTENSION] + js + [EXTENSION] + . + [SOURCE] + // Identifier.name = attributeForCrashing + window.attributeForCrashing(); + [SOURCE] + . + [ERROR] + undefined + [ERROR] + . + [REPOSITORY] + eslint-remote-tester-integration-test-target + [REPOSITORY] + . + [REPOSITORYOWNER] + AriPerkkio + [REPOSITORYOWNER] + . + [RULE] + no-undef + [RULE] + . + [MESSAGE] + 'bar' is not defined. + [MESSAGE] + . + [PATH] + AriPerkkio/eslint-remote-tester-integration-test-target/index.js + [PATH] + . + [LINK] + https://github.com/AriPerkkio/eslint-remote-tester-integration-test-target/blob/HEAD/index.js#L1-L1 + [LINK] + . + [EXTENSION] + js + [EXTENSION] + . + [SOURCE] + var foo = bar; + if (foo) { + } + var p = { + [SOURCE] + . + [ERROR] + undefined + [ERROR] + [ADDED] + [REMOVED] + . + [REPOSITORY] + eslint-remote-tester-integration-test-target + [REPOSITORY] + . + [REPOSITORYOWNER] + AriPerkkio + [REPOSITORYOWNER] + . + [RULE] + no-compare-neg-zero + [RULE] + . + [MESSAGE] + Do not use the '===' operator to compare against -0. + [MESSAGE] + . + [PATH] + AriPerkkio/eslint-remote-tester-integration-test-target/index.js + [PATH] + . + [LINK] + https://github.com/AriPerkkio/eslint-remote-tester-integration-test-target/blob/HEAD/index.js#L14-L14 + [LINK] + . + [EXTENSION] + js + [EXTENSION] + . + [SOURCE] + }; + p.getName(); + if (foo === -0) { + // prevent no-empty + } + [SOURCE] + [REMOVED] + [TEST-ON-COMPLETE-END]" + `); + }); });