@jsenv/test 3.0.10 → 3.0.11

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.
@@ -1,4 +1,4 @@
1
- import os, { cpus, totalmem, availableParallelism } from "node:os";
1
+ import os, { cpus, release, totalmem, availableParallelism, freemem } from "node:os";
2
2
  import process$1, { cpuUsage, memoryUsage } from "node:process";
3
3
  import { readdir, chmod, stat, lstat, promises, readFile as readFile$1, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir, chmodSync, statSync, lstatSync, unlinkSync, readdirSync, rmdirSync, readFileSync, existsSync } from "node:fs";
4
4
  import { takeCoverage } from "node:v8";
@@ -1456,7 +1456,7 @@ const humanizeFileSize = (numberOfBytes, { decimals, short } = {}) => {
1456
1456
  return inspectBytes(numberOfBytes, { decimals, short });
1457
1457
  };
1458
1458
 
1459
- const humanizeMemoryUsage = (metricValue, { decimals, short } = {}) => {
1459
+ const humanizeMemory = (metricValue, { decimals, short } = {}) => {
1460
1460
  return inspectBytes(metricValue, { decimals, fixedDecimals: true, short });
1461
1461
  };
1462
1462
 
@@ -3374,9 +3374,9 @@ const startMeasuringTotalCpuUsage = () => {
3374
3374
  );
3375
3375
  previousCpuUsage = processCpuUsage;
3376
3376
  const thisProcessActiveMs = thisProcessSystemMs + thisProcessUserMs;
3377
- thisProcess.active = thisProcessActiveMs / overallActiveMs;
3378
- thisProcess.system = thisProcessSystemMs / overallSystemMs;
3379
- thisProcess.user = thisProcessUserMs / overallUserMs;
3377
+ thisProcess.active = thisProcessActiveMs / overallMsEllapsed;
3378
+ thisProcess.system = thisProcessSystemMs / overallMsEllapsed;
3379
+ thisProcess.user = thisProcessUserMs / overallMsEllapsed;
3380
3380
 
3381
3381
  if (samples.length === 10) {
3382
3382
  let index = 0;
@@ -4967,7 +4967,9 @@ const replaceUrls = (source, replace) => {
4967
4967
  const reporterList = ({
4968
4968
  animated = true,
4969
4969
  mockFluctuatingValues, // used for snapshot testing logs
4970
- showMemoryUsage = true,
4970
+ platformInfo,
4971
+ memoryUsage: memoryUsage$1,
4972
+ cpuUsage,
4971
4973
  spy = () => {
4972
4974
  return {
4973
4975
  write: (log) => {
@@ -4988,7 +4990,9 @@ const reporterList = ({
4988
4990
  process.exitCode !== 1;
4989
4991
 
4990
4992
  const logOptions = {
4991
- showMemoryUsage,
4993
+ platformInfo,
4994
+ memoryUsage: memoryUsage$1,
4995
+ cpuUsage,
4992
4996
  mockFluctuatingValues,
4993
4997
  group: false,
4994
4998
  intermediateSummary: !animatedLogEnabled,
@@ -5049,7 +5053,7 @@ const reporterList = ({
5049
5053
  });
5050
5054
  infos.push(ANSI.color(duration, ANSI.GREY));
5051
5055
  const memoryHeapUsed = memoryUsage().heapUsed;
5052
- const memoryHeapUsedFormatted = humanizeMemoryUsage(memoryHeapUsed, {
5056
+ const memoryHeapUsedFormatted = humanizeMemory(memoryHeapUsed, {
5053
5057
  short: true,
5054
5058
  decimals: 0,
5055
5059
  });
@@ -5100,8 +5104,10 @@ const reporterList = ({
5100
5104
  reporters.push(
5101
5105
  reporterList({
5102
5106
  animated: false,
5107
+ platformInfo,
5108
+ memoryUsage: memoryUsage$1,
5109
+ cpuUsage,
5103
5110
  mockFluctuatingValues, // used for snapshot testing logs
5104
- showMemoryUsage,
5105
5111
  spy: () => {
5106
5112
  let rawOutput = "";
5107
5113
 
@@ -5121,58 +5127,59 @@ const reporterList = ({
5121
5127
  };
5122
5128
 
5123
5129
  const renderIntro = (testPlanResult, logOptions) => {
5124
- const { counters } = testPlanResult;
5125
- const planified = counters.planified;
5126
- const { groups } = testPlanResult;
5127
- const groupNames = Object.keys(groups);
5128
-
5129
- if (planified === 0) {
5130
- return `${renderBigSection({
5131
- title: "nothing to execute",
5132
- content: "",
5133
- })}\n\n`;
5134
- }
5135
- if (planified === 1) {
5136
- const groupName = groupNames[0];
5137
- const groupInfo = groups[groupName];
5138
- return `${renderBigSection({
5139
- title: "1 execution to run",
5140
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
5141
- })}\n\n`;
5142
- }
5143
- if (groupNames.length === 1) {
5144
- const groupName = groupNames[0];
5145
- const groupInfo = groups[groupName];
5146
- return `${renderBigSection({
5147
- title: `${planified} executions to run`,
5148
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
5149
- })}\n\n`;
5150
- }
5151
-
5152
- let introLines = [];
5153
- for (const groupName of groupNames) {
5154
- const groupInfo = groups[groupName];
5155
- introLines.push(
5156
- `${groupInfo.count} with ${groupName} (${getGroupRenderedName(
5157
- groupInfo,
5158
- logOptions,
5159
- )})`,
5160
- );
5130
+ const lines = [];
5131
+ if (logOptions.platformInfo) {
5132
+ {
5133
+ let osLine = `os: `;
5134
+ if (logOptions.mockFluctuatingValues) {
5135
+ osLine += `os@<mock>`;
5136
+ } else {
5137
+ osLine += `${testPlanResult.os.name}@${testPlanResult.os.version}`;
5138
+ }
5139
+ osLine += renderDetails({
5140
+ cpu: logOptions.mockFluctuatingValues
5141
+ ? "<mock>"
5142
+ : testPlanResult.os.availableCpu,
5143
+ memory: logOptions.mockFluctuatingValues
5144
+ ? "<mock>GB"
5145
+ : humanizeMemory(testPlanResult.os.availableMemory, {
5146
+ short: true,
5147
+ decimals: 0,
5148
+ }),
5149
+ });
5150
+ lines.push(osLine);
5151
+ }
5152
+ {
5153
+ const process = logOptions.mockFluctuatingValues
5154
+ ? `node@mock`
5155
+ : `${testPlanResult.process.name}@${testPlanResult.process.version}`;
5156
+ let processLine = `process: ${process}`;
5157
+ lines.push(processLine);
5158
+ }
5159
+ }
5160
+
5161
+ const directory = logOptions.mockFluctuatingValues
5162
+ ? "/mock/"
5163
+ : urlToFileSystemPath(testPlanResult.rootDirectoryUrl);
5164
+ const numberOfFiles = Object.keys(testPlanResult.results).length;
5165
+ let fileFoundLine = "";
5166
+ if (numberOfFiles === 0) {
5167
+ fileFoundLine += `no file matching "testPlan" in ${directory}:
5168
+ ${testPlanResult.patterns.join("\n")}`;
5169
+ } else if (numberOfFiles === 1) {
5170
+ fileFoundLine += `1 file matching "testPlan" in ${directory}`;
5171
+ } else {
5172
+ fileFoundLine += `${numberOfFiles} files matching "testPlan" in ${directory}`;
5161
5173
  }
5174
+
5175
+ lines.push(fileFoundLine);
5176
+
5162
5177
  return `${renderBigSection({
5163
- title: `${planified} executions to run`,
5164
- content: introLines.join("\n"),
5178
+ title: "execution start",
5179
+ content: lines.join("\n"),
5165
5180
  })}\n\n`;
5166
5181
  };
5167
5182
 
5168
- const getGroupRenderedName = (groupInfo, logOptions) => {
5169
- let { runtimeName, runtimeVersion } = groupInfo;
5170
- if (logOptions.mockFluctuatingValues && groupInfo.runtimeType === "node") {
5171
- runtimeVersion = "<mock>";
5172
- }
5173
- return `${runtimeName}@${runtimeVersion}`;
5174
- };
5175
-
5176
5183
  const renderExecutionLog = (execution, logOptions) => {
5177
5184
  let log = "";
5178
5185
  // label
@@ -5227,10 +5234,10 @@ const renderExecutionLabel = (execution, logOptions) => {
5227
5234
  : humanizeDuration(duration, { short: true });
5228
5235
  infos.push(ANSI.color(durationFormatted, ANSI.GREY));
5229
5236
  }
5230
- if (logOptions.showMemoryUsage && typeof memoryUsage === "number") {
5237
+ if (logOptions.memoryUsage && typeof memoryUsage === "number") {
5231
5238
  const memoryUsageFormatted = logOptions.mockFluctuatingValues
5232
5239
  ? `<mock>MB`
5233
- : humanizeMemoryUsage(memoryUsage, { short: true });
5240
+ : humanizeMemory(memoryUsage, { short: true });
5234
5241
  infos.push(ANSI.color(memoryUsageFormatted, ANSI.GREY));
5235
5242
  }
5236
5243
  if (infos.length) {
@@ -5492,55 +5499,88 @@ const renderErrors = (execution, logOptions) => {
5492
5499
  };
5493
5500
 
5494
5501
  const renderOutro = (testPlanResult, logOptions = {}) => {
5495
- let finalSummary = "";
5502
+ const lines = [];
5496
5503
  const { counters } = testPlanResult;
5497
5504
  const { planified } = counters;
5498
5505
 
5499
- if (planified === 1) {
5500
- finalSummary += `1 execution: `;
5506
+ let executionLine = "";
5507
+ if (planified === 0) {
5508
+ executionLine += `no execution`;
5509
+ } else if (planified === 1) {
5510
+ executionLine += `1 execution: `;
5501
5511
  } else {
5502
- finalSummary += `${planified} executions: `;
5512
+ executionLine += `${planified} executions: `;
5503
5513
  }
5504
- finalSummary += renderStatusRepartition(counters);
5514
+ executionLine += renderStatusRepartition(counters);
5515
+ lines.push(executionLine);
5505
5516
 
5506
- let durationLog = ``;
5517
+ let durationLine = `duration: `;
5507
5518
  const { timings } = testPlanResult;
5508
5519
  if (logOptions.mockFluctuatingValues) {
5509
- durationLog += "<mock>s";
5520
+ durationLine += "<mock>s";
5510
5521
  } else {
5511
- durationLog += humanizeDuration(timings.end, { short: true });
5522
+ durationLine += humanizeDuration(timings.end, { short: true });
5512
5523
  const namedTimings = {
5513
- setup: timings.executionStart,
5514
- execution: timings.executionEnd,
5515
- teardown: timings.teardownEnd - timings.executionEnd,
5524
+ setup: humanizeTiming(timings.executionStart),
5525
+ execution: humanizeTiming(timings.executionEnd),
5526
+ teardown: humanizeTiming(timings.teardownEnd - timings.executionEnd),
5516
5527
  ...(testPlanResult.coverage
5517
- ? { coverage: timings.coverageTeardownEnd - timings.teardownEnd }
5528
+ ? {
5529
+ coverage: humanizeTiming(
5530
+ timings.coverageTeardownEnd - timings.teardownEnd,
5531
+ ),
5532
+ }
5518
5533
  : {}),
5519
5534
  };
5520
- const timingDetails = [];
5521
- for (const key of Object.keys(namedTimings)) {
5522
- const value = namedTimings[key];
5523
- const timingDuration = humanizeDuration(value, { short: true });
5524
- const timingString = `${ANSI.color(`${key}:`, ANSI.GREY)} ${ANSI.color(
5525
- timingDuration,
5526
- ANSI.GREY,
5527
- )}`;
5528
- timingDetails.push(ANSI.color(timingString, ANSI.GREY));
5529
- }
5530
- if (timingDetails.length) {
5531
- durationLog += ` ${ANSI.color("(", ANSI.GREY)}${timingDetails.join(
5532
- ANSI.color(", ", ANSI.GREY),
5533
- )}${ANSI.color(")", ANSI.GREY)}`;
5534
- }
5535
+ durationLine += renderDetails(namedTimings);
5536
+ }
5537
+ lines.push(durationLine);
5538
+
5539
+ if (logOptions.cpuUsage) {
5540
+ const processCpuUsage = testPlanResult.cpuUsage.process;
5541
+ let cpuUsageLine = "cpu: ";
5542
+ cpuUsageLine += `${humanizeProcessCpuUsage(processCpuUsage.end)}`;
5543
+ cpuUsageLine += renderDetails({
5544
+ med: humanizeProcessCpuUsage(processCpuUsage.median),
5545
+ min: humanizeProcessCpuUsage(processCpuUsage.min),
5546
+ max: humanizeProcessCpuUsage(processCpuUsage.max),
5547
+ });
5548
+ lines.push(cpuUsageLine);
5549
+ }
5550
+ if (logOptions.memoryUsage) {
5551
+ const processMemoryUsage = testPlanResult.memoryUsage.process;
5552
+ let memoryUsageLine = "memory: ";
5553
+ memoryUsageLine += `${humanizeProcessMemoryUsage(processMemoryUsage.end)}`;
5554
+ debugger;
5555
+ memoryUsageLine += renderDetails({
5556
+ med: humanizeProcessMemoryUsage(processMemoryUsage.median),
5557
+ min: humanizeProcessMemoryUsage(processMemoryUsage.min),
5558
+ max: humanizeProcessMemoryUsage(processMemoryUsage.max),
5559
+ });
5560
+ lines.push(memoryUsageLine);
5535
5561
  }
5536
- finalSummary += `\nduration: ${durationLog}`;
5537
5562
 
5538
- return `\n${renderBigSection({ title: "summary", content: finalSummary })}\n`;
5563
+ return `\n${renderBigSection({ title: "summary", content: lines.join("\n") })}\n`;
5564
+ };
5565
+
5566
+ const humanizeTiming = (value) => {
5567
+ return humanizeDuration(value, { short: true });
5568
+ };
5569
+
5570
+ const humanizeProcessCpuUsage = (ratio) => {
5571
+ const percentageAsNumber = ratio * 100;
5572
+ const percentageAsNumberRounded = Math.round(percentageAsNumber);
5573
+ const percentage = `${percentageAsNumberRounded}%`;
5574
+ return percentage;
5575
+ };
5576
+
5577
+ const humanizeProcessMemoryUsage = (value) => {
5578
+ return humanizeMemory(value, { short: true, decimals: 0 });
5539
5579
  };
5540
5580
 
5541
5581
  const renderStatusRepartition = (counters, { showProgression } = {}) => {
5542
5582
  if (counters.planified === 0) {
5543
- return `nothing to run`;
5583
+ return ``;
5544
5584
  }
5545
5585
  if (counters.aborted === counters.planified) {
5546
5586
  return `all ${ANSI.color(`aborted`, COLOR_ABORTED)}`;
@@ -5627,6 +5667,29 @@ const renderSection = ({
5627
5667
  return section;
5628
5668
  };
5629
5669
 
5670
+ const renderDetails = (data) => {
5671
+ const details = [];
5672
+ for (const key of Object.keys(data)) {
5673
+ const value = data[key];
5674
+ let valueString = "";
5675
+ valueString += ANSI.color(`${key}:`, ANSI.GREY);
5676
+ const useNonGreyAnsiColor =
5677
+ typeof value === "string" && value.includes("\x1b");
5678
+ valueString += " ";
5679
+ valueString += useNonGreyAnsiColor ? value : ANSI.color(value, ANSI.GREY);
5680
+ details.push(valueString);
5681
+ }
5682
+ if (details.length === 0) {
5683
+ return "";
5684
+ }
5685
+
5686
+ let string = "";
5687
+ string += ` ${ANSI.color("(", ANSI.GREY)}`;
5688
+ string += details.join(ANSI.color(", ", ANSI.GREY));
5689
+ string += ANSI.color(")", ANSI.GREY);
5690
+ return string;
5691
+ };
5692
+
5630
5693
  /*
5631
5694
  *
5632
5695
  */
@@ -5648,6 +5711,9 @@ const logsDefault = {
5648
5711
  level: "info",
5649
5712
  type: "list",
5650
5713
  animated: true,
5714
+ platformInfo: false,
5715
+ memoryUsage: false,
5716
+ cpuUsage: false,
5651
5717
  fileUrl: undefined,
5652
5718
  };
5653
5719
  const githubCheckDefault = {
@@ -5744,12 +5810,63 @@ const executeTestPlan = async ({
5744
5810
  });
5745
5811
  }
5746
5812
 
5747
- const timingOrigin = Date.now();
5813
+ const cpuUsage = startMeasuringTotalCpuUsage();
5814
+ operation.addEndCallback(cpuUsage.stop);
5815
+ const processCpuUsageMonitoring = startMonitoringMetric(() => {
5816
+ return cpuUsage.thisProcess.active;
5817
+ });
5818
+ const osCpuUsageMonitoring = startMonitoringMetric(() => {
5819
+ return cpuUsage.overall.active;
5820
+ });
5821
+ const processMemoryUsageMonitoring = startMonitoringMetric(() => {
5822
+ return memoryUsage().rss;
5823
+ });
5824
+ const osMemoryUsageMonitoring = startMonitoringMetric(() => {
5825
+ const total = totalmem();
5826
+ const free = freemem();
5827
+ return total - free;
5828
+ });
5829
+
5830
+ const timingsOrigin = Date.now();
5748
5831
  const takeTiming = () => {
5749
- return Date.now() - timingOrigin;
5832
+ return Date.now() - timingsOrigin;
5750
5833
  };
5751
5834
  const testPlanResult = {
5835
+ os: {
5836
+ name:
5837
+ process.platform === "darwin"
5838
+ ? "mac"
5839
+ : process.platform === "win32" || process.platform === "win64"
5840
+ ? "windows"
5841
+ : process.platform === "linux"
5842
+ ? "linux"
5843
+ : "other",
5844
+ version: release(),
5845
+ availableCpu: countAvailableCpus(),
5846
+ availableMemory: totalmem(),
5847
+ },
5848
+ process: {
5849
+ name: "node",
5850
+ version: process.version.slice(1),
5851
+ },
5852
+ memoryUsage: {
5853
+ os: osMemoryUsageMonitoring.info,
5854
+ process: processMemoryUsageMonitoring.info,
5855
+ },
5856
+ cpuUsage: {
5857
+ os: osCpuUsageMonitoring.info,
5858
+ process: processCpuUsageMonitoring.info,
5859
+ },
5860
+ timings: {
5861
+ origin: timingsOrigin,
5862
+ executionStart: null,
5863
+ executionEnd: null,
5864
+ teardownEnd: null,
5865
+ coverageTeardownEnd: null,
5866
+ end: null,
5867
+ },
5752
5868
  rootDirectoryUrl: String(rootDirectoryUrl),
5869
+ patterns: Object.keys(testPlan),
5753
5870
  groups: {},
5754
5871
  counters: {
5755
5872
  planified: 0,
@@ -5766,14 +5883,6 @@ const executeTestPlan = async ({
5766
5883
  },
5767
5884
  aborted: false,
5768
5885
  failed: false,
5769
- timings: {
5770
- origin: timingOrigin,
5771
- executionStart: null,
5772
- executionEnd: null,
5773
- teardownEnd: null,
5774
- coverageTeardownEnd: null,
5775
- end: null,
5776
- },
5777
5886
  coverage: null,
5778
5887
  results: {},
5779
5888
  };
@@ -5801,9 +5910,6 @@ const executeTestPlan = async ({
5801
5910
  let finalizeCoverage;
5802
5911
 
5803
5912
  try {
5804
- const cpuUsage = startMeasuringTotalCpuUsage();
5805
- operation.addEndCallback(cpuUsage.stop);
5806
-
5807
5913
  let logger;
5808
5914
  const runtimeInfo = {
5809
5915
  someNeedsServer: false,
@@ -5834,6 +5940,10 @@ const executeTestPlan = async ({
5834
5940
 
5835
5941
  if (logs.type === "list" && logger.levels.info) {
5836
5942
  const listReporterOptions = {
5943
+ mockFluctuatingValues: logs.mockFluctuatingValues,
5944
+ platformInfo: logs.platformInfo,
5945
+ memoryUsage: logs.memoryUsage,
5946
+ cpuUsage: logs.cpuUsage,
5837
5947
  animated: logger.levels.debug ? false : logs.animated,
5838
5948
  fileUrl:
5839
5949
  logs.fileUrl === undefined
@@ -5892,8 +6002,8 @@ const executeTestPlan = async ({
5892
6002
  const max = parallel.max;
5893
6003
  if (typeof max === "string") {
5894
6004
  const maxAsRatio = assertPercentageAndConvertToRatio(max);
5895
- const availableCpus = countAvailableCpus();
5896
- parallel.max = Math.round(maxAsRatio * availableCpus) || 1;
6005
+ parallel.max =
6006
+ Math.round(maxAsRatio * testPlanResult.os.availableCpu) || 1;
5897
6007
  } else if (typeof max === "number") {
5898
6008
  if (max < 1) {
5899
6009
  parallel.max = 1;
@@ -5907,8 +6017,9 @@ const executeTestPlan = async ({
5907
6017
  const maxMemory = parallel.maxMemory;
5908
6018
  if (typeof maxMemory === "string") {
5909
6019
  const maxMemoryAsRatio = assertPercentageAndConvertToRatio(maxMemory);
5910
- const totalMemory = totalmem();
5911
- parallel.maxMemory = Math.round(maxMemoryAsRatio * totalMemory);
6020
+ parallel.maxMemory = Math.round(
6021
+ maxMemoryAsRatio * testPlanResult.os.availableMemory,
6022
+ );
5912
6023
  } else if (typeof maxMemory !== "number") {
5913
6024
  throw new TypeError(
5914
6025
  `parallel.maxMemory must be a number or a percentage, got ${maxMemory}`,
@@ -6446,17 +6557,22 @@ To fix this warning:
6446
6557
  // if nothing is executing these limitations don't apply
6447
6558
  executionExecutingSet.size > 0
6448
6559
  ) {
6449
- const memoryUsedByThisProcess = memoryUsage().rss;
6450
- if (memoryUsedByThisProcess > parallel.maxMemory) {
6560
+ if (processMemoryUsageMonitoring.measure() > parallel.maxMemory) {
6451
6561
  // retry after Xms in case memory usage decreases
6452
- const promise = operation.wait(200);
6562
+ const promise = (async () => {
6563
+ await operation.wait(200);
6564
+ await startAsMuchAsPossible();
6565
+ })();
6453
6566
  promises.push(promise);
6454
6567
  break;
6455
6568
  }
6456
6569
 
6457
- if (cpuUsage.thisProcess.active > parallel.maxCpu) {
6570
+ if (processCpuUsageMonitoring.measure() > parallel.maxCpu) {
6458
6571
  // retry after Xms in case cpu usage decreases
6459
- const promise = operation.wait(200);
6572
+ const promise = (async () => {
6573
+ await operation.wait(200);
6574
+ await startAsMuchAsPossible();
6575
+ })();
6460
6576
  promises.push(promise);
6461
6577
  break;
6462
6578
  }
@@ -6480,7 +6596,6 @@ To fix this warning:
6480
6596
  if (promises.length) {
6481
6597
  await Promise.all(promises);
6482
6598
  promises.length = 0;
6483
- await startAsMuchAsPossible();
6484
6599
  }
6485
6600
  };
6486
6601
 
@@ -6559,6 +6674,11 @@ To fix this warning:
6559
6674
  timings.coverageTeardownEnd = takeTiming();
6560
6675
  timings.end = takeTiming();
6561
6676
 
6677
+ osMemoryUsageMonitoring.end();
6678
+ processMemoryUsageMonitoring.end();
6679
+ osCpuUsageMonitoring.end();
6680
+ processCpuUsageMonitoring.end();
6681
+
6562
6682
  afterEachCallbackSet.clear();
6563
6683
  afterEachInOrderCallbackSet.clear();
6564
6684
  for (const afterAllCallback of afterAllCallbackSet) {
@@ -6571,6 +6691,51 @@ To fix this warning:
6571
6691
  return testPlanResult;
6572
6692
  };
6573
6693
 
6694
+ const startMonitoringMetric = (measure) => {
6695
+ const metrics = [];
6696
+ const takeMeasure = () => {
6697
+ const value = measure();
6698
+ metrics.push(value);
6699
+ return value;
6700
+ };
6701
+
6702
+ const info = {
6703
+ start: takeMeasure(),
6704
+ min: null,
6705
+ max: null,
6706
+ median: null,
6707
+ end: null,
6708
+ };
6709
+ return {
6710
+ info,
6711
+ measure: takeMeasure,
6712
+ end: () => {
6713
+ info.end = takeMeasure();
6714
+ metrics.sort((a, b) => a - b);
6715
+ info.min = metrics[0];
6716
+ info.max = metrics[metrics.length - 1];
6717
+ info.median = medianFromSortedArray(metrics);
6718
+ metrics.length = 0;
6719
+ },
6720
+ };
6721
+ };
6722
+
6723
+ const medianFromSortedArray = (array) => {
6724
+ const length = array.length;
6725
+ const isOdd = length % 2 === 1;
6726
+ if (isOdd) {
6727
+ const medianNumberIndex = (length - 1) / 2;
6728
+ const medianNumber = array[medianNumberIndex];
6729
+ return medianNumber;
6730
+ }
6731
+ const rightMiddleNumberIndex = length / 2;
6732
+ const leftMiddleNumberIndex = rightMiddleNumberIndex - 1;
6733
+ const leftMiddleNumber = array[leftMiddleNumberIndex];
6734
+ const rightMiddleNumber = array[rightMiddleNumberIndex];
6735
+ const medianNumber = (leftMiddleNumber + rightMiddleNumber) / 2;
6736
+ return medianNumber;
6737
+ };
6738
+
6574
6739
  const countAvailableCpus = () => {
6575
6740
  if (typeof availableParallelism === "function") {
6576
6741
  return availableParallelism();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/test",
3
- "version": "3.0.10",
3
+ "version": "3.0.11",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2,7 +2,13 @@
2
2
  *
3
3
  */
4
4
 
5
- import { cpus, availableParallelism, totalmem } from "node:os";
5
+ import {
6
+ release,
7
+ cpus,
8
+ availableParallelism,
9
+ totalmem,
10
+ freemem,
11
+ } from "node:os";
6
12
  import { memoryUsage } from "node:process";
7
13
  import { existsSync } from "node:fs";
8
14
  import { takeCoverage } from "node:v8";
@@ -44,6 +50,9 @@ const logsDefault = {
44
50
  level: "info",
45
51
  type: "list",
46
52
  animated: true,
53
+ platformInfo: false,
54
+ memoryUsage: false,
55
+ cpuUsage: false,
47
56
  fileUrl: undefined,
48
57
  };
49
58
  const githubCheckDefault = {
@@ -140,12 +149,63 @@ export const executeTestPlan = async ({
140
149
  });
141
150
  }
142
151
 
143
- const timingOrigin = Date.now();
152
+ const cpuUsage = startMeasuringTotalCpuUsage();
153
+ operation.addEndCallback(cpuUsage.stop);
154
+ const processCpuUsageMonitoring = startMonitoringMetric(() => {
155
+ return cpuUsage.thisProcess.active;
156
+ });
157
+ const osCpuUsageMonitoring = startMonitoringMetric(() => {
158
+ return cpuUsage.overall.active;
159
+ });
160
+ const processMemoryUsageMonitoring = startMonitoringMetric(() => {
161
+ return memoryUsage().rss;
162
+ });
163
+ const osMemoryUsageMonitoring = startMonitoringMetric(() => {
164
+ const total = totalmem();
165
+ const free = freemem();
166
+ return total - free;
167
+ });
168
+
169
+ const timingsOrigin = Date.now();
144
170
  const takeTiming = () => {
145
- return Date.now() - timingOrigin;
171
+ return Date.now() - timingsOrigin;
146
172
  };
147
173
  const testPlanResult = {
174
+ os: {
175
+ name:
176
+ process.platform === "darwin"
177
+ ? "mac"
178
+ : process.platform === "win32" || process.platform === "win64"
179
+ ? "windows"
180
+ : process.platform === "linux"
181
+ ? "linux"
182
+ : "other",
183
+ version: release(),
184
+ availableCpu: countAvailableCpus(),
185
+ availableMemory: totalmem(),
186
+ },
187
+ process: {
188
+ name: "node",
189
+ version: process.version.slice(1),
190
+ },
191
+ memoryUsage: {
192
+ os: osMemoryUsageMonitoring.info,
193
+ process: processMemoryUsageMonitoring.info,
194
+ },
195
+ cpuUsage: {
196
+ os: osCpuUsageMonitoring.info,
197
+ process: processCpuUsageMonitoring.info,
198
+ },
199
+ timings: {
200
+ origin: timingsOrigin,
201
+ executionStart: null,
202
+ executionEnd: null,
203
+ teardownEnd: null,
204
+ coverageTeardownEnd: null,
205
+ end: null,
206
+ },
148
207
  rootDirectoryUrl: String(rootDirectoryUrl),
208
+ patterns: Object.keys(testPlan),
149
209
  groups: {},
150
210
  counters: {
151
211
  planified: 0,
@@ -162,14 +222,6 @@ export const executeTestPlan = async ({
162
222
  },
163
223
  aborted: false,
164
224
  failed: false,
165
- timings: {
166
- origin: timingOrigin,
167
- executionStart: null,
168
- executionEnd: null,
169
- teardownEnd: null,
170
- coverageTeardownEnd: null,
171
- end: null,
172
- },
173
225
  coverage: null,
174
226
  results: {},
175
227
  };
@@ -197,9 +249,6 @@ export const executeTestPlan = async ({
197
249
  let finalizeCoverage;
198
250
 
199
251
  try {
200
- const cpuUsage = startMeasuringTotalCpuUsage();
201
- operation.addEndCallback(cpuUsage.stop);
202
-
203
252
  let logger;
204
253
  const runtimeInfo = {
205
254
  someNeedsServer: false,
@@ -230,6 +279,10 @@ export const executeTestPlan = async ({
230
279
 
231
280
  if (logs.type === "list" && logger.levels.info) {
232
281
  const listReporterOptions = {
282
+ mockFluctuatingValues: logs.mockFluctuatingValues,
283
+ platformInfo: logs.platformInfo,
284
+ memoryUsage: logs.memoryUsage,
285
+ cpuUsage: logs.cpuUsage,
233
286
  animated: logger.levels.debug ? false : logs.animated,
234
287
  fileUrl:
235
288
  logs.fileUrl === undefined
@@ -288,8 +341,8 @@ export const executeTestPlan = async ({
288
341
  const max = parallel.max;
289
342
  if (typeof max === "string") {
290
343
  const maxAsRatio = assertPercentageAndConvertToRatio(max);
291
- const availableCpus = countAvailableCpus();
292
- parallel.max = Math.round(maxAsRatio * availableCpus) || 1;
344
+ parallel.max =
345
+ Math.round(maxAsRatio * testPlanResult.os.availableCpu) || 1;
293
346
  } else if (typeof max === "number") {
294
347
  if (max < 1) {
295
348
  parallel.max = 1;
@@ -303,8 +356,9 @@ export const executeTestPlan = async ({
303
356
  const maxMemory = parallel.maxMemory;
304
357
  if (typeof maxMemory === "string") {
305
358
  const maxMemoryAsRatio = assertPercentageAndConvertToRatio(maxMemory);
306
- const totalMemory = totalmem();
307
- parallel.maxMemory = Math.round(maxMemoryAsRatio * totalMemory);
359
+ parallel.maxMemory = Math.round(
360
+ maxMemoryAsRatio * testPlanResult.os.availableMemory,
361
+ );
308
362
  } else if (typeof maxMemory !== "number") {
309
363
  throw new TypeError(
310
364
  `parallel.maxMemory must be a number or a percentage, got ${maxMemory}`,
@@ -842,17 +896,22 @@ To fix this warning:
842
896
  // if nothing is executing these limitations don't apply
843
897
  executionExecutingSet.size > 0
844
898
  ) {
845
- const memoryUsedByThisProcess = memoryUsage().rss;
846
- if (memoryUsedByThisProcess > parallel.maxMemory) {
899
+ if (processMemoryUsageMonitoring.measure() > parallel.maxMemory) {
847
900
  // retry after Xms in case memory usage decreases
848
- const promise = operation.wait(200);
901
+ const promise = (async () => {
902
+ await operation.wait(200);
903
+ await startAsMuchAsPossible();
904
+ })();
849
905
  promises.push(promise);
850
906
  break;
851
907
  }
852
908
 
853
- if (cpuUsage.thisProcess.active > parallel.maxCpu) {
909
+ if (processCpuUsageMonitoring.measure() > parallel.maxCpu) {
854
910
  // retry after Xms in case cpu usage decreases
855
- const promise = operation.wait(200);
911
+ const promise = (async () => {
912
+ await operation.wait(200);
913
+ await startAsMuchAsPossible();
914
+ })();
856
915
  promises.push(promise);
857
916
  break;
858
917
  }
@@ -876,7 +935,6 @@ To fix this warning:
876
935
  if (promises.length) {
877
936
  await Promise.all(promises);
878
937
  promises.length = 0;
879
- await startAsMuchAsPossible();
880
938
  }
881
939
  };
882
940
 
@@ -956,6 +1014,11 @@ To fix this warning:
956
1014
  timings.coverageTeardownEnd = takeTiming();
957
1015
  timings.end = takeTiming();
958
1016
 
1017
+ osMemoryUsageMonitoring.end();
1018
+ processMemoryUsageMonitoring.end();
1019
+ osCpuUsageMonitoring.end();
1020
+ processCpuUsageMonitoring.end();
1021
+
959
1022
  afterEachCallbackSet.clear();
960
1023
  afterEachInOrderCallbackSet.clear();
961
1024
  for (const afterAllCallback of afterAllCallbackSet) {
@@ -968,6 +1031,51 @@ To fix this warning:
968
1031
  return testPlanResult;
969
1032
  };
970
1033
 
1034
+ const startMonitoringMetric = (measure) => {
1035
+ const metrics = [];
1036
+ const takeMeasure = () => {
1037
+ const value = measure();
1038
+ metrics.push(value);
1039
+ return value;
1040
+ };
1041
+
1042
+ const info = {
1043
+ start: takeMeasure(),
1044
+ min: null,
1045
+ max: null,
1046
+ median: null,
1047
+ end: null,
1048
+ };
1049
+ return {
1050
+ info,
1051
+ measure: takeMeasure,
1052
+ end: () => {
1053
+ info.end = takeMeasure();
1054
+ metrics.sort((a, b) => a - b);
1055
+ info.min = metrics[0];
1056
+ info.max = metrics[metrics.length - 1];
1057
+ info.median = medianFromSortedArray(metrics);
1058
+ metrics.length = 0;
1059
+ },
1060
+ };
1061
+ };
1062
+
1063
+ const medianFromSortedArray = (array) => {
1064
+ const length = array.length;
1065
+ const isOdd = length % 2 === 1;
1066
+ if (isOdd) {
1067
+ const medianNumberIndex = (length - 1) / 2;
1068
+ const medianNumber = array[medianNumberIndex];
1069
+ return medianNumber;
1070
+ }
1071
+ const rightMiddleNumberIndex = length / 2;
1072
+ const leftMiddleNumberIndex = rightMiddleNumberIndex - 1;
1073
+ const leftMiddleNumber = array[leftMiddleNumberIndex];
1074
+ const rightMiddleNumber = array[rightMiddleNumberIndex];
1075
+ const medianNumber = (leftMiddleNumber + rightMiddleNumber) / 2;
1076
+ return medianNumber;
1077
+ };
1078
+
971
1079
  const countAvailableCpus = () => {
972
1080
  if (typeof availableParallelism === "function") {
973
1081
  return availableParallelism();
@@ -1,13 +1,14 @@
1
- import { memoryUsage } from "node:process";
1
+ import { memoryUsage as processMemoryUsage } from "node:process";
2
2
  import stripAnsi from "strip-ansi";
3
3
  import { writeFileSync } from "@jsenv/filesystem";
4
4
  import {
5
5
  createDynamicLog,
6
6
  humanizeDuration,
7
- humanizeMemoryUsage,
7
+ humanizeMemory,
8
8
  ANSI,
9
9
  UNICODE,
10
10
  } from "@jsenv/humanize";
11
+ import { urlToFileSystemPath } from "@jsenv/urls";
11
12
 
12
13
  import { formatErrorForTerminal } from "../format_error_for_terminal.js";
13
14
 
@@ -36,7 +37,9 @@ import { formatErrorForTerminal } from "../format_error_for_terminal.js";
36
37
  export const reporterList = ({
37
38
  animated = true,
38
39
  mockFluctuatingValues, // used for snapshot testing logs
39
- showMemoryUsage = true,
40
+ platformInfo,
41
+ memoryUsage,
42
+ cpuUsage,
40
43
  spy = () => {
41
44
  return {
42
45
  write: (log) => {
@@ -57,7 +60,9 @@ export const reporterList = ({
57
60
  process.exitCode !== 1;
58
61
 
59
62
  const logOptions = {
60
- showMemoryUsage,
63
+ platformInfo,
64
+ memoryUsage,
65
+ cpuUsage,
61
66
  mockFluctuatingValues,
62
67
  group: false,
63
68
  intermediateSummary: !animatedLogEnabled,
@@ -117,8 +122,8 @@ export const reporterList = ({
117
122
  rounded: false,
118
123
  });
119
124
  infos.push(ANSI.color(duration, ANSI.GREY));
120
- const memoryHeapUsed = memoryUsage().heapUsed;
121
- const memoryHeapUsedFormatted = humanizeMemoryUsage(memoryHeapUsed, {
125
+ const memoryHeapUsed = processMemoryUsage().heapUsed;
126
+ const memoryHeapUsedFormatted = humanizeMemory(memoryHeapUsed, {
122
127
  short: true,
123
128
  decimals: 0,
124
129
  });
@@ -169,8 +174,10 @@ export const reporterList = ({
169
174
  reporters.push(
170
175
  reporterList({
171
176
  animated: false,
177
+ platformInfo,
178
+ memoryUsage,
179
+ cpuUsage,
172
180
  mockFluctuatingValues, // used for snapshot testing logs
173
- showMemoryUsage,
174
181
  spy: () => {
175
182
  let rawOutput = "";
176
183
 
@@ -190,58 +197,59 @@ export const reporterList = ({
190
197
  };
191
198
 
192
199
  const renderIntro = (testPlanResult, logOptions) => {
193
- const { counters } = testPlanResult;
194
- const planified = counters.planified;
195
- const { groups } = testPlanResult;
196
- const groupNames = Object.keys(groups);
200
+ const lines = [];
201
+ if (logOptions.platformInfo) {
202
+ os_line: {
203
+ let osLine = `os: `;
204
+ if (logOptions.mockFluctuatingValues) {
205
+ osLine += `os@<mock>`;
206
+ } else {
207
+ osLine += `${testPlanResult.os.name}@${testPlanResult.os.version}`;
208
+ }
209
+ osLine += renderDetails({
210
+ cpu: logOptions.mockFluctuatingValues
211
+ ? "<mock>"
212
+ : testPlanResult.os.availableCpu,
213
+ memory: logOptions.mockFluctuatingValues
214
+ ? "<mock>GB"
215
+ : humanizeMemory(testPlanResult.os.availableMemory, {
216
+ short: true,
217
+ decimals: 0,
218
+ }),
219
+ });
220
+ lines.push(osLine);
221
+ }
222
+ process_line: {
223
+ const process = logOptions.mockFluctuatingValues
224
+ ? `node@mock`
225
+ : `${testPlanResult.process.name}@${testPlanResult.process.version}`;
226
+ let processLine = `process: ${process}`;
227
+ lines.push(processLine);
228
+ }
229
+ }
197
230
 
198
- if (planified === 0) {
199
- return `${renderBigSection({
200
- title: "nothing to execute",
201
- content: "",
202
- })}\n\n`;
203
- }
204
- if (planified === 1) {
205
- const groupName = groupNames[0];
206
- const groupInfo = groups[groupName];
207
- return `${renderBigSection({
208
- title: "1 execution to run",
209
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
210
- })}\n\n`;
211
- }
212
- if (groupNames.length === 1) {
213
- const groupName = groupNames[0];
214
- const groupInfo = groups[groupName];
215
- return `${renderBigSection({
216
- title: `${planified} executions to run`,
217
- content: `${groupName} (${getGroupRenderedName(groupInfo, logOptions)})`,
218
- })}\n\n`;
219
- }
220
-
221
- let introLines = [];
222
- for (const groupName of groupNames) {
223
- const groupInfo = groups[groupName];
224
- introLines.push(
225
- `${groupInfo.count} with ${groupName} (${getGroupRenderedName(
226
- groupInfo,
227
- logOptions,
228
- )})`,
229
- );
231
+ const directory = logOptions.mockFluctuatingValues
232
+ ? "/mock/"
233
+ : urlToFileSystemPath(testPlanResult.rootDirectoryUrl);
234
+ const numberOfFiles = Object.keys(testPlanResult.results).length;
235
+ let fileFoundLine = "";
236
+ if (numberOfFiles === 0) {
237
+ fileFoundLine += `no file matching "testPlan" in ${directory}:
238
+ ${testPlanResult.patterns.join("\n")}`;
239
+ } else if (numberOfFiles === 1) {
240
+ fileFoundLine += `1 file matching "testPlan" in ${directory}`;
241
+ } else {
242
+ fileFoundLine += `${numberOfFiles} files matching "testPlan" in ${directory}`;
230
243
  }
244
+
245
+ lines.push(fileFoundLine);
246
+
231
247
  return `${renderBigSection({
232
- title: `${planified} executions to run`,
233
- content: introLines.join("\n"),
248
+ title: "execution start",
249
+ content: lines.join("\n"),
234
250
  })}\n\n`;
235
251
  };
236
252
 
237
- const getGroupRenderedName = (groupInfo, logOptions) => {
238
- let { runtimeName, runtimeVersion } = groupInfo;
239
- if (logOptions.mockFluctuatingValues && groupInfo.runtimeType === "node") {
240
- runtimeVersion = "<mock>";
241
- }
242
- return `${runtimeName}@${runtimeVersion}`;
243
- };
244
-
245
253
  const renderExecutionLog = (execution, logOptions) => {
246
254
  let log = "";
247
255
  // label
@@ -296,10 +304,10 @@ const renderExecutionLabel = (execution, logOptions) => {
296
304
  : humanizeDuration(duration, { short: true });
297
305
  infos.push(ANSI.color(durationFormatted, ANSI.GREY));
298
306
  }
299
- if (logOptions.showMemoryUsage && typeof memoryUsage === "number") {
307
+ if (logOptions.memoryUsage && typeof memoryUsage === "number") {
300
308
  const memoryUsageFormatted = logOptions.mockFluctuatingValues
301
309
  ? `<mock>MB`
302
- : humanizeMemoryUsage(memoryUsage, { short: true });
310
+ : humanizeMemory(memoryUsage, { short: true });
303
311
  infos.push(ANSI.color(memoryUsageFormatted, ANSI.GREY));
304
312
  }
305
313
  if (infos.length) {
@@ -561,55 +569,88 @@ const renderErrors = (execution, logOptions) => {
561
569
  };
562
570
 
563
571
  export const renderOutro = (testPlanResult, logOptions = {}) => {
564
- let finalSummary = "";
572
+ const lines = [];
565
573
  const { counters } = testPlanResult;
566
574
  const { planified } = counters;
567
575
 
568
- if (planified === 1) {
569
- finalSummary += `1 execution: `;
576
+ let executionLine = "";
577
+ if (planified === 0) {
578
+ executionLine += `no execution`;
579
+ } else if (planified === 1) {
580
+ executionLine += `1 execution: `;
570
581
  } else {
571
- finalSummary += `${planified} executions: `;
582
+ executionLine += `${planified} executions: `;
572
583
  }
573
- finalSummary += renderStatusRepartition(counters);
584
+ executionLine += renderStatusRepartition(counters);
585
+ lines.push(executionLine);
574
586
 
575
- let durationLog = ``;
587
+ let durationLine = `duration: `;
576
588
  const { timings } = testPlanResult;
577
589
  if (logOptions.mockFluctuatingValues) {
578
- durationLog += "<mock>s";
590
+ durationLine += "<mock>s";
579
591
  } else {
580
- durationLog += humanizeDuration(timings.end, { short: true });
592
+ durationLine += humanizeDuration(timings.end, { short: true });
581
593
  const namedTimings = {
582
- setup: timings.executionStart,
583
- execution: timings.executionEnd,
584
- teardown: timings.teardownEnd - timings.executionEnd,
594
+ setup: humanizeTiming(timings.executionStart),
595
+ execution: humanizeTiming(timings.executionEnd),
596
+ teardown: humanizeTiming(timings.teardownEnd - timings.executionEnd),
585
597
  ...(testPlanResult.coverage
586
- ? { coverage: timings.coverageTeardownEnd - timings.teardownEnd }
598
+ ? {
599
+ coverage: humanizeTiming(
600
+ timings.coverageTeardownEnd - timings.teardownEnd,
601
+ ),
602
+ }
587
603
  : {}),
588
604
  };
589
- const timingDetails = [];
590
- for (const key of Object.keys(namedTimings)) {
591
- const value = namedTimings[key];
592
- const timingDuration = humanizeDuration(value, { short: true });
593
- const timingString = `${ANSI.color(`${key}:`, ANSI.GREY)} ${ANSI.color(
594
- timingDuration,
595
- ANSI.GREY,
596
- )}`;
597
- timingDetails.push(ANSI.color(timingString, ANSI.GREY));
598
- }
599
- if (timingDetails.length) {
600
- durationLog += ` ${ANSI.color("(", ANSI.GREY)}${timingDetails.join(
601
- ANSI.color(", ", ANSI.GREY),
602
- )}${ANSI.color(")", ANSI.GREY)}`;
603
- }
605
+ durationLine += renderDetails(namedTimings);
606
+ }
607
+ lines.push(durationLine);
608
+
609
+ if (logOptions.cpuUsage) {
610
+ const processCpuUsage = testPlanResult.cpuUsage.process;
611
+ let cpuUsageLine = "cpu: ";
612
+ cpuUsageLine += `${humanizeProcessCpuUsage(processCpuUsage.end)}`;
613
+ cpuUsageLine += renderDetails({
614
+ med: humanizeProcessCpuUsage(processCpuUsage.median),
615
+ min: humanizeProcessCpuUsage(processCpuUsage.min),
616
+ max: humanizeProcessCpuUsage(processCpuUsage.max),
617
+ });
618
+ lines.push(cpuUsageLine);
619
+ }
620
+ if (logOptions.memoryUsage) {
621
+ const processMemoryUsage = testPlanResult.memoryUsage.process;
622
+ let memoryUsageLine = "memory: ";
623
+ memoryUsageLine += `${humanizeProcessMemoryUsage(processMemoryUsage.end)}`;
624
+ debugger;
625
+ memoryUsageLine += renderDetails({
626
+ med: humanizeProcessMemoryUsage(processMemoryUsage.median),
627
+ min: humanizeProcessMemoryUsage(processMemoryUsage.min),
628
+ max: humanizeProcessMemoryUsage(processMemoryUsage.max),
629
+ });
630
+ lines.push(memoryUsageLine);
604
631
  }
605
- finalSummary += `\nduration: ${durationLog}`;
606
632
 
607
- return `\n${renderBigSection({ title: "summary", content: finalSummary })}\n`;
633
+ return `\n${renderBigSection({ title: "summary", content: lines.join("\n") })}\n`;
634
+ };
635
+
636
+ const humanizeTiming = (value) => {
637
+ return humanizeDuration(value, { short: true });
638
+ };
639
+
640
+ const humanizeProcessCpuUsage = (ratio) => {
641
+ const percentageAsNumber = ratio * 100;
642
+ const percentageAsNumberRounded = Math.round(percentageAsNumber);
643
+ const percentage = `${percentageAsNumberRounded}%`;
644
+ return percentage;
645
+ };
646
+
647
+ const humanizeProcessMemoryUsage = (value) => {
648
+ return humanizeMemory(value, { short: true, decimals: 0 });
608
649
  };
609
650
 
610
651
  const renderStatusRepartition = (counters, { showProgression } = {}) => {
611
652
  if (counters.planified === 0) {
612
- return `nothing to run`;
653
+ return ``;
613
654
  }
614
655
  if (counters.aborted === counters.planified) {
615
656
  return `all ${ANSI.color(`aborted`, COLOR_ABORTED)}`;
@@ -695,3 +736,26 @@ const renderSection = ({
695
736
  section += bottomDashes;
696
737
  return section;
697
738
  };
739
+
740
+ const renderDetails = (data) => {
741
+ const details = [];
742
+ for (const key of Object.keys(data)) {
743
+ const value = data[key];
744
+ let valueString = "";
745
+ valueString += ANSI.color(`${key}:`, ANSI.GREY);
746
+ const useNonGreyAnsiColor =
747
+ typeof value === "string" && value.includes("\x1b");
748
+ valueString += " ";
749
+ valueString += useNonGreyAnsiColor ? value : ANSI.color(value, ANSI.GREY);
750
+ details.push(valueString);
751
+ }
752
+ if (details.length === 0) {
753
+ return "";
754
+ }
755
+
756
+ let string = "";
757
+ string += ` ${ANSI.color("(", ANSI.GREY)}`;
758
+ string += details.join(ANSI.color(", ", ANSI.GREY));
759
+ string += ANSI.color(")", ANSI.GREY);
760
+ return string;
761
+ };
@@ -85,9 +85,9 @@ export const startMeasuringTotalCpuUsage = () => {
85
85
  );
86
86
  previousCpuUsage = processCpuUsage;
87
87
  const thisProcessActiveMs = thisProcessSystemMs + thisProcessUserMs;
88
- thisProcess.active = thisProcessActiveMs / overallActiveMs;
89
- thisProcess.system = thisProcessSystemMs / overallSystemMs;
90
- thisProcess.user = thisProcessUserMs / overallUserMs;
88
+ thisProcess.active = thisProcessActiveMs / overallMsEllapsed;
89
+ thisProcess.system = thisProcessSystemMs / overallMsEllapsed;
90
+ thisProcess.user = thisProcessUserMs / overallMsEllapsed;
91
91
 
92
92
  if (samples.length === 10) {
93
93
  let index = 0;