@jsenv/test 3.0.1 → 3.0.3

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.
@@ -3180,6 +3180,7 @@ const createDynamicLog = ({
3180
3180
  // The spy is required only if we actually wrote something in the stream
3181
3181
  // something else than this code has written in the stream
3182
3182
  // so we just write without clearing (append instead of replacing)
3183
+ lastOutput = "";
3183
3184
  lastOutputFromOutside = "";
3184
3185
  } else {
3185
3186
  stringToWrite = `${getErasePreviousOutput()}${string}`;
@@ -3455,6 +3456,7 @@ const createCallOrderer = () => {
3455
3456
 
3456
3457
  const readNodeV8CoverageDirectory = async ({
3457
3458
  logger,
3459
+ warn,
3458
3460
  signal,
3459
3461
  onV8Coverage,
3460
3462
  maxMsWaitingForNodeToWriteCoverageFile = 2000,
@@ -3475,7 +3477,10 @@ const readNodeV8CoverageDirectory = async ({
3475
3477
  logger.debug("retry to read coverage directory");
3476
3478
  return tryReadDirectory();
3477
3479
  }
3478
- logger.warn(`v8 coverage directory is empty at ${NODE_V8_COVERAGE}`);
3480
+ warn({
3481
+ code: "V8_COVERAGE_EMPTY",
3482
+ message: `v8 coverage directory is empty at ${NODE_V8_COVERAGE}`,
3483
+ });
3479
3484
  return dirContent;
3480
3485
  };
3481
3486
 
@@ -3683,7 +3688,7 @@ const sourcesFromLineLengths = (lineLengths) => {
3683
3688
  const composeV8AndIstanbul = (
3684
3689
  v8FileByFileCoverage,
3685
3690
  istanbulFileByFileCoverage,
3686
- { v8ConflictWarning },
3691
+ { warn, v8ConflictWarning },
3687
3692
  ) => {
3688
3693
  const fileByFileCoverage = {};
3689
3694
  const v8Files = Object.keys(v8FileByFileCoverage);
@@ -3696,8 +3701,9 @@ const composeV8AndIstanbul = (
3696
3701
  const v8Coverage = v8FileByFileCoverage[key];
3697
3702
  if (v8Coverage) {
3698
3703
  if (v8ConflictWarning) {
3699
- console.warn(
3700
- createDetailedMessage(
3704
+ warn({
3705
+ code: "V8_COVERAGE_CONFLICT",
3706
+ message: createDetailedMessage(
3701
3707
  `Coverage conflict on "${key}", found two coverage that cannot be merged together: v8 and istanbul. The istanbul coverage will be ignored.`,
3702
3708
  {
3703
3709
  "details": `This happens when a file is executed on a runtime using v8 coverage (node or chromium) and on runtime using istanbul coverage (firefox or webkit)`,
@@ -3706,7 +3712,7 @@ const composeV8AndIstanbul = (
3706
3712
  "suggestion 2": `force coverage using istanbul with coverage.methodForBrowsers: "istanbul"`,
3707
3713
  },
3708
3714
  ),
3709
- );
3715
+ });
3710
3716
  }
3711
3717
  fileByFileCoverage[key] = v8Coverage;
3712
3718
  } else {
@@ -3883,7 +3889,7 @@ const getMissingFileByFileCoverage = async ({
3883
3889
 
3884
3890
  const generateCoverage = async (
3885
3891
  testPlanResult,
3886
- { signal, logger, rootDirectoryUrl, coverage },
3892
+ { signal, logger, warn, rootDirectoryUrl, coverage },
3887
3893
  ) => {
3888
3894
  // collect v8 and istanbul coverage from executions
3889
3895
  let { v8Coverage, fileByFileIstanbulCoverage } =
@@ -3912,9 +3918,10 @@ const generateCoverage = async (
3912
3918
  executionResult.type === "node" &&
3913
3919
  coverage.methodForNodeJs !== "NODE_V8_COVERAGE"
3914
3920
  ) {
3915
- logger.warn(
3916
- `"${executionName}" execution of ${file} did not properly write coverage into ${executionResult.coverageFileUrl}`,
3917
- );
3921
+ warn({
3922
+ code: "EXECUTION_COVERAGE_FILE_NOT_FOUND",
3923
+ message: `"${executionName}" execution of ${file} did not properly write coverage into ${executionResult.coverageFileUrl}`,
3924
+ });
3918
3925
  }
3919
3926
  },
3920
3927
  });
@@ -3922,6 +3929,7 @@ const generateCoverage = async (
3922
3929
  if (coverage.methodForNodeJs === "NODE_V8_COVERAGE") {
3923
3930
  await readNodeV8CoverageDirectory({
3924
3931
  logger,
3932
+ warn,
3925
3933
  signal,
3926
3934
  onV8Coverage: async (nodeV8Coverage) => {
3927
3935
  const nodeV8CoverageLight = await filterV8Coverage(nodeV8Coverage, {
@@ -3955,7 +3963,10 @@ const generateCoverage = async (
3955
3963
  fileByFileCoverage = composeV8AndIstanbul(
3956
3964
  v8FileByFileCoverage,
3957
3965
  fileByFileIstanbulCoverage,
3958
- { v8ConflictWarning: coverage.v8ConflictWarning },
3966
+ {
3967
+ warn,
3968
+ v8ConflictWarning: coverage.v8ConflictWarning,
3969
+ },
3959
3970
  );
3960
3971
  } else {
3961
3972
  fileByFileCoverage = v8FileByFileCoverage;
@@ -5035,6 +5046,11 @@ const reporterList = ({
5035
5046
  }, 150);
5036
5047
 
5037
5048
  return {
5049
+ warn: (warning) => {
5050
+ dynamicLog.clearDuringFunctionCall(() => {
5051
+ console.warn(warning.message);
5052
+ });
5053
+ },
5038
5054
  afterEachInOrder: (execution) => {
5039
5055
  dynamicLog.clearDuringFunctionCall(() => {
5040
5056
  const log = renderExecutionLog(execution, logOptions);
@@ -5621,13 +5637,13 @@ const githubCheckDefault = {
5621
5637
  };
5622
5638
  const coverageDefault = {
5623
5639
  include: {
5640
+ "./**/*.js": true,
5641
+ "./**/*.ts": true,
5642
+ "./**/*.jsx": true,
5643
+ "./**/*.tsx": true,
5624
5644
  "file:///**/node_modules/": false,
5625
5645
  "./**/.*": false,
5626
5646
  "./**/.*/": false,
5627
- "./**/src/**/*.js": true,
5628
- "./**/src/**/*.ts": true,
5629
- "./**/src/**/*.jsx": true,
5630
- "./**/src/**/*.tsx": true,
5631
5647
  "./**/tests/": false,
5632
5648
  "./**/*.test.html": false,
5633
5649
  "./**/*.test.html@*.js": false,
@@ -5743,6 +5759,16 @@ const executeTestPlan = async ({
5743
5759
  const countersInOrder = { ...counters };
5744
5760
  const results = testPlanResult.results;
5745
5761
 
5762
+ const warnCallbackSet = new Set();
5763
+ const warn = (warning) => {
5764
+ if (warnCallbackSet.size === 0) {
5765
+ console.warn(warning.message);
5766
+ } else {
5767
+ for (const warnCallback of warnCallbackSet) {
5768
+ warnCallback(warning);
5769
+ }
5770
+ }
5771
+ };
5746
5772
  const beforeEachCallbackSet = new Set();
5747
5773
  const beforeEachInOrderCallbackSet = new Set();
5748
5774
  const afterEachCallbackSet = new Set();
@@ -5863,6 +5889,16 @@ const executeTestPlan = async ({
5863
5889
  `parallel.maxMemory must be a number or a percentage, got ${maxMemory}`,
5864
5890
  );
5865
5891
  }
5892
+
5893
+ const maxCpu = parallel.maxCpu;
5894
+ if (typeof maxCpu === "string") {
5895
+ const maxCpuAsRatio = assertPercentageAndConvertToRatio(maxCpu);
5896
+ parallel.maxCpu = maxCpuAsRatio;
5897
+ } else if (typeof maxCpu !== "number") {
5898
+ throw new TypeError(
5899
+ `parallel.maxCpu must be a number or a percentage, got ${maxCpu}`,
5900
+ );
5901
+ }
5866
5902
  }
5867
5903
  // testPlan
5868
5904
  {
@@ -6281,6 +6317,7 @@ To fix this warning:
6281
6317
  logger,
6282
6318
  rootDirectoryUrl,
6283
6319
  coverage,
6320
+ warn,
6284
6321
  });
6285
6322
  testPlanResult.coverage = testPlanCoverage;
6286
6323
  } catch (e) {
@@ -6397,6 +6434,7 @@ To fix this warning:
6397
6434
  promises.push(promise);
6398
6435
  }
6399
6436
 
6437
+ console.log(cpuUsage.overall.active, parallel.maxCpu);
6400
6438
  if (cpuUsage.overall.active > parallel.maxCpu) {
6401
6439
  // retry after Xms in case cpu usage decreases
6402
6440
  const promise = (async () => {
@@ -6440,12 +6478,16 @@ To fix this warning:
6440
6478
  const returnValue = await beforeAll(testPlanResult);
6441
6479
  if (returnValue) {
6442
6480
  const {
6481
+ warn,
6443
6482
  beforeEach,
6444
6483
  beforeEachInOrder,
6445
6484
  afterEach,
6446
6485
  afterEachInOrder,
6447
6486
  afterAll,
6448
6487
  } = returnValue;
6488
+ if (warn) {
6489
+ warnCallbackSet.add(warn);
6490
+ }
6449
6491
  if (beforeEach) {
6450
6492
  beforeEachCallbackSet.add(beforeEach);
6451
6493
  }
@@ -8661,18 +8703,24 @@ const reportCoverageInConsole = (
8661
8703
  report.execute(context);
8662
8704
  };
8663
8705
 
8664
- const reportCoverageAsJson = (testPlanResult, fileUrl) => {
8706
+ const reportCoverageAsJson = (
8707
+ testPlanResult,
8708
+ fileUrl,
8709
+ { logs } = {},
8710
+ ) => {
8665
8711
  if (testPlanResult.aborted) {
8666
8712
  return;
8667
8713
  }
8668
8714
  const testPlanCoverage = testPlanResult.coverage;
8669
8715
  const coverageAsText = JSON.stringify(testPlanCoverage, null, " ");
8670
8716
  writeFileSync(fileUrl, coverageAsText);
8671
- console.log(
8672
- `-> ${urlToFileSystemPath(fileUrl)} (${inspectFileSize(
8673
- Buffer.byteLength(coverageAsText),
8674
- )})`,
8675
- );
8717
+ if (logs) {
8718
+ console.log(
8719
+ `-> ${urlToFileSystemPath(fileUrl)} (${inspectFileSize(
8720
+ Buffer.byteLength(coverageAsText),
8721
+ )})`,
8722
+ );
8723
+ }
8676
8724
  };
8677
8725
 
8678
8726
  const reportCoverageAsHtml = (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/test",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,7 @@ import { getMissingFileByFileCoverage } from "./missing_coverage.js";
12
12
 
13
13
  export const generateCoverage = async (
14
14
  testPlanResult,
15
- { signal, logger, rootDirectoryUrl, coverage },
15
+ { signal, logger, warn, rootDirectoryUrl, coverage },
16
16
  ) => {
17
17
  // collect v8 and istanbul coverage from executions
18
18
  let { v8Coverage, fileByFileIstanbulCoverage } =
@@ -41,9 +41,10 @@ export const generateCoverage = async (
41
41
  executionResult.type === "node" &&
42
42
  coverage.methodForNodeJs !== "NODE_V8_COVERAGE"
43
43
  ) {
44
- logger.warn(
45
- `"${executionName}" execution of ${file} did not properly write coverage into ${executionResult.coverageFileUrl}`,
46
- );
44
+ warn({
45
+ code: "EXECUTION_COVERAGE_FILE_NOT_FOUND",
46
+ message: `"${executionName}" execution of ${file} did not properly write coverage into ${executionResult.coverageFileUrl}`,
47
+ });
47
48
  }
48
49
  },
49
50
  });
@@ -51,6 +52,7 @@ export const generateCoverage = async (
51
52
  if (coverage.methodForNodeJs === "NODE_V8_COVERAGE") {
52
53
  await readNodeV8CoverageDirectory({
53
54
  logger,
55
+ warn,
54
56
  signal,
55
57
  onV8Coverage: async (nodeV8Coverage) => {
56
58
  const nodeV8CoverageLight = await filterV8Coverage(nodeV8Coverage, {
@@ -84,7 +86,10 @@ export const generateCoverage = async (
84
86
  fileByFileCoverage = composeV8AndIstanbul(
85
87
  v8FileByFileCoverage,
86
88
  fileByFileIstanbulCoverage,
87
- { v8ConflictWarning: coverage.v8ConflictWarning },
89
+ {
90
+ warn,
91
+ v8ConflictWarning: coverage.v8ConflictWarning,
92
+ },
88
93
  );
89
94
  } else {
90
95
  fileByFileCoverage = v8FileByFileCoverage;
@@ -2,19 +2,25 @@ import { urlToFileSystemPath } from "@jsenv/urls";
2
2
  import { writeFileSync } from "@jsenv/filesystem";
3
3
  import { inspectFileSize } from "@jsenv/inspect";
4
4
 
5
- export const reportCoverageAsJson = (testPlanResult, fileUrl) => {
5
+ export const reportCoverageAsJson = (
6
+ testPlanResult,
7
+ fileUrl,
8
+ { logs } = {},
9
+ ) => {
6
10
  if (testPlanResult.aborted) {
7
11
  return;
8
12
  }
9
13
  const testPlanCoverage = testPlanResult.coverage;
10
14
  if (!testPlanCoverage) {
11
- // TODO
15
+ // TODO: throw an error
12
16
  }
13
17
  const coverageAsText = JSON.stringify(testPlanCoverage, null, " ");
14
18
  writeFileSync(fileUrl, coverageAsText);
15
- console.log(
16
- `-> ${urlToFileSystemPath(fileUrl)} (${inspectFileSize(
17
- Buffer.byteLength(coverageAsText),
18
- )})`,
19
- );
19
+ if (logs) {
20
+ console.log(
21
+ `-> ${urlToFileSystemPath(fileUrl)} (${inspectFileSize(
22
+ Buffer.byteLength(coverageAsText),
23
+ )})`,
24
+ );
25
+ }
20
26
  };
@@ -3,7 +3,7 @@ import { createDetailedMessage } from "@jsenv/log";
3
3
  export const composeV8AndIstanbul = (
4
4
  v8FileByFileCoverage,
5
5
  istanbulFileByFileCoverage,
6
- { v8ConflictWarning },
6
+ { warn, v8ConflictWarning },
7
7
  ) => {
8
8
  const fileByFileCoverage = {};
9
9
  const v8Files = Object.keys(v8FileByFileCoverage);
@@ -16,8 +16,9 @@ export const composeV8AndIstanbul = (
16
16
  const v8Coverage = v8FileByFileCoverage[key];
17
17
  if (v8Coverage) {
18
18
  if (v8ConflictWarning) {
19
- console.warn(
20
- createDetailedMessage(
19
+ warn({
20
+ code: "V8_COVERAGE_CONFLICT",
21
+ message: createDetailedMessage(
21
22
  `Coverage conflict on "${key}", found two coverage that cannot be merged together: v8 and istanbul. The istanbul coverage will be ignored.`,
22
23
  {
23
24
  "details": `This happens when a file is executed on a runtime using v8 coverage (node or chromium) and on runtime using istanbul coverage (firefox or webkit)`,
@@ -26,7 +27,7 @@ export const composeV8AndIstanbul = (
26
27
  "suggestion 2": `force coverage using istanbul with coverage.methodForBrowsers: "istanbul"`,
27
28
  },
28
29
  ),
29
- );
30
+ });
30
31
  }
31
32
  fileByFileCoverage[key] = v8Coverage;
32
33
  } else {
@@ -5,6 +5,7 @@ import { Abort } from "@jsenv/abort";
5
5
 
6
6
  export const readNodeV8CoverageDirectory = async ({
7
7
  logger,
8
+ warn,
8
9
  signal,
9
10
  onV8Coverage,
10
11
  maxMsWaitingForNodeToWriteCoverageFile = 2000,
@@ -25,7 +26,10 @@ export const readNodeV8CoverageDirectory = async ({
25
26
  logger.debug("retry to read coverage directory");
26
27
  return tryReadDirectory();
27
28
  }
28
- logger.warn(`v8 coverage directory is empty at ${NODE_V8_COVERAGE}`);
29
+ warn({
30
+ code: "V8_COVERAGE_EMPTY",
31
+ message: `v8 coverage directory is empty at ${NODE_V8_COVERAGE}`,
32
+ });
29
33
  return dirContent;
30
34
  };
31
35
 
@@ -56,13 +56,13 @@ const githubCheckDefault = {
56
56
  };
57
57
  const coverageDefault = {
58
58
  include: {
59
+ "./**/*.js": true,
60
+ "./**/*.ts": true,
61
+ "./**/*.jsx": true,
62
+ "./**/*.tsx": true,
59
63
  "file:///**/node_modules/": false,
60
64
  "./**/.*": false,
61
65
  "./**/.*/": false,
62
- "./**/src/**/*.js": true,
63
- "./**/src/**/*.ts": true,
64
- "./**/src/**/*.jsx": true,
65
- "./**/src/**/*.tsx": true,
66
66
  "./**/tests/": false,
67
67
  "./**/*.test.html": false,
68
68
  "./**/*.test.html@*.js": false,
@@ -178,6 +178,16 @@ export const executeTestPlan = async ({
178
178
  const countersInOrder = { ...counters };
179
179
  const results = testPlanResult.results;
180
180
 
181
+ const warnCallbackSet = new Set();
182
+ const warn = (warning) => {
183
+ if (warnCallbackSet.size === 0) {
184
+ console.warn(warning.message);
185
+ } else {
186
+ for (const warnCallback of warnCallbackSet) {
187
+ warnCallback(warning);
188
+ }
189
+ }
190
+ };
181
191
  const beforeEachCallbackSet = new Set();
182
192
  const beforeEachInOrderCallbackSet = new Set();
183
193
  const afterEachCallbackSet = new Set();
@@ -298,6 +308,16 @@ export const executeTestPlan = async ({
298
308
  `parallel.maxMemory must be a number or a percentage, got ${maxMemory}`,
299
309
  );
300
310
  }
311
+
312
+ const maxCpu = parallel.maxCpu;
313
+ if (typeof maxCpu === "string") {
314
+ const maxCpuAsRatio = assertPercentageAndConvertToRatio(maxCpu);
315
+ parallel.maxCpu = maxCpuAsRatio;
316
+ } else if (typeof maxCpu !== "number") {
317
+ throw new TypeError(
318
+ `parallel.maxCpu must be a number or a percentage, got ${maxCpu}`,
319
+ );
320
+ }
301
321
  }
302
322
  // testPlan
303
323
  {
@@ -716,6 +736,7 @@ To fix this warning:
716
736
  logger,
717
737
  rootDirectoryUrl,
718
738
  coverage,
739
+ warn,
719
740
  });
720
741
  testPlanResult.coverage = testPlanCoverage;
721
742
  } catch (e) {
@@ -832,6 +853,7 @@ To fix this warning:
832
853
  promises.push(promise);
833
854
  }
834
855
 
856
+ console.log(cpuUsage.overall.active, parallel.maxCpu);
835
857
  if (cpuUsage.overall.active > parallel.maxCpu) {
836
858
  // retry after Xms in case cpu usage decreases
837
859
  const promise = (async () => {
@@ -875,12 +897,16 @@ To fix this warning:
875
897
  const returnValue = await beforeAll(testPlanResult);
876
898
  if (returnValue) {
877
899
  const {
900
+ warn,
878
901
  beforeEach,
879
902
  beforeEachInOrder,
880
903
  afterEach,
881
904
  afterEachInOrder,
882
905
  afterAll,
883
906
  } = returnValue;
907
+ if (warn) {
908
+ warnCallbackSet.add(warn);
909
+ }
884
910
  if (beforeEach) {
885
911
  beforeEachCallbackSet.add(beforeEach);
886
912
  }
@@ -134,6 +134,11 @@ export const reporterList = ({
134
134
  }, 150);
135
135
 
136
136
  return {
137
+ warn: (warning) => {
138
+ dynamicLog.clearDuringFunctionCall(() => {
139
+ console.warn(warning.message);
140
+ });
141
+ },
137
142
  afterEachInOrder: (execution) => {
138
143
  dynamicLog.clearDuringFunctionCall(() => {
139
144
  const log = renderExecutionLog(execution, logOptions);