@jsenv/test 1.2.2 → 1.3.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.
@@ -3,13 +3,18 @@ const assertUrlLike = (value, name = "url") => {
3
3
  throw new TypeError(`${name} must be a url string, got ${value}`);
4
4
  }
5
5
  if (isWindowsPathnameSpecifier(value)) {
6
- throw new TypeError(`${name} must be a url but looks like a windows pathname, got ${value}`);
6
+ throw new TypeError(
7
+ `${name} must be a url but looks like a windows pathname, got ${value}`,
8
+ );
7
9
  }
8
10
  if (!hasScheme(value)) {
9
- throw new TypeError(`${name} must be a url and no scheme found, got ${value}`);
11
+ throw new TypeError(
12
+ `${name} must be a url and no scheme found, got ${value}`,
13
+ );
10
14
  }
11
15
  };
12
- const isPlainObject = value => {
16
+
17
+ const isPlainObject = (value) => {
13
18
  if (value === null) {
14
19
  return false;
15
20
  }
@@ -21,7 +26,8 @@ const isPlainObject = value => {
21
26
  }
22
27
  return false;
23
28
  };
24
- const isWindowsPathnameSpecifier = specifier => {
29
+
30
+ const isWindowsPathnameSpecifier = (specifier) => {
25
31
  const firstChar = specifier[0];
26
32
  if (!/[a-zA-Z]/.test(firstChar)) return false;
27
33
  const secondChar = specifier[1];
@@ -29,16 +35,17 @@ const isWindowsPathnameSpecifier = specifier => {
29
35
  const thirdChar = specifier[2];
30
36
  return thirdChar === "/" || thirdChar === "\\";
31
37
  };
32
- const hasScheme = specifier => /^[a-zA-Z]+:/.test(specifier);
38
+
39
+ const hasScheme = (specifier) => /^[a-zA-Z]+:/.test(specifier);
33
40
 
34
41
  const resolveAssociations = (associations, baseUrl) => {
35
42
  assertUrlLike(baseUrl, "baseUrl");
36
43
  const associationsResolved = {};
37
- Object.keys(associations).forEach(key => {
44
+ Object.keys(associations).forEach((key) => {
38
45
  const value = associations[key];
39
46
  if (typeof value === "object" && value !== null) {
40
47
  const valueMapResolved = {};
41
- Object.keys(value).forEach(pattern => {
48
+ Object.keys(value).forEach((pattern) => {
42
49
  const valueAssociated = value[pattern];
43
50
  const patternResolved = normalizeUrlPattern(pattern, baseUrl);
44
51
  valueMapResolved[patternResolved] = valueAssociated;
@@ -50,6 +57,7 @@ const resolveAssociations = (associations, baseUrl) => {
50
57
  });
51
58
  return associationsResolved;
52
59
  };
60
+
53
61
  const normalizeUrlPattern = (urlPattern, baseUrl) => {
54
62
  try {
55
63
  return String(new URL(urlPattern, baseUrl));
@@ -59,25 +67,27 @@ const normalizeUrlPattern = (urlPattern, baseUrl) => {
59
67
  }
60
68
  };
61
69
 
62
- const asFlatAssociations = associations => {
70
+ const asFlatAssociations = (associations) => {
63
71
  if (!isPlainObject(associations)) {
64
- throw new TypeError(`associations must be a plain object, got ${associations}`);
72
+ throw new TypeError(
73
+ `associations must be a plain object, got ${associations}`,
74
+ );
65
75
  }
66
76
  const flatAssociations = {};
67
- Object.keys(associations).forEach(associationName => {
77
+ Object.keys(associations).forEach((associationName) => {
68
78
  const associationValue = associations[associationName];
69
79
  if (isPlainObject(associationValue)) {
70
- Object.keys(associationValue).forEach(pattern => {
80
+ Object.keys(associationValue).forEach((pattern) => {
71
81
  const patternValue = associationValue[pattern];
72
82
  const previousValue = flatAssociations[pattern];
73
83
  if (isPlainObject(previousValue)) {
74
84
  flatAssociations[pattern] = {
75
85
  ...previousValue,
76
- [associationName]: patternValue
86
+ [associationName]: patternValue,
77
87
  };
78
88
  } else {
79
89
  flatAssociations[pattern] = {
80
- [associationName]: patternValue
90
+ [associationName]: patternValue,
81
91
  };
82
92
  }
83
93
  });
@@ -110,21 +120,13 @@ const asFlatAssociations = associations => {
110
120
  * @param {string} applyPatternMatchingParams.url a string representing an url
111
121
  * @return {MatchResult}
112
122
  */
113
- const applyPatternMatching = ({
114
- url,
115
- pattern
116
- }) => {
123
+ const applyPatternMatching = ({ url, pattern }) => {
117
124
  assertUrlLike(pattern, "pattern");
118
125
  assertUrlLike(url, "url");
119
- const {
120
- matched,
121
- patternIndex,
122
- index,
123
- groups
124
- } = applyMatching(pattern, url);
126
+ const { matched, patternIndex, index, groups } = applyMatching(pattern, url);
125
127
  const matchGroups = [];
126
128
  let groupIndex = 0;
127
- groups.forEach(group => {
129
+ groups.forEach((group) => {
128
130
  if (group.name) {
129
131
  matchGroups[group.name] = group.string;
130
132
  } else {
@@ -136,9 +138,10 @@ const applyPatternMatching = ({
136
138
  matched,
137
139
  patternIndex,
138
140
  urlIndex: index,
139
- matchGroups
141
+ matchGroups,
140
142
  };
141
143
  };
144
+
142
145
  const applyMatching = (pattern, string) => {
143
146
  const groups = [];
144
147
  let patternIndex = 0;
@@ -146,13 +149,14 @@ const applyMatching = (pattern, string) => {
146
149
  let remainingPattern = pattern;
147
150
  let remainingString = string;
148
151
  let restoreIndexes = true;
149
- const consumePattern = count => {
152
+
153
+ const consumePattern = (count) => {
150
154
  const subpattern = remainingPattern.slice(0, count);
151
155
  remainingPattern = remainingPattern.slice(count);
152
156
  patternIndex += count;
153
157
  return subpattern;
154
158
  };
155
- const consumeString = count => {
159
+ const consumeString = (count) => {
156
160
  const substring = remainingString.slice(0, count);
157
161
  remainingString = remainingString.slice(count);
158
162
  index += count;
@@ -161,6 +165,7 @@ const applyMatching = (pattern, string) => {
161
165
  const consumeRemainingString = () => {
162
166
  return consumeString(remainingString.length);
163
167
  };
168
+
164
169
  let matched;
165
170
  const iterate = () => {
166
171
  const patternIndexBefore = patternIndex;
@@ -195,9 +200,7 @@ const applyMatching = (pattern, string) => {
195
200
  return true;
196
201
  }
197
202
  if (remainingPattern === "*") {
198
- groups.push({
199
- string: ""
200
- });
203
+ groups.push({ string: "" });
201
204
  }
202
205
  return false; // fail because string shorter than expected
203
206
  }
@@ -207,9 +210,7 @@ const applyMatching = (pattern, string) => {
207
210
  if (remainingString[0] === "/") {
208
211
  // trailing slash match remaining
209
212
  consumePattern(1);
210
- groups.push({
211
- string: consumeRemainingString()
212
- });
213
+ groups.push({ string: consumeRemainingString() });
213
214
  return true;
214
215
  }
215
216
  return false;
@@ -242,7 +243,7 @@ const applyMatching = (pattern, string) => {
242
243
  const skipResult = skipUntilMatch({
243
244
  pattern: remainingPattern,
244
245
  string: remainingString,
245
- canSkipSlash: true
246
+ canSkipSlash: true,
246
247
  });
247
248
  groups.push(...skipResult.groups);
248
249
  consumePattern(skipResult.patternIndex);
@@ -257,29 +258,23 @@ const applyMatching = (pattern, string) => {
257
258
  // matches everything except "/"
258
259
  const slashIndex = remainingString.indexOf("/");
259
260
  if (slashIndex === -1) {
260
- groups.push({
261
- string: consumeRemainingString()
262
- });
261
+ groups.push({ string: consumeRemainingString() });
263
262
  return true;
264
263
  }
265
- groups.push({
266
- string: consumeString(slashIndex)
267
- });
264
+ groups.push({ string: consumeString(slashIndex) });
268
265
  return false;
269
266
  }
270
267
  // the next char must not the one expected by remainingPattern[0]
271
268
  // because * is greedy and expect to skip at least one char
272
269
  if (remainingPattern[0] === remainingString[0]) {
273
- groups.push({
274
- string: ""
275
- });
270
+ groups.push({ string: "" });
276
271
  patternIndex = patternIndex - 1;
277
272
  return false;
278
273
  }
279
274
  const skipResult = skipUntilMatch({
280
275
  pattern: remainingPattern,
281
276
  string: remainingString,
282
- canSkipSlash: false
277
+ canSkipSlash: false,
283
278
  });
284
279
  groups.push(skipResult.group, ...skipResult.groups);
285
280
  consumePattern(skipResult.patternIndex);
@@ -293,22 +288,21 @@ const applyMatching = (pattern, string) => {
293
288
  return undefined;
294
289
  };
295
290
  iterate();
291
+
296
292
  return {
297
293
  matched,
298
294
  patternIndex,
299
295
  index,
300
- groups
296
+ groups,
301
297
  };
302
298
  };
303
- const skipUntilMatch = ({
304
- pattern,
305
- string,
306
- canSkipSlash
307
- }) => {
299
+
300
+ const skipUntilMatch = ({ pattern, string, canSkipSlash }) => {
308
301
  let index = 0;
309
302
  let remainingString = string;
310
303
  let longestAttemptRange = null;
311
304
  let isLastAttempt = false;
305
+
312
306
  const failure = () => {
313
307
  return {
314
308
  matched: false,
@@ -316,10 +310,11 @@ const skipUntilMatch = ({
316
310
  index: longestAttemptRange.index + longestAttemptRange.length,
317
311
  groups: longestAttemptRange.groups,
318
312
  group: {
319
- string: string.slice(0, longestAttemptRange.index)
320
- }
313
+ string: string.slice(0, longestAttemptRange.index),
314
+ },
321
315
  };
322
316
  };
317
+
323
318
  const tryToMatch = () => {
324
319
  const matchAttempt = applyMatching(pattern, remainingString);
325
320
  if (matchAttempt.matched) {
@@ -329,8 +324,11 @@ const skipUntilMatch = ({
329
324
  index: index + matchAttempt.index,
330
325
  groups: matchAttempt.groups,
331
326
  group: {
332
- string: remainingString === "" ? string : string.slice(0, -remainingString.length)
333
- }
327
+ string:
328
+ remainingString === ""
329
+ ? string
330
+ : string.slice(0, -remainingString.length),
331
+ },
334
332
  };
335
333
  }
336
334
  const attemptIndex = matchAttempt.index;
@@ -338,9 +336,12 @@ const skipUntilMatch = ({
338
336
  patternIndex: matchAttempt.patternIndex,
339
337
  index,
340
338
  length: attemptIndex,
341
- groups: matchAttempt.groups
339
+ groups: matchAttempt.groups,
342
340
  };
343
- if (!longestAttemptRange || longestAttemptRange.length < attemptRange.length) {
341
+ if (
342
+ !longestAttemptRange ||
343
+ longestAttemptRange.length < attemptRange.length
344
+ ) {
344
345
  longestAttemptRange = attemptRange;
345
346
  }
346
347
  if (isLastAttempt) {
@@ -367,25 +368,20 @@ const skipUntilMatch = ({
367
368
  return tryToMatch();
368
369
  };
369
370
 
370
- const applyAssociations = ({
371
- url,
372
- associations
373
- }) => {
371
+ const applyAssociations = ({ url, associations }) => {
374
372
  assertUrlLike(url);
375
373
  const flatAssociations = asFlatAssociations(associations);
376
374
  return Object.keys(flatAssociations).reduce((previousValue, pattern) => {
377
- const {
378
- matched
379
- } = applyPatternMatching({
375
+ const { matched } = applyPatternMatching({
380
376
  pattern,
381
- url
377
+ url,
382
378
  });
383
379
  if (matched) {
384
380
  const value = flatAssociations[pattern];
385
381
  if (isPlainObject(previousValue) && isPlainObject(value)) {
386
382
  return {
387
383
  ...previousValue,
388
- ...value
384
+ ...value,
389
385
  };
390
386
  }
391
387
  return value;
@@ -394,15 +390,12 @@ const applyAssociations = ({
394
390
  }, {});
395
391
  };
396
392
 
397
- const applyAliases = ({
398
- url,
399
- aliases
400
- }) => {
393
+ const applyAliases = ({ url, aliases }) => {
401
394
  let aliasFullMatchResult;
402
- const aliasMatchingKey = Object.keys(aliases).find(key => {
395
+ const aliasMatchingKey = Object.keys(aliases).find((key) => {
403
396
  const aliasMatchResult = applyPatternMatching({
404
397
  pattern: key,
405
- url
398
+ url,
406
399
  });
407
400
  if (aliasMatchResult.matched) {
408
401
  aliasFullMatchResult = aliasMatchResult;
@@ -413,22 +406,18 @@ const applyAliases = ({
413
406
  if (!aliasMatchingKey) {
414
407
  return url;
415
408
  }
416
- const {
417
- matchGroups
418
- } = aliasFullMatchResult;
409
+ const { matchGroups } = aliasFullMatchResult;
419
410
  const alias = aliases[aliasMatchingKey];
420
411
  const parts = alias.split("*");
421
412
  const newUrl = parts.reduce((previous, value, index) => {
422
- return `${previous}${value}${index === parts.length - 1 ? "" : matchGroups[index]}`;
413
+ return `${previous}${value}${
414
+ index === parts.length - 1 ? "" : matchGroups[index]
415
+ }`;
423
416
  }, "");
424
417
  return newUrl;
425
418
  };
426
419
 
427
- const urlChildMayMatch = ({
428
- url,
429
- associations,
430
- predicate
431
- }) => {
420
+ const urlChildMayMatch = ({ url, associations, predicate }) => {
432
421
  assertUrlLike(url, "url");
433
422
  // the function was meants to be used on url ending with '/'
434
423
  if (!url.endsWith("/")) {
@@ -444,18 +433,18 @@ const urlChildMayMatch = ({
444
433
  // for partial match, any meta satisfying predicate will be valid because
445
434
  // we don't know for sure if pattern will still match for a file inside pathname
446
435
  const partialMatchMetaArray = [];
447
- Object.keys(flatAssociations).forEach(pattern => {
436
+ Object.keys(flatAssociations).forEach((pattern) => {
448
437
  const value = flatAssociations[pattern];
449
438
  const matchResult = applyPatternMatching({
450
439
  pattern,
451
- url
440
+ url,
452
441
  });
453
442
  if (matchResult.matched) {
454
443
  someFullMatch = true;
455
444
  if (isPlainObject(fullMatchMeta) && isPlainObject(value)) {
456
445
  fullMatchMeta = {
457
446
  ...fullMatchMeta,
458
- ...value
447
+ ...value,
459
448
  };
460
449
  } else {
461
450
  fullMatchMeta = value;
@@ -467,7 +456,9 @@ const urlChildMayMatch = ({
467
456
  if (someFullMatch) {
468
457
  return Boolean(predicate(fullMatchMeta));
469
458
  }
470
- return partialMatchMetaArray.some(partialMatchMeta => predicate(partialMatchMeta));
459
+ return partialMatchMetaArray.some((partialMatchMeta) =>
460
+ predicate(partialMatchMeta),
461
+ );
471
462
  };
472
463
 
473
464
  const URL_META = {
@@ -475,28 +466,30 @@ const URL_META = {
475
466
  applyAssociations,
476
467
  urlChildMayMatch,
477
468
  applyPatternMatching,
478
- applyAliases
469
+ applyAliases,
479
470
  };
480
471
 
481
- const filterV8Coverage = async (v8Coverage, {
482
- rootDirectoryUrl,
483
- coverageConfig
484
- }) => {
485
- const associations = URL_META.resolveAssociations({
486
- cover: coverageConfig
487
- }, rootDirectoryUrl);
488
- const urlShouldBeCovered = url => {
489
- const {
490
- cover
491
- } = URL_META.applyAssociations({
472
+ const filterV8Coverage = async (
473
+ v8Coverage,
474
+ { rootDirectoryUrl, coverageConfig },
475
+ ) => {
476
+ const associations = URL_META.resolveAssociations(
477
+ { cover: coverageConfig },
478
+ rootDirectoryUrl,
479
+ );
480
+ const urlShouldBeCovered = (url) => {
481
+ const { cover } = URL_META.applyAssociations({
492
482
  url: new URL(url, rootDirectoryUrl).href,
493
- associations
483
+ associations,
494
484
  });
495
485
  return cover;
496
486
  };
487
+
497
488
  const v8CoverageFiltered = {
498
489
  ...v8Coverage,
499
- result: v8Coverage.result.filter(fileReport => urlShouldBeCovered(fileReport.url))
490
+ result: v8Coverage.result.filter((fileReport) =>
491
+ urlShouldBeCovered(fileReport.url),
492
+ ),
500
493
  };
501
494
  return v8CoverageFiltered;
502
495
  };