sxy-test-runner 2.3.19 → 2.3.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +147 -6
- package/LICENSE +21 -0
- package/dist/cli/help.js +3 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/init.js +6 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/lib/agentReport.d.ts +16 -0
- package/dist/cli/lib/agentReport.js +117 -0
- package/dist/cli/lib/agentReport.js.map +1 -0
- package/dist/cli/lib/defaultConfig.js +3 -1
- package/dist/cli/lib/defaultConfig.js.map +1 -1
- package/dist/cli/lib/doUserSetup.js +4 -0
- package/dist/cli/lib/doUserSetup.js.map +1 -1
- package/dist/cli/lib/failureEntries.d.ts +9 -0
- package/dist/cli/lib/failureEntries.js +42 -0
- package/dist/cli/lib/failureEntries.js.map +1 -0
- package/dist/cli/lib/failureLines.d.ts +3 -0
- package/dist/cli/lib/failureLines.js +33 -0
- package/dist/cli/lib/failureLines.js.map +1 -0
- package/dist/cli/lib/listenToUser.d.ts +2 -1
- package/dist/cli/lib/listenToUser.js +6 -3
- package/dist/cli/lib/listenToUser.js.map +1 -1
- package/dist/cli/lib/reRunManager.d.ts +2 -1
- package/dist/cli/lib/reRunManager.js +9 -2
- package/dist/cli/lib/reRunManager.js.map +1 -1
- package/dist/cli/lib/runTests.js +65 -14
- package/dist/cli/lib/runTests.js.map +1 -1
- package/dist/cli/lib/statusFile.d.ts +12 -0
- package/dist/cli/lib/statusFile.js +60 -0
- package/dist/cli/lib/statusFile.js.map +1 -0
- package/dist/cli/lib/validateConfig.js +7 -0
- package/dist/cli/lib/validateConfig.js.map +1 -1
- package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js +24 -23
- package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js.map +1 -1
- package/dist/cli/once.js +3 -0
- package/dist/cli/once.js.map +1 -1
- package/dist/cli/watch.js +48 -13
- package/dist/cli/watch.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +47 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReRunManager } from './reRunManager.js';
|
|
2
2
|
import { RunTestsPromise } from './runTests.js';
|
|
3
|
+
import type { OutFn } from '../../types.js';
|
|
3
4
|
export type RerunTestsFactory = (testFiles: Set<string>) => () => RunTestsPromise;
|
|
4
|
-
export declare function listenToUser(rerunManager: ReRunManager, rerunTestsCallback: RerunTestsFactory, ttyActionsOnKeypress: boolean | undefined, initialTestRun: Promise<boolean | null> | null, input?: NodeJS.ReadStream): Promise<void>;
|
|
5
|
+
export declare function listenToUser(rerunManager: ReRunManager, rerunTestsCallback: RerunTestsFactory, ttyActionsOnKeypress: boolean | undefined, initialTestRun: Promise<boolean | null> | null, input?: NodeJS.ReadStream, customOut?: OutFn): Promise<void>;
|
|
5
6
|
//# sourceMappingURL=listenToUser.d.ts.map
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { createInterface, emitKeypressEvents } from 'node:readline';
|
|
2
2
|
import { showTtyHelp } from './showTtyHelp.js';
|
|
3
3
|
import { handleUserInput } from './handleUserInput.js';
|
|
4
|
-
import { out } from '../../output.js';
|
|
4
|
+
import { out as mainOut } from '../../output.js';
|
|
5
5
|
export async function listenToUser(
|
|
6
6
|
//allTestFiles: Set<string>,
|
|
7
7
|
//failingTests: Set<string>,
|
|
8
|
-
rerunManager, rerunTestsCallback, ttyActionsOnKeypress = false, initialTestRun, input = process.stdin) {
|
|
8
|
+
rerunManager, rerunTestsCallback, ttyActionsOnKeypress = false, initialTestRun, input = process.stdin, customOut) {
|
|
9
|
+
// an agent spawned session has no TTY, so these notices would otherwise be the only
|
|
10
|
+
// lines in agent mode that are not agent events
|
|
11
|
+
const out = customOut ?? mainOut;
|
|
9
12
|
//console.log('initia test run', initialTestRun)
|
|
10
13
|
//console.log('listen to user')
|
|
11
14
|
//setInterval(() => console.log('active runs: ', rerunManager.state.activeRuns), 10_000)
|
|
@@ -58,7 +61,7 @@ rerunManager, rerunTestsCallback, ttyActionsOnKeypress = false, initialTestRun,
|
|
|
58
61
|
}
|
|
59
62
|
//console.log('initialTestRun 2', initialTestRun)
|
|
60
63
|
await initialTestRun;
|
|
61
|
-
showTtyHelp();
|
|
64
|
+
showTtyHelp(input.isTTY, out);
|
|
62
65
|
return;
|
|
63
66
|
}
|
|
64
67
|
//# sourceMappingURL=listenToUser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listenToUser.js","sourceRoot":"","sources":["../../../src/cli/lib/listenToUser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAY,MAAM,eAAe,CAAA;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAGtD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"listenToUser.js","sourceRoot":"","sources":["../../../src/cli/lib/listenToUser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAY,MAAM,eAAe,CAAA;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAGtD,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAMhD,MAAM,CAAC,KAAK,UAAU,YAAY;AAC9B,4BAA4B;AAC5B,4BAA4B;AAC5B,YAA0B,EAC1B,kBAAqC,EACrC,oBAAoB,GAAG,KAAK,EAC5B,cAA8C,EAC9C,QAA2B,OAAO,CAAC,KAAK,EACxC,SAAiB;IAEjB,oFAAoF;IACpF,gDAAgD;IAChD,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAA;IAEhC,gDAAgD;IAChD,+BAA+B;IAE/B,wFAAwF;IAExF,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,2CAA2C,CAAC,CAAA;QAChD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC5B,CAAC;IAED,IAAI,oBAAoB,EAAE,CAAC;QAEvB,qCAAqC;QAErC,kBAAkB,CAAC,KAAK,CAAC,CAAA;QAEzB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAA;QAC1B,MAAM,cAAc,GAAG,GAAS,EAAE;YAC9B,+BAA+B;YAC/B,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM;gBAAE,OAAM;YAClC,IAAI,CAAC;gBACD,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACL,qEAAqE;YACzE,CAAC;QACL,CAAC,CAAA;QAED,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACtB,KAAK,CAAC,MAAM,EAAE,CAAA;QACd,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;QACnC,IAAI,KAAK,KAAK,OAAO,CAAC,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;QAEjE,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,aAAqB,EAAE,GAAQ,EAAE,EAAE;YACrD,wCAAwC;YACxC,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;gBACxC,cAAc,EAAE,CAAA;gBAChB,4EAA4E;gBAC5E,0EAA0E;gBAC1E,sEAAsE;gBACtE,kEAAkE;gBAClE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC;oBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBACxD,OAAM;YACV,CAAC;YAED,eAAe,CAAC,aAAa,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;IACN,CAAC;SAAM,CAAC;QACJ,wCAAwC;QAExC,MAAM,SAAS,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QAE5C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;YACzB,kCAAkC;YAClC,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAA;QAC5D,CAAC,CAAC,CAAA;IACN,CAAC;IAED,iDAAiD;IACjD,MAAM,cAAc,CAAA;IACpB,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAE7B,OAAM;AACV,CAAC","sourcesContent":["\nimport { createInterface, emitKeypressEvents, type Key } from 'node:readline'\nimport { showTtyHelp } from './showTtyHelp.js'\nimport { handleUserInput } from './handleUserInput.js'\nimport { ReRunManager } from './reRunManager.js'\nimport { RunTestsPromise } from './runTests.js'\nimport { out as mainOut } from '../../output.js'\nimport type { OutFn } from '../../types.js'\n\nexport type RerunTestsFactory = (testFiles: Set<string>) => () => RunTestsPromise\n\n\nexport async function listenToUser(\n //allTestFiles: Set<string>,\n //failingTests: Set<string>,\n rerunManager: ReRunManager,\n rerunTestsCallback: RerunTestsFactory,\n ttyActionsOnKeypress = false,\n initialTestRun: Promise<boolean | null> | null,\n input: NodeJS.ReadStream = process.stdin,\n customOut?: OutFn\n): Promise<void> {\n // an agent spawned session has no TTY, so these notices would otherwise be the only\n // lines in agent mode that are not agent events\n const out = customOut ?? mainOut\n\n //console.log('initia test run', initialTestRun)\n //console.log('listen to user')\n\n //setInterval(() => console.log('active runs: ', rerunManager.state.activeRuns), 10_000)\n\n if (!input.isTTY) {\n out('No TTY available, not receiving cli input')\n return Promise.resolve()\n }\n\n if (ttyActionsOnKeypress) {\n \n //console.log('ttyActionsOnKeypress')\n\n emitKeypressEvents(input)\n\n const wasRaw = input.isRaw\n const restoreRawMode = (): void => {\n //console.log('restoreRawMode')\n if (input.isRaw === wasRaw) return\n try {\n input.setRawMode(wasRaw)\n } catch {\n // The terminal stream may already be closed during process shutdown.\n }\n }\n\n input.setRawMode(true)\n input.resume()\n input.once('close', restoreRawMode)\n if (input === process.stdin) process.once('exit', restoreRawMode)\n\n input.on('keypress', (keypressInput: string, key: Key) => {\n //console.log('keypress', keypressInput)\n if (key.ctrl === true && key.name === 'c') {\n restoreRawMode()\n // process.kill(process.pid, 'SIGINT') terminates unconditionally on Windows\n // rather than raising the event, which skips the shutdown handlers and so\n // skips the user's teardown. Emitting reaches them on every platform.\n // Nothing listening means nobody will exit for us, so do it here.\n if (!process.emit('SIGINT', 'SIGINT')) process.exit(130)\n return\n }\n\n handleUserInput(keypressInput, rerunManager, rerunTestsCallback)\n })\n } else {\n //console.log('no ttyActionsOnKeypress')\n\n const userInput = createInterface({ input })\n\n userInput.on('line', input => {\n //console.log('line input', input)\n handleUserInput(input, rerunManager, rerunTestsCallback)\n })\n }\n\n //console.log('initialTestRun 2', initialTestRun)\n await initialTestRun\n showTtyHelp(input.isTTY, out)\n\n return\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReRunManageState } from './makeWatchRunState.js';
|
|
2
2
|
import type { RunTestsPromise } from './runTests.js';
|
|
3
|
+
import type { OutFn } from '../../types.js';
|
|
3
4
|
export type RunType = 'auto' | 'all' | 'last' | 'failed';
|
|
4
5
|
type RunReqest = {
|
|
5
6
|
type: RunType;
|
|
@@ -13,6 +14,6 @@ export type ReRunManager = {
|
|
|
13
14
|
queue: RunReqest[];
|
|
14
15
|
};
|
|
15
16
|
};
|
|
16
|
-
export declare function makeReRunManager(currentRun: RunTestsPromise | null, state: ReRunManageState): ReRunManager;
|
|
17
|
+
export declare function makeReRunManager(currentRun: RunTestsPromise | null, state: ReRunManageState, customOut?: OutFn): ReRunManager;
|
|
17
18
|
export {};
|
|
18
19
|
//# sourceMappingURL=reRunManager.d.ts.map
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { inspect } from 'util';
|
|
2
|
-
import { debug, log, out } from '../../output.js';
|
|
2
|
+
import { debug, log, out as mainOut } from '../../output.js';
|
|
3
|
+
import { agentSetRunReason } from './agentReport.js';
|
|
3
4
|
import chalk from '../../packages/chalk.js';
|
|
4
|
-
export function makeReRunManager(currentRun, state
|
|
5
|
+
export function makeReRunManager(currentRun, state,
|
|
6
|
+
//callback: () => RunTestsPromise
|
|
7
|
+
customOut) {
|
|
8
|
+
// agent mode passes a sink - runTests reports the run instead
|
|
9
|
+
const out = customOut ?? mainOut;
|
|
5
10
|
let queue = [];
|
|
6
11
|
let waiting = false;
|
|
7
12
|
const __test = {
|
|
@@ -22,6 +27,8 @@ export function makeReRunManager(currentRun, state) {
|
|
|
22
27
|
debug('runReqest', runReqest);
|
|
23
28
|
if (runReqest === undefined)
|
|
24
29
|
return;
|
|
30
|
+
// tells the run about to start why it is running, for the agent `why=` field
|
|
31
|
+
agentSetRunReason(runReqest.type);
|
|
25
32
|
switch (runReqest.type) {
|
|
26
33
|
case 'all': {
|
|
27
34
|
out(chalk.brightblue `re-running all tests...`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reRunManager.js","sourceRoot":"","sources":["../../../src/cli/lib/reRunManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"reRunManager.js","sourceRoot":"","sources":["../../../src/cli/lib/reRunManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAI5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAsB3C,MAAM,UAAU,gBAAgB,CAC5B,UAAkC,EAClC,KAAuB;AACvB,iCAAiC;AACjC,SAAiB;IAEjB,8DAA8D;IAC9D,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAA;IAChC,IAAI,KAAK,GAAgB,EAAE,CAAA;IAC3B,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,MAAM,MAAM,GAAG;QACX,OAAO;QACP,KAAK;KACR,CAAA;IAED,KAAK,UAAU,YAAY;QAEvB,KAAK,CAAC,kBAAkB,CAAC,CAAA;QAEzB,IAAI,OAAO;YAAE,OAAM,CAAC,wDAAwD;QAC5E,MAAM,CAAC,OAAO,GAAG,OAAO,GAAG,IAAI,CAAA,CAAC,2BAA2B;QAC3D,MAAM,UAAU,CAAA,CAAC,uBAAuB;QACxC,MAAM,CAAC,OAAO,GAAG,OAAO,GAAG,KAAK,CAAA;QAEhC,KAAK,CAAC,eAAe,CAAC,CAAA;QAEtB,oCAAoC;QACpC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;QAC/B,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QAC7B,IAAI,SAAS,KAAK,SAAS;YAAE,OAAM;QAEnC,6EAA6E;QAC7E,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QAEjC,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,KAAK,CAAC,CAAC,CAAC;gBACT,GAAG,CAAC,KAAK,CAAC,UAAU,CAAA,yBAAyB,CAAC,CAAA;gBAC9C,MAAK;YACT,CAAC;YACD,KAAK,MAAM,CAAC,CAAC,CAAC;gBACV,GAAG,CAAC,KAAK,CAAC,UAAU,CAAA,0BAA0B,CAAC,CAAA;gBAC/C,MAAK;YACT,CAAC;YACD,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACZ,GAAG,CAAC,KAAK,CAAC,UAAU,CAAA,4BAA4B,CAAC,CAAA;gBACjD,MAAK;YACT,CAAC;YACD,KAAK,MAAM,CAAC,CAAC,CAAC;gBACV,GAAG,CAAC,KAAK,CAAC,UAAU,CAAA,mCAAmC,CAAC,CAAA;gBACxD,MAAK;YACT,CAAC;YACD,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;QACrD,CAAC;QAED,qBAAqB;QACrB,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC/C,UAAU,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAA;QACjC,KAAK,CAAC,UAAU,GAAG,UAAU,CAAA;QAC7B,qDAAqD;QACrD,MAAM,UAAU,CAAA;QAChB,mDAAmD;QACnD,mDAAmD;QACnD,mCAAmC;QACnC,YAAY,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC,CAAA;IAC3E,CAAC;IAED,OAAO;QACH,KAAK;QACL,UAAU,CAAC,IAAa,EAAE,QAA+B;YAErD,mDAAmD;YACnD,wDAAwD;YAExD,sDAAsD;YACtD,kDAAkD;YAClD,sDAAsD;YACtD,YAAY;YAEZ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBAClB,MAAM,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;gBAC3D,KAAK,CAAC,IAAI,CAAC;oBACP,IAAI;oBACJ,QAAQ;oBACR,QAAQ;iBACX,CAAC,CAAA;YACN,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;gBAC3D,MAAM,CAAC,KAAK,GAAG,KAAK,GAAG,CAAC;wBACpB,IAAI;wBACJ,QAAQ;wBACR,QAAQ;qBACX,CAAC,CAAA;YACN,CAAC;YACD,KAAK,CAAC,gBAAgB,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;YACvC,uBAAuB;YACvB,OAAO,YAAY,EAAE,CAAA,CAAC,2DAA2D;QACrF,CAAC;QACD,MAAM;KACT,CAAA;AACL,CAAC","sourcesContent":["import { inspect } from 'util'\nimport { debug, log, out as mainOut } from '../../output.js'\nimport { ReRunManageState } from './makeWatchRunState.js'\nimport type { RunTestsPromise } from './runTests.js'\nimport type { OutFn } from '../../types.js'\nimport { agentSetRunReason } from './agentReport.js'\nimport chalk from '../../packages/chalk.js'\n\nexport type RunType = 'auto' | 'all' | 'last' | 'failed'\n\ntype RunReqest = {\n type: RunType\n //tests: string[] | Set<string>\n callback: () => RunTestsPromise\n}\n\n//export type ReRunManager = ReturnType<typeof makeReRunManager>\n\nexport type ReRunManager = {\n state: ReRunManageState\n requestRun: (type: RunType, callback: () => RunTestsPromise) => void\n __test: {\n waiting: boolean\n queue: RunReqest[]\n }\n}\n\n\nexport function makeReRunManager(\n currentRun: RunTestsPromise | null,\n state: ReRunManageState,\n //callback: () => RunTestsPromise\n customOut?: OutFn\n): ReRunManager {\n // agent mode passes a sink - runTests reports the run instead\n const out = customOut ?? mainOut\n let queue: RunReqest[] = []\n let waiting = false\n\n const __test = {\n waiting,\n queue\n }\n\n async function processQueue() {\n \n debug('processing queue')\n\n if (waiting) return // do nothing if another processQueue is already waiting\n __test.waiting = waiting = true // mark that we are waiting\n await currentRun // wait for current run\n __test.waiting = waiting = false\n\n debug('done waitinng')\n\n // see if there is a request waiting\n debug('the queue', inspect(queue))\n const runReqest = queue.shift()\n debug('runReqest', runReqest)\n if (runReqest === undefined) return\n\n // tells the run about to start why it is running, for the agent `why=` field\n agentSetRunReason(runReqest.type)\n\n switch (runReqest.type) {\n case 'all': {\n out(chalk.brightblue`re-running all tests...`)\n break\n }\n case 'last': {\n out(chalk.brightblue`re-running last tests...`)\n break\n }\n case 'failed': {\n out(chalk.brightblue`re-running failed tests...`)\n break\n }\n case 'auto': {\n out(chalk.brightblue`running tests due to file changes`)\n break\n }\n default: throw new Error('Unrecognised run type')\n }\n\n // run it and save it\n debug('calling', runReqest.callback.toString())\n currentRun = runReqest.callback()\n state.currentRun = currentRun\n // wait for the run then trigger another processQueue\n await currentRun\n // if one has already been started by a run request\n // then this won't start a new one. This is used to\n // clear a queue if it has built it\n processQueue().catch(err => log(`processQueue threw an error: ${err}`))\n }\n\n return {\n state,\n requestRun(type: RunType, callback: () => RunTestsPromise) {\n\n // if it's type auto, we only want to keep one, but\n // we want it to include all relevant tests when it runs\n\n // if it's a human triggered type, we'll replace other\n // human requests, but leave the auto, so the user\n // can see update to changed code that would be hidden\n // otherwise\n \n if (type === 'auto') {\n __test.queue = queue = queue.filter(x => x.type !== 'auto')\n queue.push({\n type,\n //tests,\n callback\n })\n } else {\n __test.queue = queue = queue.filter(x => x.type === 'auto')\n __test.queue = queue = [{\n type,\n //tests,\n callback\n }]\n }\n debug('added to queue', inspect(queue))\n // see if we can run it\n return processQueue() //.catch(err => log(`processQueue threw an error: ${err}`))\n },\n __test\n }\n}\n\n\n"]}
|
package/dist/cli/lib/runTests.js
CHANGED
|
@@ -9,14 +9,29 @@ import { loadTestFile } from './loadTestFile.js';
|
|
|
9
9
|
import { runTest } from './runTest.js';
|
|
10
10
|
import { showTestLoadingError } from './showTestLoadingError.js';
|
|
11
11
|
import { showTestResult } from './showTestResult.js';
|
|
12
|
+
import { failureLines } from './failureLines.js';
|
|
13
|
+
import { failureEntries } from './failureEntries.js';
|
|
14
|
+
import { agentDone, agentFailure, agentRunStart } from './agentReport.js';
|
|
15
|
+
import { statusCodes, writeStatusFile } from './statusFile.js';
|
|
12
16
|
import { makeRunManagerState } from './makeWatchRunState.js';
|
|
13
17
|
const { timeProfileAsync } = createTimeProfiler(showTimeProfiling);
|
|
18
|
+
// the summary lines, minus the colouring, for the status file
|
|
19
|
+
function joinPlain(...parts) {
|
|
20
|
+
return parts.filter(part => part !== '').join(' ');
|
|
21
|
+
}
|
|
22
|
+
function plural(count, noun, verb) {
|
|
23
|
+
if (count < 1)
|
|
24
|
+
return '';
|
|
25
|
+
return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`;
|
|
26
|
+
}
|
|
14
27
|
export async function runTests(config, testFiles, reRunManager, refresh = 'refresh', customOut, filters = {}) {
|
|
15
28
|
if (reRunManager !== undefined) {
|
|
16
29
|
reRunManager.state.lastTestFiles = new Set(testFiles);
|
|
17
30
|
reRunManager.state.activeRuns++; // whatever, obsolete. Can use it to check on things
|
|
18
31
|
}
|
|
19
32
|
const state = reRunManager?.state || makeRunManagerState();
|
|
33
|
+
const runStartTime = new Date().getTime();
|
|
34
|
+
const agentRun = agentRunStart(config, testFiles.size);
|
|
20
35
|
//console.log('new runTests:', watchRunState?.activeRuns)
|
|
21
36
|
//console.log(inspect(testFiles))
|
|
22
37
|
try {
|
|
@@ -99,6 +114,9 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
|
|
|
99
114
|
&& failedToLoadCount === 0
|
|
100
115
|
&& describesThrownCount === 0) {
|
|
101
116
|
out(chalk.orange('No tests matched the describe/test filters.'));
|
|
117
|
+
const durationMs = new Date().getTime() - runStartTime;
|
|
118
|
+
writeStatusFile(config, statusCodes.couldNotRun, 'no tests matched the describe/test filters', [], durationMs);
|
|
119
|
+
agentDone(config, agentRun, statusCodes.couldNotRun, 'no tests matched the describe/test filters', testsResultsSummary, durationMs, state.failedTestFiles.size);
|
|
102
120
|
return null;
|
|
103
121
|
}
|
|
104
122
|
out('\n');
|
|
@@ -121,17 +139,19 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
|
|
|
121
139
|
}
|
|
122
140
|
// number of items successful
|
|
123
141
|
const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`;
|
|
124
|
-
const
|
|
142
|
+
const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)
|
|
125
143
|
? (testsResultsSummary.describesInvalid === 1)
|
|
126
|
-
?
|
|
127
|
-
:
|
|
144
|
+
? '(+1 describe without tests)'
|
|
145
|
+
: `(+${testsResultsSummary.describesInvalid} describes without tests)`
|
|
128
146
|
: '';
|
|
129
|
-
const
|
|
147
|
+
const describesThrownPlain = (describesThrownCount >= 1)
|
|
130
148
|
? (describesThrownCount === 1)
|
|
131
|
-
?
|
|
132
|
-
:
|
|
149
|
+
? '(1 describe errored)'
|
|
150
|
+
: `(${describesThrownCount} describes errored)`
|
|
133
151
|
: '';
|
|
134
|
-
const describesDetailsText = [
|
|
152
|
+
const describesDetailsText = [
|
|
153
|
+
chalk.grey(invalidDescribesPlain), chalk.mediumred(describesThrownPlain)
|
|
154
|
+
]
|
|
135
155
|
.filter(text => text !== '')
|
|
136
156
|
.join(' ');
|
|
137
157
|
const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`;
|
|
@@ -143,17 +163,19 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
|
|
|
143
163
|
}
|
|
144
164
|
// number of test files successful
|
|
145
165
|
const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`;
|
|
146
|
-
const
|
|
166
|
+
const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)
|
|
147
167
|
? (testsResultsSummary.invalid === 1)
|
|
148
|
-
?
|
|
149
|
-
:
|
|
168
|
+
? '(+1 file without tests)'
|
|
169
|
+
: `(+${testsResultsSummary.invalid} files without tests)`
|
|
150
170
|
: '';
|
|
151
|
-
const
|
|
171
|
+
const failedToLoadPlain = (failedToLoadCount >= 1)
|
|
152
172
|
? (failedToLoadCount === 1)
|
|
153
|
-
?
|
|
154
|
-
:
|
|
173
|
+
? '(1 file failed to load, or errored)'
|
|
174
|
+
: `(${failedToLoadCount} files failed to load, or errored)`
|
|
155
175
|
: '';
|
|
156
|
-
const testFilesDetailsText = [
|
|
176
|
+
const testFilesDetailsText = [
|
|
177
|
+
chalk.grey(invalidTestFilesPlain), chalk.mediumred(failedToLoadPlain)
|
|
178
|
+
]
|
|
157
179
|
.filter(text => text !== '')
|
|
158
180
|
.join(' ');
|
|
159
181
|
const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`;
|
|
@@ -163,6 +185,35 @@ export async function runTests(config, testFiles, reRunManager, refresh = 'refre
|
|
|
163
185
|
else {
|
|
164
186
|
out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix);
|
|
165
187
|
}
|
|
188
|
+
const summaryLines = [
|
|
189
|
+
testsText,
|
|
190
|
+
joinPlain(describesText, invalidDescribesPlain, describesThrownPlain),
|
|
191
|
+
joinPlain(testFilesText, invalidTestFilesPlain, failedToLoadPlain)
|
|
192
|
+
];
|
|
193
|
+
const durationMs = new Date().getTime() - runStartTime;
|
|
194
|
+
if (allPassed) {
|
|
195
|
+
writeStatusFile(config, statusCodes.passed, 'all tests passed', summaryLines, durationMs);
|
|
196
|
+
agentDone(config, agentRun, statusCodes.passed, 'all tests passed', testsResultsSummary, durationMs, state.failedTestFiles.size);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const abortedFiles = Object.keys(erroringTests);
|
|
200
|
+
// a file that would not load, or a describe that threw, means the run died
|
|
201
|
+
// partway - a different problem from tests that ran and failed
|
|
202
|
+
const aborted = abortedFiles.length > 0 || describesThrownCount > 0;
|
|
203
|
+
const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses;
|
|
204
|
+
const description = [
|
|
205
|
+
plural(abortedFiles.length, 'test file', 'failed to load or errored'),
|
|
206
|
+
plural(describesThrownCount, 'describe', 'errored'),
|
|
207
|
+
plural(failedTestsCount, 'test', 'failed')
|
|
208
|
+
].filter(part => part !== '').join(', ') || 'test run failed';
|
|
209
|
+
const code = (aborted) ? statusCodes.aborted : statusCodes.failed;
|
|
210
|
+
const failures = failureEntries(Object.values(runTestResults), erroringTests);
|
|
211
|
+
writeStatusFile(config, code, description, [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)], durationMs);
|
|
212
|
+
// failures first, so the done line is a complete end of run marker
|
|
213
|
+
for (const failure of failures)
|
|
214
|
+
agentFailure(config, agentRun, failure);
|
|
215
|
+
agentDone(config, agentRun, code, description, testsResultsSummary, durationMs, state.failedTestFiles.size);
|
|
216
|
+
}
|
|
166
217
|
// full success?
|
|
167
218
|
// true/false gets returned to the caller of runTests()
|
|
168
219
|
return allPassed;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../../src/cli/lib/runTests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAC3C,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,OAAO,MAAM,2BAA2B,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAKpD,OAAO,EAAE,mBAAmB,EAAoB,MAAM,wBAAwB,CAAA;AAG9E,MAAM,EAAE,gBAAgB,EAAE,GAAG,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;AAIlE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC1B,MAAmB,EACnB,SAAsB,EACtB,YAAsC,EACtC,UAAgC,SAAS,EACzC,SAAiB,EACjB,UAAgC,EAAE;IAElC,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC7B,YAAY,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAA;QACrD,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA,CAAC,oDAAoD;IACxF,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,EAAE,KAAK,IAAI,mBAAmB,EAAE,CAAA;IAC1D,yDAAyD;IACzD,iCAAiC;IAEjC,IAAI,CAAC;QACD,MAAM,eAAe,GAAwC,EAAE,CAAA;QAC/D,MAAM,aAAa,GAA6B,EAAE,CAAA;QAClD,MAAM,kBAAkB,GAAkC,EAAE,CAAA;QAE5D,MAAM,gBAAgB,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;YAC3C,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACvE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;oBAC/B,qCAAqC;oBACrC,mCAAmC;oBACnC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;oBAE1D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;wBACnD,aAAa,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;wBAC9B,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;wBACnC,oBAAoB,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;oBACjD,CAAC;yBAAM,CAAC;wBACJ,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;wBACrD,eAAe,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAA;wBAE1C,kBAAkB,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,EAAC,UAAU,EAAC,EAAE;4BAClE,IAAI,UAAU,CAAC,OAAO,KAAK,IAAI,IAAI,UAAU,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;gCAC7D,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;4BACjD,CAAC;iCAAM,CAAC;gCACJ,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;4BACvC,CAAC;4BACD,MAAM,qBAAqB,GAAG,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,CAAA;4BACxF,IAAI,CAAC,qBAAqB,IAAI,UAAU,CAAC,sBAAsB,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;gCAC3E,MAAM,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAA;4BACvD,CAAC;wBACL,CAAC,CAAC,CAAA;wBAEN,iFAAiF;wBAC7E,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY;4BAAE,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAA;oBACnF,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC,CAAC,CAAA;QAEF,IAAI,cAAc,GAA+B,EAAE,CAAA;QAEnD,MAAM,gBAAgB,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YAC1D,cAAc,GAAG,MAAM,aAAa,CAAC,eAAe,CAAC,CAAA;YAEzD,kCAAkC;YAC9B,MAAM,aAAa,CAAC,kBAAkB,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,OAAO,MAAM,gBAAgB,CAAC,+BAA+B,EAAE,GAAG,EAAE;YAEhE,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAA;YAEhC,MAAM,mBAAmB,GAAwB;gBAC7C,KAAK,EAAE,CAAC;gBACR,MAAM,EAAE,CAAC;gBACT,OAAO,EAAE,CAAC;gBACV,cAAc,EAAE,CAAC;gBACjB,eAAe,EAAE,CAAC;gBAClB,gBAAgB,EAAE,CAAC;gBACnB,QAAQ,EAAE,CAAC;gBACX,SAAS,EAAE,CAAC;gBAChB,qGAAqG;aACpG,CAAA;YACD,IAAI,oBAAoB,GAAG,CAAC,CAAA;YAE5B,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;gBACpC,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;gBAC9C,IAAI,CAAC,aAAa;oBAAE,SAAQ;gBAE5B,mBAAmB,CAAC,KAAK,IAAI,CAAC,CAAC,aAAa,CAAC,OAAO,KAAK,IAAI,CAAC,CAAA;gBAC9D,mBAAmB,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,CAAC,OAAO,IAAI,KAAK,CAAC,CAAA;gBAC/D,mBAAmB,CAAC,OAAO,IAAI,CAAC,CAAC,aAAa,CAAC,OAAO,KAAK,IAAI,CAAC,CAAA;gBAChE,mBAAmB,CAAC,cAAc,IAAI,aAAa,CAAC,sBAAsB,CAAC,KAAK,CAAA;gBAChF,mBAAmB,CAAC,eAAe,IAAI,aAAa,CAAC,sBAAsB,CAAC,MAAM,CAAA;gBAClF,mBAAmB,CAAC,gBAAgB,IAAI,aAAa,CAAC,sBAAsB,CAAC,OAAO,CAAA;gBACpF,mBAAmB,CAAC,QAAQ,IAAI,aAAa,CAAC,sBAAsB,CAAC,QAAQ,CAAA;gBAC7E,mBAAmB,CAAC,SAAS,IAAI,aAAa,CAAC,sBAAsB,CAAC,SAAS,CAAA;gBAC/E,oBAAoB,IAAI,aAAa,CAAC,eAAe;qBAChD,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,KAAK,KAAK,SAAS,CAAC;qBAC5D,MAAM,CAAA;YACf,CAAC;YAED,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAAC,CAAA;YAC9C,mBAAmB,CAAC,KAAK,IAAI,iBAAiB,CAAA;YAE9C,IACI,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,CAAC;mBACzD,mBAAmB,CAAC,QAAQ,KAAK,CAAC;mBAClC,iBAAiB,KAAK,CAAC;mBACvB,oBAAoB,KAAK,CAAC,EAC/B,CAAC;gBACC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,6CAA6C,CAAC,CAAC,CAAA;gBAChE,OAAO,IAAI,CAAA;YACf,CAAC;YAED,GAAG,CAAC,IAAI,CAAC,CAAA;YAET,MAAM,SAAS,GAAG,CACd,mBAAmB,CAAC,MAAM,KAAK,mBAAmB,CAAC,KAAK;mBACrD,mBAAmB,CAAC,eAAe,KAAK,mBAAmB,CAAC,cAAc;mBAC1E,mBAAmB,CAAC,SAAS,KAAK,mBAAmB,CAAC,QAAQ,CACpE,CAAA;YAED,IAAI,SAAS,EAAE,CAAC;gBACZ,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YAC7C,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YAC5C,CAAC;YAEL,6BAA6B;YACzB,MAAM,SAAS,GAAG,UAAU,mBAAmB,CAAC,SAAS,IAAI,mBAAmB,CAAC,QAAQ,EAAE,CAAA;YAC3F,IAAI,mBAAmB,CAAC,SAAS,KAAK,mBAAmB,CAAC,QAAQ,EAAE,CAAC;gBACjE,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC,CAAA;YAC1C,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,SAAS,EAAE,CAAC,CAAC,CAAA;YACxC,CAAC;YAEL,6BAA6B;YACzB,MAAM,aAAa,GAAG,UAAU,mBAAmB,CAAC,eAAe,IAAI,mBAAmB,CAAC,cAAc,EAAE,CAAA;YAC3G,MAAM,oBAAoB,GAAG,CAAC,mBAAmB,CAAC,gBAAgB,IAAI,CAAC,CAAC;gBACpE,CAAC,CAAC,CAAC,mBAAmB,CAAC,gBAAgB,KAAK,CAAC,CAAC;oBAC1C,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC;oBAC3C,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,mBAAmB,CAAC,gBAAgB,2BAA2B,CAAC;gBACtF,CAAC,CAAC,EAAE,CAAA;YACR,MAAM,mBAAmB,GAAG,CAAC,oBAAoB,IAAI,CAAC,CAAC;gBACnD,CAAC,CAAC,CAAC,oBAAoB,KAAK,CAAC,CAAC;oBAC1B,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,sBAAsB,CAAC;oBACzC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,oBAAoB,qBAAqB,CAAC;gBACpE,CAAC,CAAC,EAAE,CAAA;YACR,MAAM,oBAAoB,GAAG,CAAC,oBAAoB,EAAE,mBAAmB,CAAC;iBACnE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;iBAC3B,IAAI,CAAC,GAAG,CAAC,CAAA;YACd,MAAM,sBAAsB,GAAG,oBAAoB,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,oBAAoB,EAAE,CAAA;YAC5F,IAAI,mBAAmB,CAAC,eAAe,KAAK,mBAAmB,CAAC,cAAc,EAAE,CAAC;gBAC7E,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,aAAa,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAA;YACvE,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,aAAa,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAA;YACrE,CAAC;YAEL,kCAAkC;YAC9B,MAAM,aAAa,GAAG,eAAe,mBAAmB,CAAC,MAAM,IAAI,mBAAmB,CAAC,KAAK,EAAE,CAAA;YAC9F,MAAM,oBAAoB,GAAG,CAAC,mBAAmB,CAAC,OAAO,IAAI,CAAC,CAAC;gBAC3D,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,KAAK,CAAC,CAAC;oBACjC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC;oBACvC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,mBAAmB,CAAC,OAAO,uBAAuB,CAAC;gBACzE,CAAC,CAAC,EAAE,CAAA;YACR,MAAM,gBAAgB,GAAG,CAAC,iBAAiB,IAAI,CAAC,CAAC;gBAC7C,CAAC,CAAC,CAAC,iBAAiB,KAAK,CAAC,CAAC;oBACvB,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,qCAAqC,CAAC;oBACxD,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,iBAAiB,oCAAoC,CAAC;gBAChF,CAAC,CAAC,EAAE,CAAA;YACR,MAAM,oBAAoB,GAAG,CAAC,oBAAoB,EAAE,gBAAgB,CAAC;iBAChE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;iBAC3B,IAAI,CAAC,GAAG,CAAC,CAAA;YACd,MAAM,sBAAsB,GAAG,oBAAoB,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,oBAAoB,EAAE,CAAA;YAC5F,IAAI,mBAAmB,CAAC,MAAM,KAAK,mBAAmB,CAAC,KAAK,EAAE,CAAC;gBAC3D,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,aAAa,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAA;YACvE,CAAC;iBAAM,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,aAAa,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAA;YACrE,CAAC;YAED,gBAAgB;YAChB,uDAAuD;YACvD,OAAO,SAAS,CAAA;QACpB,CAAC,CAAC,CAAA;IACN,CAAC;YAAS,CAAC;QACP,IAAI,YAAY,KAAK,SAAS;YAAE,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA;IACnE,CAAC;AACL,CAAC","sourcesContent":["import { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport chalk from '../../packages/chalk.js'\nimport { out as mainOut } from '../../output.js'\nimport figures from '../../packages/figures.js'\nimport { count } from 'sxy-lib/objects.js'\nimport { remove as arrayRemove } from 'sxy-lib/arrays.js'\nimport { allObj as promiseAllObj } from 'sxy-lib/promises.js'\n\nimport { loadTestFile } from './loadTestFile.js'\nimport { runTest } from './runTest.js'\nimport { showTestLoadingError } from './showTestLoadingError.js'\nimport { showTestResult } from './showTestResult.js'\n\nimport type {\n FinalConfig, OutFn, TestExecutionFilters, TestFile, TestResult, TestsResultsSummary\n} from '../../types.js'\nimport { makeRunManagerState, ReRunManageState } from './makeWatchRunState.js'\nimport { ReRunManager } from './reRunManager.js'\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport type RunTestsPromise = Promise<boolean | null>\n\nexport async function runTests(\n config: FinalConfig,\n testFiles: Set<string>,\n reRunManager: ReRunManager | undefined,\n refresh: 'refresh' | 'cached' = 'refresh',\n customOut?: OutFn,\n filters: TestExecutionFilters = {}\n): RunTestsPromise {\n if (reRunManager !== undefined) {\n reRunManager.state.lastTestFiles = new Set(testFiles)\n reRunManager.state.activeRuns++ // whatever, obsolete. Can use it to check on things\n }\n\n const state = reRunManager?.state || makeRunManagerState()\n //console.log('new runTests:', watchRunState?.activeRuns)\n //console.log(inspect(testFiles))\n\n try {\n const testRunPromises: Record<string, Promise<TestResult>> = {}\n const erroringTests: Record<string, TestFile> = {}\n const testRunOutPromises: Record<string, Promise<void>> = {}\n\n await timeProfileAsync('run tests', async () => {\n if (Array.isArray(testFiles) ? testFiles.length > 0 : testFiles.size > 0) {\n for (const testFile of testFiles) {\n //console.log('testFiles', testFiles)\n //console.log('testFile', testFile)\n const test = await loadTestFile(config, testFile, refresh)\n\n if (test.error !== undefined && test.error !== false) {\n erroringTests[testFile] = test\n state.failedTestFiles.add(testFile)\n showTestLoadingError(config, test, customOut)\n } else {\n const testRunPromise = runTest(config, test, filters)\n testRunPromises[testFile] = testRunPromise\n\n testRunOutPromises[testFile] = testRunPromise.then(async testResult => {\n if (testResult.success === true || testResult.success === null) {\n state.failedTestFiles.delete(testResult.file)\n } else {\n state.failedTestFiles.add(testFile)\n }\n const executionFilterActive = filters.describe !== undefined || filters.it !== undefined\n if (!executionFilterActive || testResult.describeResultsSummary.itsTotal > 0) {\n await showTestResult(config, testResult, customOut)\n }\n })\n\n // wait for the test to complete before proceeding if we are in 'sequential' mode\n if (config.execution.files === 'sequential') await testRunOutPromises[testFile]\n }\n }\n }\n })\n\n let runTestResults: Record<string, TestResult> = {}\n\n await timeProfileAsync('wait for tests to finish', async () => {\n runTestResults = await promiseAllObj(testRunPromises)\n\n // wait for the output to complete\n await promiseAllObj(testRunOutPromises)\n })\n\n return await timeProfileAsync('show initial test run results', () => {\n \n const out = customOut ?? mainOut\n\n const testsResultsSummary: TestsResultsSummary = {\n total: 0,\n passes: 0,\n invalid: 0,\n describesTotal: 0,\n describesPasses: 0,\n describesInvalid: 0,\n itsTotal: 0,\n itsPasses: 0\n // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)\n }\n let describesThrownCount = 0\n\n for (const testFile in runTestResults) {\n const runTestResult = runTestResults[testFile]\n if (!runTestResult) continue\n\n testsResultsSummary.total += +(runTestResult.success !== null)\n testsResultsSummary.passes += +(runTestResult.success ?? false)\n testsResultsSummary.invalid += +(runTestResult.success === null)\n testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total\n testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes\n testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid\n testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal\n testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses\n describesThrownCount += runTestResult.describeResults\n .filter(describeResult => describeResult.error !== undefined)\n .length\n }\n\n const failedToLoadCount = count(erroringTests)\n testsResultsSummary.total += failedToLoadCount\n\n if (\n (filters.describe !== undefined || filters.it !== undefined)\n && testsResultsSummary.itsTotal === 0\n && failedToLoadCount === 0\n && describesThrownCount === 0\n ) {\n out(chalk.orange('No tests matched the describe/test filters.'))\n return null\n }\n\n out('\\n')\n\n const allPassed = (\n testsResultsSummary.passes === testsResultsSummary.total\n && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal\n && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal\n )\n\n if (allPassed) {\n out(chalk.mediumgreen(`${figures.tick}`))\n } else {\n out(chalk.mediumred(`${figures.cross}`))\n }\n\n // number of tests successful\n const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`\n if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {\n out(chalk.mediumgreen(`${testsText}`))\n } else {\n out(chalk.mediumred(`${testsText}`))\n }\n\n // number of items successful\n const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`\n const invalidDescribesText = (testsResultsSummary.describesInvalid >= 1)\n ? (testsResultsSummary.describesInvalid === 1)\n ? chalk.grey('(+1 describe without tests)')\n : chalk.grey(`(+${testsResultsSummary.describesInvalid} describes without tests)`)\n : ''\n const describesThrownText = (describesThrownCount >= 1)\n ? (describesThrownCount === 1)\n ? chalk.mediumred('(1 describe errored)')\n : chalk.mediumred(`(${describesThrownCount} describes errored)`)\n : ''\n const describesDetailsText = [invalidDescribesText, describesThrownText]\n .filter(text => text !== '')\n .join(' ')\n const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`\n if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {\n out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix)\n }\n\n // number of test files successful\n const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`\n const invalidTestFilesText = (testsResultsSummary.invalid >= 1)\n ? (testsResultsSummary.invalid === 1)\n ? chalk.grey('(+1 file without tests)')\n : chalk.grey(`(+${testsResultsSummary.invalid} files without tests)`)\n : ''\n const failedToLoadText = (failedToLoadCount >= 1)\n ? (failedToLoadCount === 1)\n ? chalk.mediumred('(1 file failed to load, or errored)')\n : chalk.mediumred(`(${failedToLoadCount} files failed to load, or errored)`)\n : ''\n const testFilesDetailsText = [invalidTestFilesText, failedToLoadText]\n .filter(text => text !== '')\n .join(' ')\n const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`\n if (testsResultsSummary.passes === testsResultsSummary.total) {\n out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix)\n }\n\n // full success?\n // true/false gets returned to the caller of runTests()\n return allPassed\n })\n } finally {\n if (reRunManager !== undefined) reRunManager.state.activeRuns--\n }\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../../src/cli/lib/runTests.ts"],"names":[],"mappings":"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","sourcesContent":["import { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport chalk from '../../packages/chalk.js'\nimport { out as mainOut } from '../../output.js'\nimport figures from '../../packages/figures.js'\nimport { count } from 'sxy-lib/objects.js'\nimport { remove as arrayRemove } from 'sxy-lib/arrays.js'\nimport { allObj as promiseAllObj } from 'sxy-lib/promises.js'\n\nimport { loadTestFile } from './loadTestFile.js'\nimport { runTest } from './runTest.js'\nimport { showTestLoadingError } from './showTestLoadingError.js'\nimport { showTestResult } from './showTestResult.js'\nimport { failureLines } from './failureLines.js'\nimport { failureEntries } from './failureEntries.js'\nimport { agentDone, agentFailure, agentRunStart } from './agentReport.js'\nimport { statusCodes, writeStatusFile } from './statusFile.js'\n\nimport type {\n FinalConfig, OutFn, TestExecutionFilters, TestFile, TestResult, TestsResultsSummary\n} from '../../types.js'\nimport { makeRunManagerState, ReRunManageState } from './makeWatchRunState.js'\nimport { ReRunManager } from './reRunManager.js'\n\nconst { timeProfileAsync } = createTimeProfiler(showTimeProfiling)\n\nexport type RunTestsPromise = Promise<boolean | null>\n\n// the summary lines, minus the colouring, for the status file\nfunction joinPlain(...parts: string[]): string {\n return parts.filter(part => part !== '').join(' ')\n}\n\nfunction plural(count: number, noun: string, verb: string): string {\n if (count < 1) return ''\n return `${count} ${noun}${count === 1 ? '' : 's'} ${verb}`\n}\n\n\nexport async function runTests(\n config: FinalConfig,\n testFiles: Set<string>,\n reRunManager: ReRunManager | undefined,\n refresh: 'refresh' | 'cached' = 'refresh',\n customOut?: OutFn,\n filters: TestExecutionFilters = {}\n): RunTestsPromise {\n if (reRunManager !== undefined) {\n reRunManager.state.lastTestFiles = new Set(testFiles)\n reRunManager.state.activeRuns++ // whatever, obsolete. Can use it to check on things\n }\n\n const state = reRunManager?.state || makeRunManagerState()\n const runStartTime = new Date().getTime()\n const agentRun = agentRunStart(config, testFiles.size)\n //console.log('new runTests:', watchRunState?.activeRuns)\n //console.log(inspect(testFiles))\n\n try {\n const testRunPromises: Record<string, Promise<TestResult>> = {}\n const erroringTests: Record<string, TestFile> = {}\n const testRunOutPromises: Record<string, Promise<void>> = {}\n\n await timeProfileAsync('run tests', async () => {\n if (Array.isArray(testFiles) ? testFiles.length > 0 : testFiles.size > 0) {\n for (const testFile of testFiles) {\n //console.log('testFiles', testFiles)\n //console.log('testFile', testFile)\n const test = await loadTestFile(config, testFile, refresh)\n\n if (test.error !== undefined && test.error !== false) {\n erroringTests[testFile] = test\n state.failedTestFiles.add(testFile)\n showTestLoadingError(config, test, customOut)\n } else {\n const testRunPromise = runTest(config, test, filters)\n testRunPromises[testFile] = testRunPromise\n\n testRunOutPromises[testFile] = testRunPromise.then(async testResult => {\n if (testResult.success === true || testResult.success === null) {\n state.failedTestFiles.delete(testResult.file)\n } else {\n state.failedTestFiles.add(testFile)\n }\n const executionFilterActive = filters.describe !== undefined || filters.it !== undefined\n if (!executionFilterActive || testResult.describeResultsSummary.itsTotal > 0) {\n await showTestResult(config, testResult, customOut)\n }\n })\n\n // wait for the test to complete before proceeding if we are in 'sequential' mode\n if (config.execution.files === 'sequential') await testRunOutPromises[testFile]\n }\n }\n }\n })\n\n let runTestResults: Record<string, TestResult> = {}\n\n await timeProfileAsync('wait for tests to finish', async () => {\n runTestResults = await promiseAllObj(testRunPromises)\n\n // wait for the output to complete\n await promiseAllObj(testRunOutPromises)\n })\n\n return await timeProfileAsync('show initial test run results', () => {\n \n const out = customOut ?? mainOut\n\n const testsResultsSummary: TestsResultsSummary = {\n total: 0,\n passes: 0,\n invalid: 0,\n describesTotal: 0,\n describesPasses: 0,\n describesInvalid: 0,\n itsTotal: 0,\n itsPasses: 0\n // itsInvalid: 0 // we don't check whether tests run any asserts (we don't control the assertion lib)\n }\n let describesThrownCount = 0\n\n for (const testFile in runTestResults) {\n const runTestResult = runTestResults[testFile]\n if (!runTestResult) continue\n\n testsResultsSummary.total += +(runTestResult.success !== null)\n testsResultsSummary.passes += +(runTestResult.success ?? false)\n testsResultsSummary.invalid += +(runTestResult.success === null)\n testsResultsSummary.describesTotal += runTestResult.describeResultsSummary.total\n testsResultsSummary.describesPasses += runTestResult.describeResultsSummary.passes\n testsResultsSummary.describesInvalid += runTestResult.describeResultsSummary.invalid\n testsResultsSummary.itsTotal += runTestResult.describeResultsSummary.itsTotal\n testsResultsSummary.itsPasses += runTestResult.describeResultsSummary.itsPasses\n describesThrownCount += runTestResult.describeResults\n .filter(describeResult => describeResult.error !== undefined)\n .length\n }\n\n const failedToLoadCount = count(erroringTests)\n testsResultsSummary.total += failedToLoadCount\n\n if (\n (filters.describe !== undefined || filters.it !== undefined)\n && testsResultsSummary.itsTotal === 0\n && failedToLoadCount === 0\n && describesThrownCount === 0\n ) {\n out(chalk.orange('No tests matched the describe/test filters.'))\n const durationMs = new Date().getTime() - runStartTime\n writeStatusFile(\n config,\n statusCodes.couldNotRun,\n 'no tests matched the describe/test filters',\n [],\n durationMs\n )\n agentDone(\n config, agentRun, statusCodes.couldNotRun,\n 'no tests matched the describe/test filters', testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n return null\n }\n\n out('\\n')\n\n const allPassed = (\n testsResultsSummary.passes === testsResultsSummary.total\n && testsResultsSummary.describesPasses === testsResultsSummary.describesTotal\n && testsResultsSummary.itsPasses === testsResultsSummary.itsTotal\n )\n\n if (allPassed) {\n out(chalk.mediumgreen(`${figures.tick}`))\n } else {\n out(chalk.mediumred(`${figures.cross}`))\n }\n\n // number of tests successful\n const testsText = `Tests: ${testsResultsSummary.itsPasses}/${testsResultsSummary.itsTotal}`\n if (testsResultsSummary.itsPasses === testsResultsSummary.itsTotal) {\n out(chalk.mediumgreen(`${testsText}`))\n } else {\n out(chalk.mediumred(`${testsText}`))\n }\n\n // number of items successful\n const describesText = `Items: ${testsResultsSummary.describesPasses}/${testsResultsSummary.describesTotal}`\n const invalidDescribesPlain = (testsResultsSummary.describesInvalid >= 1)\n ? (testsResultsSummary.describesInvalid === 1)\n ? '(+1 describe without tests)'\n : `(+${testsResultsSummary.describesInvalid} describes without tests)`\n : ''\n const describesThrownPlain = (describesThrownCount >= 1)\n ? (describesThrownCount === 1)\n ? '(1 describe errored)'\n : `(${describesThrownCount} describes errored)`\n : ''\n const describesDetailsText = [\n chalk.grey(invalidDescribesPlain), chalk.mediumred(describesThrownPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const describesDetailsSuffix = describesDetailsText === '' ? '' : ` ${describesDetailsText}`\n if (testsResultsSummary.describesPasses === testsResultsSummary.describesTotal) {\n out(chalk.mediumgreen(`${describesText}`) + describesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${describesText}`) + describesDetailsSuffix)\n }\n\n // number of test files successful\n const testFilesText = `Test Files: ${testsResultsSummary.passes}/${testsResultsSummary.total}`\n const invalidTestFilesPlain = (testsResultsSummary.invalid >= 1)\n ? (testsResultsSummary.invalid === 1)\n ? '(+1 file without tests)'\n : `(+${testsResultsSummary.invalid} files without tests)`\n : ''\n const failedToLoadPlain = (failedToLoadCount >= 1)\n ? (failedToLoadCount === 1)\n ? '(1 file failed to load, or errored)'\n : `(${failedToLoadCount} files failed to load, or errored)`\n : ''\n const testFilesDetailsText = [\n chalk.grey(invalidTestFilesPlain), chalk.mediumred(failedToLoadPlain)\n ]\n .filter(text => text !== '')\n .join(' ')\n const testFilesDetailsSuffix = testFilesDetailsText === '' ? '' : ` ${testFilesDetailsText}`\n if (testsResultsSummary.passes === testsResultsSummary.total) {\n out(chalk.mediumgreen(`${testFilesText}`) + testFilesDetailsSuffix)\n } else {\n out(chalk.mediumred(`${testFilesText}`) + testFilesDetailsSuffix)\n }\n\n const summaryLines = [\n testsText,\n joinPlain(describesText, invalidDescribesPlain, describesThrownPlain),\n joinPlain(testFilesText, invalidTestFilesPlain, failedToLoadPlain)\n ]\n\n const durationMs = new Date().getTime() - runStartTime\n\n if (allPassed) {\n writeStatusFile(\n config, statusCodes.passed, 'all tests passed', summaryLines, durationMs\n )\n agentDone(\n config, agentRun, statusCodes.passed, 'all tests passed',\n testsResultsSummary, durationMs, state.failedTestFiles.size\n )\n } else {\n const abortedFiles = Object.keys(erroringTests)\n\n // a file that would not load, or a describe that threw, means the run died\n // partway - a different problem from tests that ran and failed\n const aborted = abortedFiles.length > 0 || describesThrownCount > 0\n const failedTestsCount = testsResultsSummary.itsTotal - testsResultsSummary.itsPasses\n\n const description = [\n plural(abortedFiles.length, 'test file', 'failed to load or errored'),\n plural(describesThrownCount, 'describe', 'errored'),\n plural(failedTestsCount, 'test', 'failed')\n ].filter(part => part !== '').join(', ') || 'test run failed'\n\n const code = (aborted) ? statusCodes.aborted : statusCodes.failed\n const failures = failureEntries(Object.values(runTestResults), erroringTests)\n\n writeStatusFile(\n config,\n code,\n description,\n [...summaryLines, ...failureLines(Object.values(runTestResults), erroringTests)],\n durationMs\n )\n\n // failures first, so the done line is a complete end of run marker\n for (const failure of failures) agentFailure(config, agentRun, failure)\n agentDone(\n config, agentRun, code, description, testsResultsSummary, durationMs,\n state.failedTestFiles.size\n )\n }\n\n // full success?\n // true/false gets returned to the caller of runTests()\n return allPassed\n })\n } finally {\n if (reRunManager !== undefined) reRunManager.state.activeRuns--\n }\n}\n\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FinalConfig } from '../../types.js';
|
|
2
|
+
export declare const statusCodes: {
|
|
3
|
+
readonly notRunYet: -1;
|
|
4
|
+
readonly passed: 0;
|
|
5
|
+
readonly failed: 1;
|
|
6
|
+
readonly aborted: 2;
|
|
7
|
+
readonly couldNotRun: 3;
|
|
8
|
+
};
|
|
9
|
+
export type StatusCode = typeof statusCodes[keyof typeof statusCodes];
|
|
10
|
+
export declare function resetStatusFile(config: FinalConfig): void;
|
|
11
|
+
export declare function writeStatusFile(config: FinalConfig, code: StatusCode, description: string, details?: string[], durationMs?: number): void;
|
|
12
|
+
//# sourceMappingURL=statusFile.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import chalk from '../../packages/chalk.js';
|
|
4
|
+
import { packageName } from '../../config.js';
|
|
5
|
+
import { log } from '../../output.js';
|
|
6
|
+
// The status file holds the result of the latest run: `<code> - <description>` on the first
|
|
7
|
+
// line, then any detail. Watch mode resets it to -1 on startup so a stale result is never
|
|
8
|
+
// mistaken for the current one.
|
|
9
|
+
export const statusCodes = {
|
|
10
|
+
notRunYet: -1, // watch mode has started, but no run has finished
|
|
11
|
+
passed: 0,
|
|
12
|
+
failed: 1, // tests ran and failed
|
|
13
|
+
aborted: 2, // the run died partway - a test file failed to load, or a describe threw
|
|
14
|
+
couldNotRun: 3 // nothing ran at all - no test files, or no match for the filters
|
|
15
|
+
};
|
|
16
|
+
export function resetStatusFile(config) {
|
|
17
|
+
writeStatusFile(config, statusCodes.notRunYet, 'no run has finished yet');
|
|
18
|
+
}
|
|
19
|
+
export function writeStatusFile(config, code, description, details = [], durationMs) {
|
|
20
|
+
write(config, [
|
|
21
|
+
`${code} - ${description}`,
|
|
22
|
+
localTime(new Date()),
|
|
23
|
+
...details,
|
|
24
|
+
...(durationMs === undefined) ? [] : [`${durationMs.toLocaleString()}ms`]
|
|
25
|
+
].join('\n') + '\n');
|
|
26
|
+
}
|
|
27
|
+
// local time, so the file reads the way the terminal beside it does, with the offset so a
|
|
28
|
+
// reader elsewhere can still place it
|
|
29
|
+
function localTime(date) {
|
|
30
|
+
const pad = (value) => String(value).padStart(2, '0');
|
|
31
|
+
// getTimezoneOffset() counts minutes behind UTC, so the sign is the other way round
|
|
32
|
+
const offsetMinutes = -date.getTimezoneOffset();
|
|
33
|
+
const offset = `${(offsetMinutes < 0) ? '-' : '+'}`
|
|
34
|
+
+ `${pad(Math.floor(Math.abs(offsetMinutes) / 60))}:${pad(Math.abs(offsetMinutes) % 60)}`;
|
|
35
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
|
|
36
|
+
+ ` ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
|
|
37
|
+
+ ` ${offset}`;
|
|
38
|
+
}
|
|
39
|
+
function write(config, contents) {
|
|
40
|
+
const statusFile = config.watch.statusFile;
|
|
41
|
+
if (typeof statusFile !== 'string' || statusFile === '')
|
|
42
|
+
return;
|
|
43
|
+
const location = path.resolve(process.cwd(), statusFile);
|
|
44
|
+
// written via a temp file and renamed, so a poller never reads a half written status
|
|
45
|
+
const tempLocation = `${location}.${process.pid}.tmp`;
|
|
46
|
+
try {
|
|
47
|
+
fs.mkdirSync(path.dirname(location), { recursive: true });
|
|
48
|
+
fs.writeFileSync(tempLocation, contents);
|
|
49
|
+
fs.renameSync(tempLocation, location);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
// never let the status file take the run down with it
|
|
53
|
+
log(chalk.mediumred(`[${packageName}] Could not write status file ${location}: ${String(error)}`));
|
|
54
|
+
try {
|
|
55
|
+
fs.rmSync(tempLocation, { force: true });
|
|
56
|
+
}
|
|
57
|
+
catch { /* nothing more to do */ }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=statusFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusFile.js","sourceRoot":"","sources":["../../../src/cli/lib/statusFile.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs'\nimport path from 'path'\n\nimport chalk from '../../packages/chalk.js'\nimport { packageName } from '../../config.js'\nimport { log } from '../../output.js'\n\nimport type { FinalConfig } from '../../types.js'\n\n// The status file holds the result of the latest run: `<code> - <description>` on the first\n// line, then any detail. Watch mode resets it to -1 on startup so a stale result is never\n// mistaken for the current one.\nexport const statusCodes = {\n notRunYet: -1, // watch mode has started, but no run has finished\n passed: 0,\n failed: 1, // tests ran and failed\n aborted: 2, // the run died partway - a test file failed to load, or a describe threw\n couldNotRun: 3 // nothing ran at all - no test files, or no match for the filters\n} as const\n\nexport type StatusCode = typeof statusCodes[keyof typeof statusCodes]\n\nexport function resetStatusFile(config: FinalConfig): void {\n writeStatusFile(config, statusCodes.notRunYet, 'no run has finished yet')\n}\n\nexport function writeStatusFile(\n config: FinalConfig,\n code: StatusCode,\n description: string,\n details: string[] = [],\n durationMs?: number\n): void {\n write(config, [\n `${code} - ${description}`,\n localTime(new Date()),\n ...details,\n ...(durationMs === undefined) ? [] : [`${durationMs.toLocaleString()}ms`]\n ].join('\\n') + '\\n')\n}\n\n// local time, so the file reads the way the terminal beside it does, with the offset so a\n// reader elsewhere can still place it\nfunction localTime(date: Date): string {\n const pad = (value: number): string => String(value).padStart(2, '0')\n // getTimezoneOffset() counts minutes behind UTC, so the sign is the other way round\n const offsetMinutes = -date.getTimezoneOffset()\n const offset = `${(offsetMinutes < 0) ? '-' : '+'}`\n + `${pad(Math.floor(Math.abs(offsetMinutes) / 60))}:${pad(Math.abs(offsetMinutes) % 60)}`\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n + ` ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`\n + ` ${offset}`\n}\n\nfunction write(config: FinalConfig, contents: string): void {\n const statusFile = config.watch.statusFile\n if (typeof statusFile !== 'string' || statusFile === '') return\n\n const location = path.resolve(process.cwd(), statusFile)\n // written via a temp file and renamed, so a poller never reads a half written status\n const tempLocation = `${location}.${process.pid}.tmp`\n try {\n fs.mkdirSync(path.dirname(location), { recursive: true })\n fs.writeFileSync(tempLocation, contents)\n fs.renameSync(tempLocation, location)\n } catch (error) {\n // never let the status file take the run down with it\n log(chalk.mediumred(\n `[${packageName}] Could not write status file ${location}: ${String(error)}`\n ))\n try { fs.rmSync(tempLocation, { force: true }) } catch { /* nothing more to do */ }\n }\n}\n"]}
|
|
@@ -20,5 +20,12 @@ export function validateConfig(config, customOut) {
|
|
|
20
20
|
if (typeof config.watch.ttyActionsOnKeypress !== 'boolean') {
|
|
21
21
|
doError('Config error, config.watch.ttyActionsOnKeypress should be a boolean');
|
|
22
22
|
}
|
|
23
|
+
const statusFile = config.watch.statusFile;
|
|
24
|
+
if (statusFile !== false && (typeof statusFile !== 'string' || statusFile === '')) {
|
|
25
|
+
doError('Config error, config.watch.statusFile should be false or a file path');
|
|
26
|
+
}
|
|
27
|
+
if (typeof config.watch.agent !== 'boolean') {
|
|
28
|
+
doError('Config error, config.watch.agent should be a boolean');
|
|
29
|
+
}
|
|
23
30
|
}
|
|
24
31
|
//# sourceMappingURL=validateConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/validateConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAGhD,MAAM,UAAU,cAAc,CAAC,MAAmB,EAAE,SAAiB;IACjE,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAA;IAEhC,SAAS,OAAO,CAAC,OAAe;QAC5B,GAAG,CAAC,OAAO,CAAC,CAAA;QACZ,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,CAAC,+CAA+C,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;QAC3F,OAAO,CAAC,mFAAmF,CAAC,CAAA;IAChG,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,CAAC,qEAAqE,CAAC,CAAA;IAClF,CAAC;AACL,CAAC","sourcesContent":["import { out as mainOut } from '../../output.js'\nimport type { FinalConfig, OutFn } from '../../types.js'\n\nexport function validateConfig(config: FinalConfig, customOut?: OutFn): void {\n const out = customOut ?? mainOut\n\n function doError(message: string): never {\n out(message)\n throw new Error(message)\n }\n\n if (config.execution === undefined) {\n doError('Config error, config.execution is not defined')\n }\n\n if (config.execution.files !== 'parallel' && config.execution.files !== 'sequential') {\n doError('Config error, config.execution.files should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.describes !== 'parallel' && config.execution.describes !== 'sequential') {\n doError('Config error, config.execution.describes should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.tests !== 'parallel' && config.execution.tests !== 'sequential') {\n doError('Config error, config.execution.tests should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (typeof config.watch.ttyActionsOnKeypress !== 'boolean') {\n doError('Config error, config.watch.ttyActionsOnKeypress should be a boolean')\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validateConfig.js","sourceRoot":"","sources":["../../../src/cli/lib/validateConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAGhD,MAAM,UAAU,cAAc,CAAC,MAAmB,EAAE,SAAiB;IACjE,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAA;IAEhC,SAAS,OAAO,CAAC,OAAe;QAC5B,GAAG,CAAC,OAAO,CAAC,CAAA;QACZ,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,CAAC,+CAA+C,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;QAC3F,OAAO,CAAC,mFAAmF,CAAC,CAAA;IAChG,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,KAAK,YAAY,EAAE,CAAC;QACnF,OAAO,CAAC,+EAA+E,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACzD,OAAO,CAAC,qEAAqE,CAAC,CAAA;IAClF,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAA;IAC1C,IAAI,UAAU,KAAK,KAAK,IAAI,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,EAAE,CAAC,EAAE,CAAC;QAChF,OAAO,CAAC,sEAAsE,CAAC,CAAA;IACnF,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,CAAC,sDAAsD,CAAC,CAAA;IACnE,CAAC;AACL,CAAC","sourcesContent":["import { out as mainOut } from '../../output.js'\nimport type { FinalConfig, OutFn } from '../../types.js'\n\nexport function validateConfig(config: FinalConfig, customOut?: OutFn): void {\n const out = customOut ?? mainOut\n\n function doError(message: string): never {\n out(message)\n throw new Error(message)\n }\n\n if (config.execution === undefined) {\n doError('Config error, config.execution is not defined')\n }\n\n if (config.execution.files !== 'parallel' && config.execution.files !== 'sequential') {\n doError('Config error, config.execution.files should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.describes !== 'parallel' && config.execution.describes !== 'sequential') {\n doError('Config error, config.execution.describes should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (config.execution.tests !== 'parallel' && config.execution.tests !== 'sequential') {\n doError('Config error, config.execution.tests should be \\'parallel\\' or \\'sequential\\'')\n }\n\n if (typeof config.watch.ttyActionsOnKeypress !== 'boolean') {\n doError('Config error, config.watch.ttyActionsOnKeypress should be a boolean')\n }\n\n const statusFile = config.watch.statusFile\n if (statusFile !== false && (typeof statusFile !== 'string' || statusFile === '')) {\n doError('Config error, config.watch.statusFile should be false or a file path')\n }\n\n if (typeof config.watch.agent !== 'boolean') {\n doError('Config error, config.watch.agent should be a boolean')\n }\n}\n"]}
|
|
@@ -3,7 +3,8 @@ import { showTimeProfiling } from '../../config.js';
|
|
|
3
3
|
import chalk from '../../packages/chalk.js';
|
|
4
4
|
import minimatch from 'minimatch';
|
|
5
5
|
import slash from '../../packages/slash.js';
|
|
6
|
-
import { out, log, debug } from '../../output.js';
|
|
6
|
+
import { out as mainOut, log, debug } from '../../output.js';
|
|
7
|
+
import { agentChange } from './agentReport.js';
|
|
7
8
|
import { runTests } from './runTests.js';
|
|
8
9
|
import { buildDependencyTree } from './buildDependencyTree.js';
|
|
9
10
|
import { globArgCombine } from './globArgCombine.js';
|
|
@@ -17,6 +18,8 @@ dependencyTrees, failingTests, reRunManager,
|
|
|
17
18
|
//watchRunState: WatchRunState,
|
|
18
19
|
customOut, executionFilters = {}) {
|
|
19
20
|
const projectDir = process.cwd();
|
|
21
|
+
// agent mode passes a sink here, so its own change lines are the only ones printed
|
|
22
|
+
const out = customOut ?? mainOut;
|
|
20
23
|
await timeProfileAsync('init watching', async () => {
|
|
21
24
|
debug('failingTests', failingTests);
|
|
22
25
|
const testsGlobs = addBasePath(config.testsBase, config.tests);
|
|
@@ -49,6 +52,7 @@ customOut, executionFilters = {}) {
|
|
|
49
52
|
}
|
|
50
53
|
// info on the event found
|
|
51
54
|
out(chalk.grey `change: ${filename} (${event})`);
|
|
55
|
+
agentChange(config, filename, event);
|
|
52
56
|
// add the file to changed files
|
|
53
57
|
changedFiles.push([filename, event]);
|
|
54
58
|
// wait 100ms after any change before processing, to avoid multiple execution?
|
|
@@ -92,29 +96,26 @@ customOut, executionFilters = {}) {
|
|
|
92
96
|
if (tests.size > 0) {
|
|
93
97
|
await timeProfileAsync('build list of files to test and request a run', async () => {
|
|
94
98
|
debug('tests', tests);
|
|
95
|
-
// NOTE: the original guarded this cleanup with `config.reRunFailingTests`
|
|
96
|
-
// (missing the `.watch.` prefix every other reference here uses), which is
|
|
97
|
-
// always undefined - so this block never ran. Preserved as dead code rather
|
|
98
|
-
// than newly activating it as part of a TS conversion.
|
|
99
|
-
debug('tests', tests);
|
|
100
|
-
debug('failingTests', failingTests);
|
|
101
99
|
debug('reRunFailingTests', config.watch.reRunFailingTests);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
100
|
+
// changes accumulate here because an 'auto' request made while a
|
|
101
|
+
// run is in flight is coalesced into the queued one - everything
|
|
102
|
+
// edited in the meantime still has to be covered
|
|
103
|
+
reRunManager.state.untestedFiles
|
|
104
|
+
= reRunManager.state.untestedFiles.union(tests);
|
|
105
|
+
reRunManager.requestRun('auto', () => {
|
|
106
|
+
// resolved when the run actually starts, not when it is
|
|
107
|
+
// queued, so a coalesced request picks up the later edits
|
|
108
|
+
const toTest = (config.watch.reRunFailingTests)
|
|
109
|
+
? reRunManager.state.untestedFiles
|
|
110
|
+
.union(reRunManager.state.failedTestFiles)
|
|
111
|
+
: new Set(reRunManager.state.untestedFiles);
|
|
112
|
+
// consumed by this run - without this they are retested
|
|
113
|
+
// on every later run for the rest of the session
|
|
114
|
+
reRunManager.state.untestedFiles = new Set();
|
|
115
|
+
debug('run tests on change');
|
|
116
|
+
debug('toTest', toTest);
|
|
117
|
+
return runTests(config, toTest, reRunManager, 'refresh', customOut, executionFilters);
|
|
118
|
+
});
|
|
118
119
|
});
|
|
119
120
|
}
|
|
120
121
|
}
|