@jsenv/test 3.0.28 → 3.2.0

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.
@@ -809,6 +809,9 @@ const createException = (reason, { rootDirectoryUrl } = {}) => {
809
809
 
810
810
  const stackFramesNonNative = [];
811
811
  for (const stackFrame of stackFrames) {
812
+ if (!stackFrame.url) {
813
+ continue;
814
+ }
812
815
  if (stackFrame.url.startsWith("node:")) {
813
816
  stackFrame.native = "node";
814
817
  continue;
@@ -4946,14 +4946,16 @@ const renderIntro = (testPlanResult, logOptions) => {
4946
4946
  ? "/mock/"
4947
4947
  : urlToFileSystemPath(testPlanResult.rootDirectoryUrl);
4948
4948
  const numberOfFiles = Object.keys(testPlanResult.results).length;
4949
+ const { counters } = testPlanResult;
4950
+ const { planified } = counters;
4949
4951
 
4950
4952
  let title;
4951
- if (numberOfFiles === 0) {
4953
+ if (planified === 0) {
4952
4954
  title = `no file to execute`;
4953
- } else if (numberOfFiles === 1) {
4954
- title = `1 file to execute`;
4955
+ } else if (planified === 1) {
4956
+ title = `1 execution planified`;
4955
4957
  } else {
4956
- title = `${numberOfFiles} files to execute`;
4958
+ title = `${planified} executions planified`;
4957
4959
  }
4958
4960
  const lines = [];
4959
4961
  lines.push(`directory: ${directory}`);
@@ -5335,8 +5337,16 @@ const renderOutro = (testPlanResult, logOptions = {}) => {
5335
5337
  if (planified === 0) {
5336
5338
  return "";
5337
5339
  }
5340
+ let title;
5341
+ if (planified === 0) {
5342
+ title = `no execution`;
5343
+ } else if (planified === 1) {
5344
+ title = `1 execution done`;
5345
+ } else {
5346
+ title = `${planified} executions done`;
5347
+ }
5338
5348
  return `${renderBigSection({
5339
- title: "",
5349
+ title,
5340
5350
  content: renderOutroContent(testPlanResult, logOptions),
5341
5351
  })}\n`;
5342
5352
  };
@@ -5344,17 +5354,8 @@ const renderOutro = (testPlanResult, logOptions = {}) => {
5344
5354
  const renderOutroContent = (testPlanResult, logOptions = {}) => {
5345
5355
  const lines = [];
5346
5356
  const { counters } = testPlanResult;
5347
- const { planified } = counters;
5348
5357
 
5349
- let executionLine = "";
5350
- if (planified === 0) {
5351
- executionLine += `no execution`;
5352
- } else if (planified === 1) {
5353
- executionLine += `1 execution: `;
5354
- } else {
5355
- executionLine += `${planified} executions: `;
5356
- }
5357
- executionLine += renderStatusRepartition(counters);
5358
+ let executionLine = `status: ${renderStatusRepartition(counters)}`;
5358
5359
  lines.push(executionLine);
5359
5360
 
5360
5361
  let durationLine = `duration: `;
@@ -6132,6 +6133,7 @@ To fix this warning:
6132
6133
  runtime,
6133
6134
  runtimeParams,
6134
6135
  allocatedMs = defaultMsAllocatedPerExecution,
6136
+ uses,
6135
6137
  } = stepConfig;
6136
6138
  const params = {
6137
6139
  measureMemoryUsage: true,
@@ -6139,6 +6141,7 @@ To fix this warning:
6139
6141
  collectPerformance: false,
6140
6142
  collectConsole: true,
6141
6143
  allocatedMs,
6144
+ uses,
6142
6145
  runtime,
6143
6146
  runtimeParams: {
6144
6147
  rootDirectoryUrl,
@@ -6168,6 +6171,7 @@ To fix this warning:
6168
6171
  }
6169
6172
 
6170
6173
  const execution = {
6174
+ name: `${relativeUrl}/${groupName}`,
6171
6175
  counters,
6172
6176
  countersInOrder,
6173
6177
  index,
@@ -6320,7 +6324,13 @@ To fix this warning:
6320
6324
 
6321
6325
  const executionRemainingSet = new Set(executionPlanifiedSet);
6322
6326
  const executionExecutingSet = new Set();
6327
+ const usedTagSet = new Set();
6323
6328
  const start = async (execution) => {
6329
+ if (execution.params.uses) {
6330
+ for (const tagThatWillBeUsed of execution.params.uses) {
6331
+ usedTagSet.add(tagThatWillBeUsed);
6332
+ }
6333
+ }
6324
6334
  execution.fileExecutionCount = Object.keys(
6325
6335
  testPlanResult.results[execution.fileRelativeUrl],
6326
6336
  ).length;
@@ -6340,7 +6350,6 @@ To fix this warning:
6340
6350
  afterEachCallbackSet.add(callback);
6341
6351
  }
6342
6352
  }
6343
-
6344
6353
  for (const beforeEachInOrderCallback of beforeEachInOrderCallbackSet) {
6345
6354
  const returnValue = beforeEachInOrderCallback(
6346
6355
  execution,
@@ -6373,7 +6382,6 @@ To fix this warning:
6373
6382
  process.exitCode = 1;
6374
6383
  }
6375
6384
  }
6376
-
6377
6385
  for (const afterEachCallback of afterEachCallbackSet) {
6378
6386
  afterEachCallback(execution, testPlanResult);
6379
6387
  }
@@ -6383,7 +6391,11 @@ To fix this warning:
6383
6391
  afterEachInOrderCallback(execution, testPlanResult);
6384
6392
  }
6385
6393
  });
6386
-
6394
+ if (execution.params.uses) {
6395
+ for (const tagNoLongerInUse of execution.params.uses) {
6396
+ usedTagSet.delete(tagNoLongerInUse);
6397
+ }
6398
+ }
6387
6399
  if (testPlanResult.failed && failFast && counters.remaining) {
6388
6400
  logger.info(`"failFast" enabled -> cancel remaining executions`);
6389
6401
  failFastAbortController.abort();
@@ -6391,23 +6403,16 @@ To fix this warning:
6391
6403
  }
6392
6404
  };
6393
6405
  const startAsMuchAsPossible = async () => {
6406
+ operation.throwIfAborted();
6394
6407
  const promises = [];
6395
- // eslint-disable-next-line no-constant-condition
6396
- while (true) {
6397
- operation.throwIfAborted();
6398
- if (executionRemainingSet.size === 0) {
6399
- break;
6400
- }
6408
+ for (const executionCandidate of executionRemainingSet) {
6401
6409
  if (executionExecutingSet.size >= parallel.max) {
6402
6410
  break;
6403
6411
  }
6404
-
6405
- if (
6412
+ if (executionExecutingSet.size > 0) {
6406
6413
  // starting execution in parallel is limited by
6407
6414
  // cpu and memory only when trying to parallelize
6408
6415
  // if nothing is executing these limitations don't apply
6409
- executionExecutingSet.size > 0
6410
- ) {
6411
6416
  if (processMemoryUsageMonitoring.measure() > parallel.maxMemory) {
6412
6417
  // retry after Xms in case memory usage decreases
6413
6418
  const promise = (async () => {
@@ -6417,7 +6422,6 @@ To fix this warning:
6417
6422
  promises.push(promise);
6418
6423
  break;
6419
6424
  }
6420
-
6421
6425
  if (processCpuUsageMonitoring.measure() > parallel.maxCpu) {
6422
6426
  // retry after Xms in case cpu usage decreases
6423
6427
  const promise = (async () => {
@@ -6427,27 +6431,29 @@ To fix this warning:
6427
6431
  promises.push(promise);
6428
6432
  break;
6429
6433
  }
6434
+ if (executionCandidate.params.uses) {
6435
+ const nonAvailableTag = executionCandidate.params.uses.find(
6436
+ (tagToUse) => usedTagSet.has(tagToUse),
6437
+ );
6438
+ if (nonAvailableTag) {
6439
+ logger.debug(
6440
+ `"${nonAvailableTag}" is not available, ${executionCandidate.name} will wait until it is released by a previous execution`,
6441
+ );
6442
+ continue;
6443
+ }
6444
+ }
6430
6445
  }
6431
-
6432
- let execution;
6433
- for (const executionCandidate of executionRemainingSet) {
6434
- // TODO: this is where we'll check if it can be executed
6435
- // according to upcoming "using" execution param
6436
- execution = executionCandidate;
6437
- break;
6438
- }
6439
- if (execution) {
6440
- const promise = (async () => {
6441
- await start(execution);
6442
- await startAsMuchAsPossible();
6443
- })();
6444
- promises.push(promise);
6445
- }
6446
+ const promise = (async () => {
6447
+ await start(executionCandidate);
6448
+ await startAsMuchAsPossible();
6449
+ })();
6450
+ promises.push(promise);
6446
6451
  }
6447
- if (promises.length) {
6448
- await Promise.all(promises);
6449
- promises.length = 0;
6452
+ if (promises.length === 0) {
6453
+ return;
6450
6454
  }
6455
+ await Promise.all(promises);
6456
+ promises.length = 0;
6451
6457
  };
6452
6458
 
6453
6459
  reporters = reporters.flat(Infinity);
@@ -9185,4 +9191,75 @@ const execute = async ({
9185
9191
  }
9186
9192
  };
9187
9193
 
9188
- export { chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, nodeChildProcess, nodeWorkerThread, reportAsJunitXml, reportCoverageAsHtml, reportCoverageAsJson, reportCoverageInConsole, reporterList, webkit, webkitIsolatedTab };
9194
+ const inlineRuntime = (fn) => {
9195
+ return {
9196
+ type: "inline",
9197
+ name: "inline",
9198
+ version: "1",
9199
+ run: async ({
9200
+ signal = new AbortController().signal,
9201
+ onRuntimeStarted,
9202
+ onRuntimeStopped,
9203
+ }) => {
9204
+ const actionOperation = Abort.startOperation();
9205
+ actionOperation.addAbortSignal(signal);
9206
+ const result = {
9207
+ status: "executing",
9208
+ errors: [],
9209
+ namespace: null,
9210
+ timings: {},
9211
+ memoryUsage: null,
9212
+ performance: null,
9213
+ };
9214
+ try {
9215
+ let executionInternalErrorCallback;
9216
+ let executionCompletedCallback;
9217
+ const winnerPromise = new Promise((resolve) => {
9218
+ raceCallbacks(
9219
+ {
9220
+ aborted: (cb) => {
9221
+ return actionOperation.addAbortCallback(cb);
9222
+ },
9223
+ execution_internal_error: (cb) => {
9224
+ executionInternalErrorCallback = cb;
9225
+ },
9226
+ execution_completed: (cb) => {
9227
+ executionCompletedCallback = cb;
9228
+ },
9229
+ },
9230
+ resolve,
9231
+ );
9232
+ });
9233
+ try {
9234
+ onRuntimeStarted();
9235
+ const value = await fn();
9236
+ executionCompletedCallback(value);
9237
+ } catch (e) {
9238
+ executionInternalErrorCallback(e);
9239
+ }
9240
+ const raceHandlers = {
9241
+ aborted: () => {
9242
+ result.status = "aborted";
9243
+ },
9244
+ execution_internal_error: (e) => {
9245
+ result.status = "failed";
9246
+ result.errors.push(e);
9247
+ },
9248
+ execution_completed: (value) => {
9249
+ result.status = "completed";
9250
+ result.errors = [];
9251
+ result.namespace = value;
9252
+ },
9253
+ };
9254
+ const winner = await winnerPromise;
9255
+ raceHandlers[winner.name](winner.data);
9256
+ } finally {
9257
+ onRuntimeStopped();
9258
+ await actionOperation.end();
9259
+ return result;
9260
+ }
9261
+ },
9262
+ };
9263
+ };
9264
+
9265
+ export { chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, inlineRuntime, nodeChildProcess, nodeWorkerThread, reportAsJunitXml, reportCoverageAsHtml, reportCoverageAsJson, reportCoverageInConsole, reporterList, webkit, webkitIsolatedTab };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/test",
3
- "version": "3.0.28",
3
+ "version": "3.2.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,11 +38,11 @@
38
38
  "dependencies": {
39
39
  "@c88/v8-coverage": "0.1.1",
40
40
  "@jsenv/abort": "4.3.0",
41
- "@jsenv/ast": "6.0.7",
41
+ "@jsenv/ast": "6.1.0",
42
42
  "@jsenv/filesystem": "4.7.2",
43
43
  "@jsenv/github-check-run": "0.1.16",
44
44
  "@jsenv/humanize": "1.1.3",
45
- "@jsenv/plugin-supervisor": "1.4.11",
45
+ "@jsenv/plugin-supervisor": "1.4.12",
46
46
  "@jsenv/url-meta": "8.4.2",
47
47
  "@jsenv/urls": "2.2.7",
48
48
  "@jsenv/utils": "2.1.1",
@@ -110,6 +110,9 @@ export const createException = (reason, { rootDirectoryUrl } = {}) => {
110
110
 
111
111
  const stackFramesNonNative = [];
112
112
  for (const stackFrame of stackFrames) {
113
+ if (!stackFrame.url) {
114
+ continue;
115
+ }
113
116
  if (stackFrame.url.startsWith("node:")) {
114
117
  stackFrame.native = "node";
115
118
  continue;
@@ -619,6 +619,7 @@ To fix this warning:
619
619
  runtime,
620
620
  runtimeParams,
621
621
  allocatedMs = defaultMsAllocatedPerExecution,
622
+ uses,
622
623
  } = stepConfig;
623
624
  const params = {
624
625
  measureMemoryUsage: true,
@@ -626,6 +627,7 @@ To fix this warning:
626
627
  collectPerformance: false,
627
628
  collectConsole: true,
628
629
  allocatedMs,
630
+ uses,
629
631
  runtime,
630
632
  runtimeParams: {
631
633
  rootDirectoryUrl,
@@ -655,6 +657,7 @@ To fix this warning:
655
657
  }
656
658
 
657
659
  const execution = {
660
+ name: `${relativeUrl}/${groupName}`,
658
661
  counters,
659
662
  countersInOrder,
660
663
  index,
@@ -807,7 +810,13 @@ To fix this warning:
807
810
 
808
811
  const executionRemainingSet = new Set(executionPlanifiedSet);
809
812
  const executionExecutingSet = new Set();
813
+ const usedTagSet = new Set();
810
814
  const start = async (execution) => {
815
+ if (execution.params.uses) {
816
+ for (const tagThatWillBeUsed of execution.params.uses) {
817
+ usedTagSet.add(tagThatWillBeUsed);
818
+ }
819
+ }
811
820
  execution.fileExecutionCount = Object.keys(
812
821
  testPlanResult.results[execution.fileRelativeUrl],
813
822
  ).length;
@@ -827,7 +836,6 @@ To fix this warning:
827
836
  afterEachCallbackSet.add(callback);
828
837
  }
829
838
  }
830
-
831
839
  for (const beforeEachInOrderCallback of beforeEachInOrderCallbackSet) {
832
840
  const returnValue = beforeEachInOrderCallback(
833
841
  execution,
@@ -860,7 +868,6 @@ To fix this warning:
860
868
  process.exitCode = 1;
861
869
  }
862
870
  }
863
-
864
871
  for (const afterEachCallback of afterEachCallbackSet) {
865
872
  afterEachCallback(execution, testPlanResult);
866
873
  }
@@ -870,7 +877,11 @@ To fix this warning:
870
877
  afterEachInOrderCallback(execution, testPlanResult);
871
878
  }
872
879
  });
873
-
880
+ if (execution.params.uses) {
881
+ for (const tagNoLongerInUse of execution.params.uses) {
882
+ usedTagSet.delete(tagNoLongerInUse);
883
+ }
884
+ }
874
885
  if (testPlanResult.failed && failFast && counters.remaining) {
875
886
  logger.info(`"failFast" enabled -> cancel remaining executions`);
876
887
  failFastAbortController.abort();
@@ -878,23 +889,16 @@ To fix this warning:
878
889
  }
879
890
  };
880
891
  const startAsMuchAsPossible = async () => {
892
+ operation.throwIfAborted();
881
893
  const promises = [];
882
- // eslint-disable-next-line no-constant-condition
883
- while (true) {
884
- operation.throwIfAborted();
885
- if (executionRemainingSet.size === 0) {
886
- break;
887
- }
894
+ for (const executionCandidate of executionRemainingSet) {
888
895
  if (executionExecutingSet.size >= parallel.max) {
889
896
  break;
890
897
  }
891
-
892
- if (
898
+ if (executionExecutingSet.size > 0) {
893
899
  // starting execution in parallel is limited by
894
900
  // cpu and memory only when trying to parallelize
895
901
  // if nothing is executing these limitations don't apply
896
- executionExecutingSet.size > 0
897
- ) {
898
902
  if (processMemoryUsageMonitoring.measure() > parallel.maxMemory) {
899
903
  // retry after Xms in case memory usage decreases
900
904
  const promise = (async () => {
@@ -904,7 +908,6 @@ To fix this warning:
904
908
  promises.push(promise);
905
909
  break;
906
910
  }
907
-
908
911
  if (processCpuUsageMonitoring.measure() > parallel.maxCpu) {
909
912
  // retry after Xms in case cpu usage decreases
910
913
  const promise = (async () => {
@@ -914,27 +917,29 @@ To fix this warning:
914
917
  promises.push(promise);
915
918
  break;
916
919
  }
920
+ if (executionCandidate.params.uses) {
921
+ const nonAvailableTag = executionCandidate.params.uses.find(
922
+ (tagToUse) => usedTagSet.has(tagToUse),
923
+ );
924
+ if (nonAvailableTag) {
925
+ logger.debug(
926
+ `"${nonAvailableTag}" is not available, ${executionCandidate.name} will wait until it is released by a previous execution`,
927
+ );
928
+ continue;
929
+ }
930
+ }
917
931
  }
918
-
919
- let execution;
920
- for (const executionCandidate of executionRemainingSet) {
921
- // TODO: this is where we'll check if it can be executed
922
- // according to upcoming "using" execution param
923
- execution = executionCandidate;
924
- break;
925
- }
926
- if (execution) {
927
- const promise = (async () => {
928
- await start(execution);
929
- await startAsMuchAsPossible();
930
- })();
931
- promises.push(promise);
932
- }
932
+ const promise = (async () => {
933
+ await start(executionCandidate);
934
+ await startAsMuchAsPossible();
935
+ })();
936
+ promises.push(promise);
933
937
  }
934
- if (promises.length) {
935
- await Promise.all(promises);
936
- promises.length = 0;
938
+ if (promises.length === 0) {
939
+ return;
937
940
  }
941
+ await Promise.all(promises);
942
+ promises.length = 0;
938
943
  };
939
944
 
940
945
  reporters = reporters.flat(Infinity);
@@ -213,14 +213,16 @@ const renderIntro = (testPlanResult, logOptions) => {
213
213
  ? "/mock/"
214
214
  : urlToFileSystemPath(testPlanResult.rootDirectoryUrl);
215
215
  const numberOfFiles = Object.keys(testPlanResult.results).length;
216
+ const { counters } = testPlanResult;
217
+ const { planified } = counters;
216
218
 
217
219
  let title;
218
- if (numberOfFiles === 0) {
220
+ if (planified === 0) {
219
221
  title = `no file to execute`;
220
- } else if (numberOfFiles === 1) {
221
- title = `1 file to execute`;
222
+ } else if (planified === 1) {
223
+ title = `1 execution planified`;
222
224
  } else {
223
- title = `${numberOfFiles} files to execute`;
225
+ title = `${planified} executions planified`;
224
226
  }
225
227
  const lines = [];
226
228
  lines.push(`directory: ${directory}`);
@@ -602,8 +604,16 @@ const renderOutro = (testPlanResult, logOptions = {}) => {
602
604
  if (planified === 0) {
603
605
  return "";
604
606
  }
607
+ let title;
608
+ if (planified === 0) {
609
+ title = `no execution`;
610
+ } else if (planified === 1) {
611
+ title = `1 execution done`;
612
+ } else {
613
+ title = `${planified} executions done`;
614
+ }
605
615
  return `${renderBigSection({
606
- title: "",
616
+ title,
607
617
  content: renderOutroContent(testPlanResult, logOptions),
608
618
  })}\n`;
609
619
  };
@@ -611,17 +621,8 @@ const renderOutro = (testPlanResult, logOptions = {}) => {
611
621
  export const renderOutroContent = (testPlanResult, logOptions = {}) => {
612
622
  const lines = [];
613
623
  const { counters } = testPlanResult;
614
- const { planified } = counters;
615
624
 
616
- let executionLine = "";
617
- if (planified === 0) {
618
- executionLine += `no execution`;
619
- } else if (planified === 1) {
620
- executionLine += `1 execution: `;
621
- } else {
622
- executionLine += `${planified} executions: `;
623
- }
624
- executionLine += renderStatusRepartition(counters);
625
+ let executionLine = `status: ${renderStatusRepartition(counters)}`;
625
626
  lines.push(executionLine);
626
627
 
627
628
  let durationLine = `duration: `;
package/src/main.js CHANGED
@@ -16,3 +16,7 @@ export { reporterList } from "./execution/reporters/reporter_list.js";
16
16
  export { reportAsJunitXml } from "./execution/junit_xml_file/report_as_junit_xml.js";
17
17
  // advanced
18
18
  export { execute } from "./execution/execute.js";
19
+
20
+ // internals
21
+ // help for internal self unit test
22
+ export { inlineRuntime } from "./runtime_inline/runtime_inline.js";
@@ -0,0 +1,72 @@
1
+ import { Abort, raceCallbacks } from "@jsenv/abort";
2
+
3
+ export const inlineRuntime = (fn) => {
4
+ return {
5
+ type: "inline",
6
+ name: "inline",
7
+ version: "1",
8
+ run: async ({
9
+ signal = new AbortController().signal,
10
+ onRuntimeStarted,
11
+ onRuntimeStopped,
12
+ }) => {
13
+ const actionOperation = Abort.startOperation();
14
+ actionOperation.addAbortSignal(signal);
15
+ const result = {
16
+ status: "executing",
17
+ errors: [],
18
+ namespace: null,
19
+ timings: {},
20
+ memoryUsage: null,
21
+ performance: null,
22
+ };
23
+ try {
24
+ let executionInternalErrorCallback;
25
+ let executionCompletedCallback;
26
+ const winnerPromise = new Promise((resolve) => {
27
+ raceCallbacks(
28
+ {
29
+ aborted: (cb) => {
30
+ return actionOperation.addAbortCallback(cb);
31
+ },
32
+ execution_internal_error: (cb) => {
33
+ executionInternalErrorCallback = cb;
34
+ },
35
+ execution_completed: (cb) => {
36
+ executionCompletedCallback = cb;
37
+ },
38
+ },
39
+ resolve,
40
+ );
41
+ });
42
+ try {
43
+ onRuntimeStarted();
44
+ const value = await fn();
45
+ executionCompletedCallback(value);
46
+ } catch (e) {
47
+ executionInternalErrorCallback(e);
48
+ }
49
+ const raceHandlers = {
50
+ aborted: () => {
51
+ result.status = "aborted";
52
+ },
53
+ execution_internal_error: (e) => {
54
+ result.status = "failed";
55
+ result.errors.push(e);
56
+ },
57
+ execution_completed: (value) => {
58
+ result.status = "completed";
59
+ result.errors = [];
60
+ result.namespace = value;
61
+ },
62
+ };
63
+ const winner = await winnerPromise;
64
+ raceHandlers[winner.name](winner.data);
65
+ } finally {
66
+ onRuntimeStopped();
67
+ await actionOperation.end();
68
+ return result;
69
+ }
70
+ },
71
+ };
72
+ };