@jsenv/test 3.7.54 → 3.7.55
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/dist/jsenv_test.js
CHANGED
|
@@ -5731,6 +5731,11 @@ const isV8Coverage = (coverage) => Boolean(coverage.result);
|
|
|
5731
5731
|
*
|
|
5732
5732
|
* Only the start order is affected: executions keep the index they got from the
|
|
5733
5733
|
* filesystem, so they are still reported in that order.
|
|
5734
|
+
*
|
|
5735
|
+
* The duration of the whole run is remembered too, so the logs can tell how
|
|
5736
|
+
* long the wait will likely be. It is kept per run name (what the run was
|
|
5737
|
+
* narrowed to): the duration of every test in the repository says nothing about
|
|
5738
|
+
* the duration of the tests of one package.
|
|
5734
5739
|
*/
|
|
5735
5740
|
|
|
5736
5741
|
|
|
@@ -5739,10 +5744,24 @@ const MS_IN_A_DAY = 24 * 60 * 60 * 1000;
|
|
|
5739
5744
|
const ENTRY_MAX_AGE_MS = 30 * MS_IN_A_DAY;
|
|
5740
5745
|
|
|
5741
5746
|
const createExecutionTimings = ({ fileUrl }) => {
|
|
5742
|
-
const previousEntryMap =
|
|
5747
|
+
const { previousEntryMap, previousRunEntryMap } = readMemory(fileUrl);
|
|
5743
5748
|
const entryMap = new Map();
|
|
5749
|
+
const runEntryMap = new Map();
|
|
5744
5750
|
|
|
5745
5751
|
return {
|
|
5752
|
+
getRunDurationMs: (runName) => {
|
|
5753
|
+
const previousRunEntry = previousRunEntryMap.get(runName);
|
|
5754
|
+
if (!previousRunEntry) {
|
|
5755
|
+
return null;
|
|
5756
|
+
}
|
|
5757
|
+
return previousRunEntry.durationMs;
|
|
5758
|
+
},
|
|
5759
|
+
recordRun: (runName, durationMs) => {
|
|
5760
|
+
runEntryMap.set(runName, {
|
|
5761
|
+
durationMs,
|
|
5762
|
+
updatedAt: Date.now(),
|
|
5763
|
+
});
|
|
5764
|
+
},
|
|
5746
5765
|
getAllocatedMsRequested: (executionName) => {
|
|
5747
5766
|
const previousEntry = previousEntryMap.get(executionName);
|
|
5748
5767
|
if (!previousEntry) {
|
|
@@ -5803,47 +5822,69 @@ const createExecutionTimings = ({ fileUrl }) => {
|
|
|
5803
5822
|
},
|
|
5804
5823
|
write: () => {
|
|
5805
5824
|
const nowMs = Date.now();
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5825
|
+
writeFileSync(
|
|
5826
|
+
fileUrl,
|
|
5827
|
+
JSON.stringify(
|
|
5828
|
+
{
|
|
5829
|
+
// what is not part of this run keeps what was known about it
|
|
5830
|
+
executions: mergeEntries(previousEntryMap, entryMap, nowMs),
|
|
5831
|
+
runs: mergeEntries(previousRunEntryMap, runEntryMap, nowMs),
|
|
5832
|
+
},
|
|
5833
|
+
null,
|
|
5834
|
+
" ",
|
|
5835
|
+
),
|
|
5836
|
+
);
|
|
5817
5837
|
},
|
|
5818
5838
|
};
|
|
5819
5839
|
};
|
|
5820
5840
|
|
|
5821
|
-
const
|
|
5822
|
-
const
|
|
5841
|
+
const mergeEntries = (previousEntryMap, entryMap, nowMs) => {
|
|
5842
|
+
const entries = {};
|
|
5843
|
+
for (const [name, entry] of previousEntryMap) {
|
|
5844
|
+
if (nowMs - entry.updatedAt < ENTRY_MAX_AGE_MS) {
|
|
5845
|
+
entries[name] = entry;
|
|
5846
|
+
}
|
|
5847
|
+
}
|
|
5848
|
+
for (const [name, entry] of entryMap) {
|
|
5849
|
+
entries[name] = entry;
|
|
5850
|
+
}
|
|
5851
|
+
return entries;
|
|
5852
|
+
};
|
|
5853
|
+
|
|
5854
|
+
const readMemory = (fileUrl) => {
|
|
5855
|
+
const previousEntryMap = new Map();
|
|
5856
|
+
const previousRunEntryMap = new Map();
|
|
5857
|
+
const memory = { previousEntryMap, previousRunEntryMap };
|
|
5823
5858
|
let fileContent;
|
|
5824
5859
|
try {
|
|
5825
5860
|
fileContent = readFileSync(new URL(fileUrl), "utf8");
|
|
5826
5861
|
} catch {
|
|
5827
5862
|
// no memory of a previous run: every execution is an unknown
|
|
5828
|
-
return
|
|
5863
|
+
return memory;
|
|
5829
5864
|
}
|
|
5830
5865
|
let executions;
|
|
5866
|
+
let runs;
|
|
5831
5867
|
try {
|
|
5832
|
-
({ executions } = JSON.parse(fileContent));
|
|
5868
|
+
({ executions, runs } = JSON.parse(fileContent));
|
|
5833
5869
|
} catch {
|
|
5834
5870
|
// file was truncated by a run killed while writing it
|
|
5835
|
-
return
|
|
5871
|
+
return memory;
|
|
5836
5872
|
}
|
|
5837
|
-
|
|
5838
|
-
|
|
5873
|
+
fillEntryMap(previousEntryMap, executions);
|
|
5874
|
+
fillEntryMap(previousRunEntryMap, runs);
|
|
5875
|
+
return memory;
|
|
5876
|
+
};
|
|
5877
|
+
|
|
5878
|
+
const fillEntryMap = (entryMap, entries) => {
|
|
5879
|
+
if (!entries) {
|
|
5880
|
+
return;
|
|
5839
5881
|
}
|
|
5840
|
-
for (const
|
|
5841
|
-
const entry =
|
|
5882
|
+
for (const name of Object.keys(entries)) {
|
|
5883
|
+
const entry = entries[name];
|
|
5842
5884
|
if (typeof entry.durationMs === "number") {
|
|
5843
|
-
entryMap.set(
|
|
5885
|
+
entryMap.set(name, entry);
|
|
5844
5886
|
}
|
|
5845
5887
|
}
|
|
5846
|
-
return entryMap;
|
|
5847
5888
|
};
|
|
5848
5889
|
|
|
5849
5890
|
const githubAnnotationFromError = (
|
|
@@ -6486,11 +6527,19 @@ const reporterList = ({
|
|
|
6486
6527
|
|
|
6487
6528
|
const msEllapsed = Date.now() - startMs;
|
|
6488
6529
|
const infos = [];
|
|
6489
|
-
|
|
6530
|
+
let duration = humanizeDuration(msEllapsed, {
|
|
6490
6531
|
short: true,
|
|
6491
6532
|
decimals: 0,
|
|
6492
6533
|
rounded: false,
|
|
6493
6534
|
});
|
|
6535
|
+
const { previousRunEnd } = testPlanResult.timings;
|
|
6536
|
+
if (previousRunEnd !== null) {
|
|
6537
|
+
duration += ` of ~${humanizeDuration(previousRunEnd, {
|
|
6538
|
+
short: true,
|
|
6539
|
+
decimals: 0,
|
|
6540
|
+
rounded: false,
|
|
6541
|
+
})}`;
|
|
6542
|
+
}
|
|
6494
6543
|
infos.push(ANSI.color(duration, ANSI.GREY));
|
|
6495
6544
|
let memoryUsageColor = ANSI.GREY;
|
|
6496
6545
|
const memoryHeapUsed = memoryUsage().heapUsed;
|
|
@@ -6680,6 +6729,16 @@ const renderIntro = (testPlanResult, logOptions) => {
|
|
|
6680
6729
|
`fragment: ${testPlanResult.fragment}, executing only ${testPlanResult.fragmentStart}:${testPlanResult.fragmentEnd}`,
|
|
6681
6730
|
);
|
|
6682
6731
|
}
|
|
6732
|
+
const { previousRunEnd } = testPlanResult.timings;
|
|
6733
|
+
if (previousRunEnd !== null) {
|
|
6734
|
+
lines.push(
|
|
6735
|
+
`previous run: ${
|
|
6736
|
+
logOptions.mockFluctuatingValues
|
|
6737
|
+
? "<mock>s"
|
|
6738
|
+
: humanizeDuration(previousRunEnd, { short: true })
|
|
6739
|
+
}`,
|
|
6740
|
+
);
|
|
6741
|
+
}
|
|
6683
6742
|
if (logOptions.platformInfo) {
|
|
6684
6743
|
{
|
|
6685
6744
|
let osLine = `os: `;
|
|
@@ -7866,7 +7925,7 @@ const ensureWebServerIsStarted = async (
|
|
|
7866
7925
|
* @param {Object} [testPlanParameters.webServer] Web server info; required when executing test on browsers
|
|
7867
7926
|
* @param {Object} testPlanParameters.testPlan Object associating files with runtimes where they will be executed
|
|
7868
7927
|
* @param {Object|false} [testPlanParameters.parallel] Maximum amount of execution running at the same time
|
|
7869
|
-
* @param {Object|false} [testPlanParameters.executionTimings=false] Remembers how long executions took; on the next run "parallel.maxAhead" uses it to start the longest ones ahead of their turn
|
|
7928
|
+
* @param {Object|false} [testPlanParameters.executionTimings=false] Remembers how long executions took; on the next run "parallel.maxAhead" uses it to start the longest ones ahead of their turn, and the logs show how long the previous run took
|
|
7870
7929
|
* @param {number} [testPlanParameters.defaultMsAllocatedPerExecution=30000] Milliseconds after which execution is aborted and considered as failed by timeout
|
|
7871
7930
|
* @param {boolean} [testPlanParameters.failFast=false] Fails immediatly when a test execution fails
|
|
7872
7931
|
* @param {Object|false} [testPlanParameters.coverage=false] Controls if coverage is collected during files executions
|
|
@@ -8047,6 +8106,8 @@ const executeTestPlan = async ({
|
|
|
8047
8106
|
teardownEnd: null,
|
|
8048
8107
|
coverageTeardownEnd: null,
|
|
8049
8108
|
end: null,
|
|
8109
|
+
// "end" of the previous run with the same name (see "executionTimings")
|
|
8110
|
+
previousRunEnd: null,
|
|
8050
8111
|
},
|
|
8051
8112
|
rootDirectoryUrl: String(rootDirectoryUrl),
|
|
8052
8113
|
patterns: Object.keys(testPlan),
|
|
@@ -8126,6 +8187,7 @@ const executeTestPlan = async ({
|
|
|
8126
8187
|
const afterAllCallbackSet = new Set();
|
|
8127
8188
|
let finalizeCoverage;
|
|
8128
8189
|
let timingsMemory;
|
|
8190
|
+
let runName;
|
|
8129
8191
|
|
|
8130
8192
|
try {
|
|
8131
8193
|
let logger;
|
|
@@ -8570,6 +8632,13 @@ To fix this warning:
|
|
|
8570
8632
|
onlyWithinUrl = new URL(onlyWithin, rootDirectoryUrl);
|
|
8571
8633
|
}
|
|
8572
8634
|
}
|
|
8635
|
+
// what the run is narrowed to decides how long it takes
|
|
8636
|
+
runName = onlyWithinUrl
|
|
8637
|
+
? urlToRelativeUrl(onlyWithinUrl, rootDirectoryUrl) || "./"
|
|
8638
|
+
: "./";
|
|
8639
|
+
if (fragment) {
|
|
8640
|
+
runName += `?fragment=${fragment}`;
|
|
8641
|
+
}
|
|
8573
8642
|
|
|
8574
8643
|
let index = 0;
|
|
8575
8644
|
let lastExecution;
|
|
@@ -8770,6 +8839,9 @@ To fix this warning:
|
|
|
8770
8839
|
countersInOrder.remaining =
|
|
8771
8840
|
countersInOrder.waiting =
|
|
8772
8841
|
executionPlanifiedArray.length;
|
|
8842
|
+
if (timingsMemory) {
|
|
8843
|
+
timings.previousRunEnd = timingsMemory.getRunDurationMs(runName);
|
|
8844
|
+
}
|
|
8773
8845
|
if (githubCheck) {
|
|
8774
8846
|
const githubCheckRun = await startGithubCheckRun({
|
|
8775
8847
|
logLevel: githubCheck.logLevel,
|
|
@@ -9186,16 +9258,21 @@ To fix this warning:
|
|
|
9186
9258
|
}
|
|
9187
9259
|
timings.teardownEnd = takeTiming();
|
|
9188
9260
|
|
|
9189
|
-
if (timingsMemory) {
|
|
9190
|
-
timingsMemory.write();
|
|
9191
|
-
}
|
|
9192
|
-
|
|
9193
9261
|
if (finalizeCoverage) {
|
|
9194
9262
|
await finalizeCoverage();
|
|
9195
9263
|
}
|
|
9196
9264
|
timings.coverageTeardownEnd = takeTiming();
|
|
9197
9265
|
timings.end = takeTiming();
|
|
9198
9266
|
|
|
9267
|
+
if (timingsMemory) {
|
|
9268
|
+
// a run stopped before its end (aborted, failFast, an error) says nothing
|
|
9269
|
+
// about how long the next one takes
|
|
9270
|
+
if (timings.executionEnd !== null && !testPlanResult.aborted) {
|
|
9271
|
+
timingsMemory.recordRun(runName, timings.end);
|
|
9272
|
+
}
|
|
9273
|
+
timingsMemory.write();
|
|
9274
|
+
}
|
|
9275
|
+
|
|
9199
9276
|
osMemoryUsageMonitoring.end();
|
|
9200
9277
|
processMemoryUsageMonitoring.end();
|
|
9201
9278
|
osCpuUsageMonitoring.end();
|
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
startMonitoringMemoryUsage,
|
|
28
28
|
} from "@jsenv/os-metrics";
|
|
29
29
|
import { URL_META } from "@jsenv/url-meta";
|
|
30
|
-
import { urlIsOrIsInsideOf } from "@jsenv/urls";
|
|
30
|
+
import { urlIsOrIsInsideOf, urlToRelativeUrl } from "@jsenv/urls";
|
|
31
31
|
import { existsSync } from "node:fs";
|
|
32
32
|
import { takeCoverage } from "node:v8";
|
|
33
33
|
import stripAnsi from "strip-ansi";
|
|
@@ -47,7 +47,7 @@ import { assertAndNormalizeWebServer } from "./web_server_param.js";
|
|
|
47
47
|
* @param {Object} [testPlanParameters.webServer] Web server info; required when executing test on browsers
|
|
48
48
|
* @param {Object} testPlanParameters.testPlan Object associating files with runtimes where they will be executed
|
|
49
49
|
* @param {Object|false} [testPlanParameters.parallel] Maximum amount of execution running at the same time
|
|
50
|
-
* @param {Object|false} [testPlanParameters.executionTimings=false] Remembers how long executions took; on the next run "parallel.maxAhead" uses it to start the longest ones ahead of their turn
|
|
50
|
+
* @param {Object|false} [testPlanParameters.executionTimings=false] Remembers how long executions took; on the next run "parallel.maxAhead" uses it to start the longest ones ahead of their turn, and the logs show how long the previous run took
|
|
51
51
|
* @param {number} [testPlanParameters.defaultMsAllocatedPerExecution=30000] Milliseconds after which execution is aborted and considered as failed by timeout
|
|
52
52
|
* @param {boolean} [testPlanParameters.failFast=false] Fails immediatly when a test execution fails
|
|
53
53
|
* @param {Object|false} [testPlanParameters.coverage=false] Controls if coverage is collected during files executions
|
|
@@ -228,6 +228,8 @@ export const executeTestPlan = async ({
|
|
|
228
228
|
teardownEnd: null,
|
|
229
229
|
coverageTeardownEnd: null,
|
|
230
230
|
end: null,
|
|
231
|
+
// "end" of the previous run with the same name (see "executionTimings")
|
|
232
|
+
previousRunEnd: null,
|
|
231
233
|
},
|
|
232
234
|
rootDirectoryUrl: String(rootDirectoryUrl),
|
|
233
235
|
patterns: Object.keys(testPlan),
|
|
@@ -307,6 +309,7 @@ export const executeTestPlan = async ({
|
|
|
307
309
|
const afterAllCallbackSet = new Set();
|
|
308
310
|
let finalizeCoverage;
|
|
309
311
|
let timingsMemory;
|
|
312
|
+
let runName;
|
|
310
313
|
|
|
311
314
|
try {
|
|
312
315
|
let logger;
|
|
@@ -751,6 +754,13 @@ To fix this warning:
|
|
|
751
754
|
onlyWithinUrl = new URL(onlyWithin, rootDirectoryUrl);
|
|
752
755
|
}
|
|
753
756
|
}
|
|
757
|
+
// what the run is narrowed to decides how long it takes
|
|
758
|
+
runName = onlyWithinUrl
|
|
759
|
+
? urlToRelativeUrl(onlyWithinUrl, rootDirectoryUrl) || "./"
|
|
760
|
+
: "./";
|
|
761
|
+
if (fragment) {
|
|
762
|
+
runName += `?fragment=${fragment}`;
|
|
763
|
+
}
|
|
754
764
|
|
|
755
765
|
let index = 0;
|
|
756
766
|
let lastExecution;
|
|
@@ -951,6 +961,9 @@ To fix this warning:
|
|
|
951
961
|
countersInOrder.remaining =
|
|
952
962
|
countersInOrder.waiting =
|
|
953
963
|
executionPlanifiedArray.length;
|
|
964
|
+
if (timingsMemory) {
|
|
965
|
+
timings.previousRunEnd = timingsMemory.getRunDurationMs(runName);
|
|
966
|
+
}
|
|
954
967
|
if (githubCheck) {
|
|
955
968
|
const githubCheckRun = await startGithubCheckRun({
|
|
956
969
|
logLevel: githubCheck.logLevel,
|
|
@@ -1368,16 +1381,21 @@ To fix this warning:
|
|
|
1368
1381
|
}
|
|
1369
1382
|
timings.teardownEnd = takeTiming();
|
|
1370
1383
|
|
|
1371
|
-
if (timingsMemory) {
|
|
1372
|
-
timingsMemory.write();
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
1384
|
if (finalizeCoverage) {
|
|
1376
1385
|
await finalizeCoverage();
|
|
1377
1386
|
}
|
|
1378
1387
|
timings.coverageTeardownEnd = takeTiming();
|
|
1379
1388
|
timings.end = takeTiming();
|
|
1380
1389
|
|
|
1390
|
+
if (timingsMemory) {
|
|
1391
|
+
// a run stopped before its end (aborted, failFast, an error) says nothing
|
|
1392
|
+
// about how long the next one takes
|
|
1393
|
+
if (timings.executionEnd !== null && !testPlanResult.aborted) {
|
|
1394
|
+
timingsMemory.recordRun(runName, timings.end);
|
|
1395
|
+
}
|
|
1396
|
+
timingsMemory.write();
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1381
1399
|
osMemoryUsageMonitoring.end();
|
|
1382
1400
|
processMemoryUsageMonitoring.end();
|
|
1383
1401
|
osCpuUsageMonitoring.end();
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Only the start order is affected: executions keep the index they got from the
|
|
12
12
|
* filesystem, so they are still reported in that order.
|
|
13
|
+
*
|
|
14
|
+
* The duration of the whole run is remembered too, so the logs can tell how
|
|
15
|
+
* long the wait will likely be. It is kept per run name (what the run was
|
|
16
|
+
* narrowed to): the duration of every test in the repository says nothing about
|
|
17
|
+
* the duration of the tests of one package.
|
|
13
18
|
*/
|
|
14
19
|
|
|
15
20
|
import { writeFileSync } from "@jsenv/filesystem";
|
|
@@ -20,10 +25,24 @@ const MS_IN_A_DAY = 24 * 60 * 60 * 1000;
|
|
|
20
25
|
const ENTRY_MAX_AGE_MS = 30 * MS_IN_A_DAY;
|
|
21
26
|
|
|
22
27
|
export const createExecutionTimings = ({ fileUrl }) => {
|
|
23
|
-
const previousEntryMap =
|
|
28
|
+
const { previousEntryMap, previousRunEntryMap } = readMemory(fileUrl);
|
|
24
29
|
const entryMap = new Map();
|
|
30
|
+
const runEntryMap = new Map();
|
|
25
31
|
|
|
26
32
|
return {
|
|
33
|
+
getRunDurationMs: (runName) => {
|
|
34
|
+
const previousRunEntry = previousRunEntryMap.get(runName);
|
|
35
|
+
if (!previousRunEntry) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return previousRunEntry.durationMs;
|
|
39
|
+
},
|
|
40
|
+
recordRun: (runName, durationMs) => {
|
|
41
|
+
runEntryMap.set(runName, {
|
|
42
|
+
durationMs,
|
|
43
|
+
updatedAt: Date.now(),
|
|
44
|
+
});
|
|
45
|
+
},
|
|
27
46
|
getAllocatedMsRequested: (executionName) => {
|
|
28
47
|
const previousEntry = previousEntryMap.get(executionName);
|
|
29
48
|
if (!previousEntry) {
|
|
@@ -84,45 +103,67 @@ export const createExecutionTimings = ({ fileUrl }) => {
|
|
|
84
103
|
},
|
|
85
104
|
write: () => {
|
|
86
105
|
const nowMs = Date.now();
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
106
|
+
writeFileSync(
|
|
107
|
+
fileUrl,
|
|
108
|
+
JSON.stringify(
|
|
109
|
+
{
|
|
110
|
+
// what is not part of this run keeps what was known about it
|
|
111
|
+
executions: mergeEntries(previousEntryMap, entryMap, nowMs),
|
|
112
|
+
runs: mergeEntries(previousRunEntryMap, runEntryMap, nowMs),
|
|
113
|
+
},
|
|
114
|
+
null,
|
|
115
|
+
" ",
|
|
116
|
+
),
|
|
117
|
+
);
|
|
98
118
|
},
|
|
99
119
|
};
|
|
100
120
|
};
|
|
101
121
|
|
|
102
|
-
const
|
|
103
|
-
const
|
|
122
|
+
const mergeEntries = (previousEntryMap, entryMap, nowMs) => {
|
|
123
|
+
const entries = {};
|
|
124
|
+
for (const [name, entry] of previousEntryMap) {
|
|
125
|
+
if (nowMs - entry.updatedAt < ENTRY_MAX_AGE_MS) {
|
|
126
|
+
entries[name] = entry;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
for (const [name, entry] of entryMap) {
|
|
130
|
+
entries[name] = entry;
|
|
131
|
+
}
|
|
132
|
+
return entries;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const readMemory = (fileUrl) => {
|
|
136
|
+
const previousEntryMap = new Map();
|
|
137
|
+
const previousRunEntryMap = new Map();
|
|
138
|
+
const memory = { previousEntryMap, previousRunEntryMap };
|
|
104
139
|
let fileContent;
|
|
105
140
|
try {
|
|
106
141
|
fileContent = readFileSync(new URL(fileUrl), "utf8");
|
|
107
142
|
} catch {
|
|
108
143
|
// no memory of a previous run: every execution is an unknown
|
|
109
|
-
return
|
|
144
|
+
return memory;
|
|
110
145
|
}
|
|
111
146
|
let executions;
|
|
147
|
+
let runs;
|
|
112
148
|
try {
|
|
113
|
-
({ executions } = JSON.parse(fileContent));
|
|
149
|
+
({ executions, runs } = JSON.parse(fileContent));
|
|
114
150
|
} catch {
|
|
115
151
|
// file was truncated by a run killed while writing it
|
|
116
|
-
return
|
|
152
|
+
return memory;
|
|
117
153
|
}
|
|
118
|
-
|
|
119
|
-
|
|
154
|
+
fillEntryMap(previousEntryMap, executions);
|
|
155
|
+
fillEntryMap(previousRunEntryMap, runs);
|
|
156
|
+
return memory;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const fillEntryMap = (entryMap, entries) => {
|
|
160
|
+
if (!entries) {
|
|
161
|
+
return;
|
|
120
162
|
}
|
|
121
|
-
for (const
|
|
122
|
-
const entry =
|
|
163
|
+
for (const name of Object.keys(entries)) {
|
|
164
|
+
const entry = entries[name];
|
|
123
165
|
if (typeof entry.durationMs === "number") {
|
|
124
|
-
entryMap.set(
|
|
166
|
+
entryMap.set(name, entry);
|
|
125
167
|
}
|
|
126
168
|
}
|
|
127
|
-
return entryMap;
|
|
128
169
|
};
|
|
@@ -137,11 +137,19 @@ export const reporterList = ({
|
|
|
137
137
|
|
|
138
138
|
const msEllapsed = Date.now() - startMs;
|
|
139
139
|
const infos = [];
|
|
140
|
-
|
|
140
|
+
let duration = humanizeDuration(msEllapsed, {
|
|
141
141
|
short: true,
|
|
142
142
|
decimals: 0,
|
|
143
143
|
rounded: false,
|
|
144
144
|
});
|
|
145
|
+
const { previousRunEnd } = testPlanResult.timings;
|
|
146
|
+
if (previousRunEnd !== null) {
|
|
147
|
+
duration += ` of ~${humanizeDuration(previousRunEnd, {
|
|
148
|
+
short: true,
|
|
149
|
+
decimals: 0,
|
|
150
|
+
rounded: false,
|
|
151
|
+
})}`;
|
|
152
|
+
}
|
|
145
153
|
infos.push(ANSI.color(duration, ANSI.GREY));
|
|
146
154
|
let memoryUsageColor = ANSI.GREY;
|
|
147
155
|
const memoryHeapUsed = processMemoryUsage().heapUsed;
|
|
@@ -331,6 +339,16 @@ const renderIntro = (testPlanResult, logOptions) => {
|
|
|
331
339
|
`fragment: ${testPlanResult.fragment}, executing only ${testPlanResult.fragmentStart}:${testPlanResult.fragmentEnd}`,
|
|
332
340
|
);
|
|
333
341
|
}
|
|
342
|
+
const { previousRunEnd } = testPlanResult.timings;
|
|
343
|
+
if (previousRunEnd !== null) {
|
|
344
|
+
lines.push(
|
|
345
|
+
`previous run: ${
|
|
346
|
+
logOptions.mockFluctuatingValues
|
|
347
|
+
? "<mock>s"
|
|
348
|
+
: humanizeDuration(previousRunEnd, { short: true })
|
|
349
|
+
}`,
|
|
350
|
+
);
|
|
351
|
+
}
|
|
334
352
|
if (logOptions.platformInfo) {
|
|
335
353
|
os_line: {
|
|
336
354
|
let osLine = `os: `;
|