diff --git a/config.js b/config.js index 90e7d03b..a1a7f033 100644 --- a/config.js +++ b/config.js @@ -418,7 +418,7 @@ async function readConfigFile(configDir, env) { } /** - * @typedef {{no_external_locking?: boolean, no_locking?: boolean, locking_verbose?: boolean, external_locking_client?: string, external_locking_url?: string, expect_nothing?: boolean}} Config + * @typedef {{no_external_locking?: boolean, no_locking?: boolean, locking_verbose?: boolean, external_locking_client?: string, external_locking_url?: string, expect_nothing?: boolean, filter?: RegExp, forward_console?: boolean, keep_open?: boolean}} Config */ /** diff --git a/main.js b/main.js index dc2add8c..f3a5207c 100644 --- a/main.js +++ b/main.js @@ -99,6 +99,7 @@ async function real_main(options={}) { if (!test_info) return; results = render.craftResults(config, test_info); + console.log(test_info); } await render.doRender(config, results); diff --git a/output.js b/output.js index 30569fad..2fa673d8 100644 --- a/output.js +++ b/output.js @@ -195,7 +195,11 @@ function resultSummary(config, tasks, onTests=false) { return res; } - +/** + * @param {import('./config').Config} config + * @param {import('./runner').RunnerState} state + * @private + */ function finish(config, state) { last_state = null; const {tasks} = state; @@ -213,10 +217,31 @@ function finish(config, state) { print(resultSummary(config, tasks) + '\n'); const expectedToFail = tasks.filter(t => t.expectedToFail && t.status === 'error'); + + let hasHint = false; if (!config.expect_nothing && (expectedToFail.length > 0)) { - let msg = color(config, 'gray', ' Pass in -E/--expect-nothing to ignore expectedToFail declarations.'); - msg += '\n\n'; - print(msg); + const msg = color(config, 'gray', ' Pass in -E/--expect-nothing to ignore expectedToFail declarations.'); + print(msg + '\n'); + hasHint = true; + } + const hasDebug = config.debug || config.forward_console || config.keep_open || config.devtools || config.devtools_preserve; + if ((!config.filter || !hasDebug) && utils.count(tasks, t => t.status === 'error' && (!t.expectedToFail || config.expect_nothing)) > 0) { + let msg = ''; + if (!config.filter && !hasDebug) { + msg = ' Pass in -f/--filter REGEX and -d/--debug to inspect specific tests.'; + } else if (!config.filter) { + msg = ' Pass in -f/--filter REGEX to inspect specific tests.'; + } else if (!hasDebug) { + msg = ' Pass in -d/--debug to inspect tests.'; + } + + if (msg) { + print(color(config, 'gray', msg) + '\n'); + hasHint = true; + } + } + if (hasHint) { + print('\n'); } // Internal self-check diff --git a/tests/debug_tests/config/local.json b/tests/debug_tests/config/local.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/tests/debug_tests/config/local.json @@ -0,0 +1 @@ +{} diff --git a/tests/debug_tests/run b/tests/debug_tests/run new file mode 100755 index 00000000..5c09a827 --- /dev/null +++ b/tests/debug_tests/run @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +const pentf = require('../../index.js'); + +pentf.main({ + rootDir: __dirname, + testsDir: __dirname, +}); diff --git a/tests/debug_tests/test.js b/tests/debug_tests/test.js new file mode 100644 index 00000000..bb6329aa --- /dev/null +++ b/tests/debug_tests/test.js @@ -0,0 +1,8 @@ +async function run() { + throw new Error('fail'); +} + +module.exports = { + run, + description: 'fail' +}; diff --git a/tests/selftest_debug_hint.js b/tests/selftest_debug_hint.js new file mode 100644 index 00000000..3898df92 --- /dev/null +++ b/tests/selftest_debug_hint.js @@ -0,0 +1,39 @@ +const assert = require('assert').strict; +const path = require('path'); +const child_process = require('child_process'); + +async function run() { + // Run in subprocess so that handle exhaustion does not affect this process + const sub_run = path.join(__dirname, 'debug_tests', 'run'); + + async function runPentf(...args) { + return await new Promise((resolve, reject) => { + child_process.execFile( + sub_run, + ['--exit-zero', '--no-screenshots', ...args], + (err, stdout, stderr) => { + if (err) reject(err); + else resolve({stdout, stderr}); + } + ); + }); + } + + let stderr = (await runPentf()).stderr; + assert(/Pass in -f\/--filter REGEX and -d\/--debug to inspect specific tests/.test(stderr)); + + // stderr = (await runPentf('-d')).stderr; + // assert(/Pass in -f\/--filter REGEX to inspect specific tests/.test(stderr)); + + // stderr = (await runPentf('-f test')).stderr; + // assert(/Pass in -d\/--debug to inspect tests/.test(stderr)); + + // stderr = (await runPentf('-f test -d')).stderr; + // assert(!/Pass in/.test(stderr)); +} + +module.exports = { + description: 'Display debug hints', + resources: [], + run, +}; diff --git a/utils.js b/utils.js index 4284aca1..67fbed36 100644 --- a/utils.js +++ b/utils.js @@ -91,6 +91,11 @@ function arange(count) { return Array.from(range(count)); } +/** + * @template T + * @param {T[]} ar + * @param {(item: T) => boolean} filter + */ function count(ar, filter) { let res = 0; for (var el of ar) {