@testream/dotnet-reporter 1.1.0 → 1.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.
- package/README.md +2 -0
- package/dist/index.js +1067 -171
- package/dist/index.js.map +1 -1
- package/dist/source-snippets.d.ts +26 -0
- package/dist/source-snippets.d.ts.map +1 -0
- package/dist/trx-parser.d.ts.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
|
3
3
|
/******/ var __webpack_modules__ = ({
|
|
4
4
|
|
|
5
|
-
/***/
|
|
5
|
+
/***/ 1537:
|
|
6
6
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
7
7
|
|
|
8
8
|
"use strict";
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
const validator = __nccwpck_require__(93);
|
|
12
|
-
const XMLParser = __nccwpck_require__(
|
|
13
|
-
const XMLBuilder = __nccwpck_require__(
|
|
12
|
+
const XMLParser = __nccwpck_require__(2360);
|
|
13
|
+
const XMLBuilder = __nccwpck_require__(2823);
|
|
14
14
|
|
|
15
15
|
module.exports = {
|
|
16
16
|
XMLParser: XMLParser,
|
|
@@ -20,7 +20,7 @@ module.exports = {
|
|
|
20
20
|
|
|
21
21
|
/***/ }),
|
|
22
22
|
|
|
23
|
-
/***/
|
|
23
|
+
/***/ 3064:
|
|
24
24
|
/***/ ((module) => {
|
|
25
25
|
|
|
26
26
|
function getIgnoreAttributesFn(ignoreAttributes) {
|
|
@@ -46,7 +46,7 @@ module.exports = getIgnoreAttributesFn
|
|
|
46
46
|
|
|
47
47
|
/***/ }),
|
|
48
48
|
|
|
49
|
-
/***/
|
|
49
|
+
/***/ 7559:
|
|
50
50
|
/***/ ((__unused_webpack_module, exports) => {
|
|
51
51
|
|
|
52
52
|
"use strict";
|
|
@@ -132,7 +132,7 @@ exports.nameRegexp = nameRegexp;
|
|
|
132
132
|
"use strict";
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
const util = __nccwpck_require__(
|
|
135
|
+
const util = __nccwpck_require__(7559);
|
|
136
136
|
|
|
137
137
|
const defaultOptions = {
|
|
138
138
|
allowBooleanAttributes: false, //A tag can have attributes without any value
|
|
@@ -559,14 +559,14 @@ function getPositionFromMatch(match) {
|
|
|
559
559
|
|
|
560
560
|
/***/ }),
|
|
561
561
|
|
|
562
|
-
/***/
|
|
562
|
+
/***/ 2823:
|
|
563
563
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
564
564
|
|
|
565
565
|
"use strict";
|
|
566
566
|
|
|
567
567
|
//parse Empty Node as self closing node
|
|
568
|
-
const buildFromOrderedJs = __nccwpck_require__(
|
|
569
|
-
const getIgnoreAttributesFn = __nccwpck_require__(
|
|
568
|
+
const buildFromOrderedJs = __nccwpck_require__(1057);
|
|
569
|
+
const getIgnoreAttributesFn = __nccwpck_require__(3064)
|
|
570
570
|
|
|
571
571
|
const defaultOptions = {
|
|
572
572
|
attributeNamePrefix: '@_',
|
|
@@ -853,7 +853,7 @@ module.exports = Builder;
|
|
|
853
853
|
|
|
854
854
|
/***/ }),
|
|
855
855
|
|
|
856
|
-
/***/
|
|
856
|
+
/***/ 1057:
|
|
857
857
|
/***/ ((module) => {
|
|
858
858
|
|
|
859
859
|
const EOL = "\n";
|
|
@@ -995,10 +995,10 @@ module.exports = toXml;
|
|
|
995
995
|
|
|
996
996
|
/***/ }),
|
|
997
997
|
|
|
998
|
-
/***/
|
|
998
|
+
/***/ 2091:
|
|
999
999
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
1000
1000
|
|
|
1001
|
-
const util = __nccwpck_require__(
|
|
1001
|
+
const util = __nccwpck_require__(7559);
|
|
1002
1002
|
|
|
1003
1003
|
//TODO: handle comments
|
|
1004
1004
|
function readDocType(xmlData, i){
|
|
@@ -1209,18 +1209,18 @@ exports.defaultOptions = defaultOptions;
|
|
|
1209
1209
|
|
|
1210
1210
|
/***/ }),
|
|
1211
1211
|
|
|
1212
|
-
/***/
|
|
1212
|
+
/***/ 2629:
|
|
1213
1213
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
1214
1214
|
|
|
1215
1215
|
"use strict";
|
|
1216
1216
|
|
|
1217
1217
|
///@ts-check
|
|
1218
1218
|
|
|
1219
|
-
const util = __nccwpck_require__(
|
|
1220
|
-
const xmlNode = __nccwpck_require__(
|
|
1221
|
-
const readDocType = __nccwpck_require__(
|
|
1222
|
-
const toNumber = __nccwpck_require__(
|
|
1223
|
-
const getIgnoreAttributesFn = __nccwpck_require__(
|
|
1219
|
+
const util = __nccwpck_require__(7559);
|
|
1220
|
+
const xmlNode = __nccwpck_require__(7079);
|
|
1221
|
+
const readDocType = __nccwpck_require__(2091);
|
|
1222
|
+
const toNumber = __nccwpck_require__(6236);
|
|
1223
|
+
const getIgnoreAttributesFn = __nccwpck_require__(3064)
|
|
1224
1224
|
|
|
1225
1225
|
// const regx =
|
|
1226
1226
|
// '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)'
|
|
@@ -1823,12 +1823,12 @@ module.exports = OrderedObjParser;
|
|
|
1823
1823
|
|
|
1824
1824
|
/***/ }),
|
|
1825
1825
|
|
|
1826
|
-
/***/
|
|
1826
|
+
/***/ 2360:
|
|
1827
1827
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
1828
1828
|
|
|
1829
1829
|
const { buildOptions} = __nccwpck_require__(901);
|
|
1830
|
-
const OrderedObjParser = __nccwpck_require__(
|
|
1831
|
-
const { prettify} = __nccwpck_require__(
|
|
1830
|
+
const OrderedObjParser = __nccwpck_require__(2629);
|
|
1831
|
+
const { prettify} = __nccwpck_require__(5318);
|
|
1832
1832
|
const validator = __nccwpck_require__(93);
|
|
1833
1833
|
|
|
1834
1834
|
class XMLParser{
|
|
@@ -1887,7 +1887,7 @@ module.exports = XMLParser;
|
|
|
1887
1887
|
|
|
1888
1888
|
/***/ }),
|
|
1889
1889
|
|
|
1890
|
-
/***/
|
|
1890
|
+
/***/ 5318:
|
|
1891
1891
|
/***/ ((__unused_webpack_module, exports) => {
|
|
1892
1892
|
|
|
1893
1893
|
"use strict";
|
|
@@ -2008,7 +2008,7 @@ exports.prettify = prettify;
|
|
|
2008
2008
|
|
|
2009
2009
|
/***/ }),
|
|
2010
2010
|
|
|
2011
|
-
/***/
|
|
2011
|
+
/***/ 7079:
|
|
2012
2012
|
/***/ ((module) => {
|
|
2013
2013
|
|
|
2014
2014
|
"use strict";
|
|
@@ -2040,7 +2040,7 @@ module.exports = XmlNode;
|
|
|
2040
2040
|
|
|
2041
2041
|
/***/ }),
|
|
2042
2042
|
|
|
2043
|
-
/***/
|
|
2043
|
+
/***/ 6236:
|
|
2044
2044
|
/***/ ((module) => {
|
|
2045
2045
|
|
|
2046
2046
|
const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;
|
|
@@ -2157,7 +2157,7 @@ module.exports = toNumber;
|
|
|
2157
2157
|
|
|
2158
2158
|
/***/ }),
|
|
2159
2159
|
|
|
2160
|
-
/***/
|
|
2160
|
+
/***/ 2406:
|
|
2161
2161
|
/***/ ((__unused_webpack_module, exports) => {
|
|
2162
2162
|
|
|
2163
2163
|
"use strict";
|
|
@@ -2296,7 +2296,7 @@ function detectCIContext() {
|
|
|
2296
2296
|
|
|
2297
2297
|
/***/ }),
|
|
2298
2298
|
|
|
2299
|
-
/***/
|
|
2299
|
+
/***/ 3827:
|
|
2300
2300
|
/***/ ((__unused_webpack_module, exports) => {
|
|
2301
2301
|
|
|
2302
2302
|
"use strict";
|
|
@@ -2307,7 +2307,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
2307
2307
|
|
|
2308
2308
|
/***/ }),
|
|
2309
2309
|
|
|
2310
|
-
/***/
|
|
2310
|
+
/***/ 7322:
|
|
2311
2311
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
2312
2312
|
|
|
2313
2313
|
"use strict";
|
|
@@ -2327,21 +2327,580 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
2327
2327
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
2328
2328
|
};
|
|
2329
2329
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2330
|
-
exports.ensureReportId = exports.mapAttachmentsToTestResults = exports.uploadArtifacts = exports.uploadTestRun = exports.detectCIContext = void 0;
|
|
2330
|
+
exports.createTestLocationCollector = exports.enrichReportWithJsTestNameSourceSnippets = exports.resolveSourceSnippetOptions = exports.enrichReportWithSourceSnippets = exports.ensureReportId = exports.mapAttachmentsToTestResults = exports.uploadArtifacts = exports.uploadTestRun = exports.detectCIContext = void 0;
|
|
2331
2331
|
// CTRF types
|
|
2332
|
-
__exportStar(__nccwpck_require__(
|
|
2333
|
-
var ci_detection_1 = __nccwpck_require__(
|
|
2332
|
+
__exportStar(__nccwpck_require__(3827), exports);
|
|
2333
|
+
var ci_detection_1 = __nccwpck_require__(2406);
|
|
2334
2334
|
Object.defineProperty(exports, "detectCIContext", ({ enumerable: true, get: function () { return ci_detection_1.detectCIContext; } }));
|
|
2335
|
-
var upload_1 = __nccwpck_require__(
|
|
2335
|
+
var upload_1 = __nccwpck_require__(8969);
|
|
2336
2336
|
Object.defineProperty(exports, "uploadTestRun", ({ enumerable: true, get: function () { return upload_1.uploadTestRun; } }));
|
|
2337
2337
|
Object.defineProperty(exports, "uploadArtifacts", ({ enumerable: true, get: function () { return upload_1.uploadArtifacts; } }));
|
|
2338
2338
|
Object.defineProperty(exports, "mapAttachmentsToTestResults", ({ enumerable: true, get: function () { return upload_1.mapAttachmentsToTestResults; } }));
|
|
2339
2339
|
Object.defineProperty(exports, "ensureReportId", ({ enumerable: true, get: function () { return upload_1.ensureReportId; } }));
|
|
2340
|
+
var source_snippets_1 = __nccwpck_require__(9304);
|
|
2341
|
+
Object.defineProperty(exports, "enrichReportWithSourceSnippets", ({ enumerable: true, get: function () { return source_snippets_1.enrichReportWithSourceSnippets; } }));
|
|
2342
|
+
Object.defineProperty(exports, "resolveSourceSnippetOptions", ({ enumerable: true, get: function () { return source_snippets_1.resolveSourceSnippetOptions; } }));
|
|
2343
|
+
var js_test_name_snippets_1 = __nccwpck_require__(6913);
|
|
2344
|
+
Object.defineProperty(exports, "enrichReportWithJsTestNameSourceSnippets", ({ enumerable: true, get: function () { return js_test_name_snippets_1.enrichReportWithJsTestNameSourceSnippets; } }));
|
|
2345
|
+
var test_locations_1 = __nccwpck_require__(2293);
|
|
2346
|
+
Object.defineProperty(exports, "createTestLocationCollector", ({ enumerable: true, get: function () { return test_locations_1.createTestLocationCollector; } }));
|
|
2340
2347
|
//# sourceMappingURL=index.js.map
|
|
2341
2348
|
|
|
2342
2349
|
/***/ }),
|
|
2343
2350
|
|
|
2344
|
-
/***/
|
|
2351
|
+
/***/ 6913:
|
|
2352
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
2353
|
+
|
|
2354
|
+
"use strict";
|
|
2355
|
+
|
|
2356
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
2357
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
2358
|
+
};
|
|
2359
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2360
|
+
exports.enrichReportWithJsTestNameSourceSnippets = enrichReportWithJsTestNameSourceSnippets;
|
|
2361
|
+
const promises_1 = __nccwpck_require__(1455);
|
|
2362
|
+
const node_path_1 = __importDefault(__nccwpck_require__(6760));
|
|
2363
|
+
const source_snippets_1 = __nccwpck_require__(9304);
|
|
2364
|
+
const MAX_CANDIDATES = 3;
|
|
2365
|
+
// Finds the start of common JS/TS test declarations, then the title is parsed
|
|
2366
|
+
// manually so titles can contain non-delimiting quotes like `it("doesn't")`.
|
|
2367
|
+
const JS_TEST_DECLARATION_PATTERN = /\b(describe|it|test)(?:\.(only|skip))?\s*\(\s*(['"`])/g;
|
|
2368
|
+
async function enrichReportWithJsTestNameSourceSnippets(report, options) {
|
|
2369
|
+
const resolved = (0, source_snippets_1.resolveSourceSnippetOptions)(options);
|
|
2370
|
+
const fileCandidateCache = new Map();
|
|
2371
|
+
await Promise.all(report.results.tests.map(async (test) => {
|
|
2372
|
+
if (test.snippet || !test.filePath) {
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
const filePath = node_path_1.default.resolve(resolved.sourceRoot, test.filePath);
|
|
2376
|
+
if (!isInsideSourceRoot(filePath, resolved.sourceRoot)) {
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
const candidates = await getCachedJsTestCandidates(filePath, fileCandidateCache);
|
|
2380
|
+
if (!candidates) {
|
|
2381
|
+
return;
|
|
2382
|
+
}
|
|
2383
|
+
const matches = rankCandidatesForTest(test, candidates).slice(0, MAX_CANDIDATES);
|
|
2384
|
+
if (matches.length === 0) {
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
test.line ?? (test.line = matches[0].line);
|
|
2388
|
+
test.snippet = formatCandidateSnippet(matches, resolved);
|
|
2389
|
+
}));
|
|
2390
|
+
}
|
|
2391
|
+
function getCachedJsTestCandidates(filePath, fileCandidateCache) {
|
|
2392
|
+
let cached = fileCandidateCache.get(filePath);
|
|
2393
|
+
if (!cached) {
|
|
2394
|
+
cached = (0, promises_1.readFile)(filePath, 'utf-8')
|
|
2395
|
+
.then((content) => scanJsTestCandidates(content))
|
|
2396
|
+
.catch(() => undefined);
|
|
2397
|
+
fileCandidateCache.set(filePath, cached);
|
|
2398
|
+
}
|
|
2399
|
+
return cached;
|
|
2400
|
+
}
|
|
2401
|
+
// This scanner intentionally handles the common JS/TS test declaration shapes
|
|
2402
|
+
// without adding parser dependencies to every reporter package. Exact runner
|
|
2403
|
+
// line metadata still wins; this fallback exists to give AI review bounded
|
|
2404
|
+
// source context when the reporter only emitted file path and test name.
|
|
2405
|
+
function scanJsTestCandidates(content) {
|
|
2406
|
+
const lineOffsets = buildLineOffsets(content);
|
|
2407
|
+
const blocks = scanJsTestBlocks(content, lineOffsets);
|
|
2408
|
+
const describeBlocks = blocks.filter((block) => block.kind === 'describe');
|
|
2409
|
+
return blocks
|
|
2410
|
+
.filter((block) => block.kind === 'test')
|
|
2411
|
+
.map((block) => {
|
|
2412
|
+
const describeTitles = describeBlocks
|
|
2413
|
+
.filter((describeBlock) => describeBlock.startIndex < block.startIndex && describeBlock.endIndex >= block.endIndex)
|
|
2414
|
+
.sort((left, right) => left.startIndex - right.startIndex)
|
|
2415
|
+
.map((describeBlock) => describeBlock.title);
|
|
2416
|
+
return {
|
|
2417
|
+
title: block.title,
|
|
2418
|
+
describeTitles,
|
|
2419
|
+
fullName: [...describeTitles, block.title].join(' ').trim(),
|
|
2420
|
+
line: block.startLine,
|
|
2421
|
+
snippet: block.snippet,
|
|
2422
|
+
};
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
function scanJsTestBlocks(content, lineOffsets) {
|
|
2426
|
+
const blocks = [];
|
|
2427
|
+
JS_TEST_DECLARATION_PATTERN.lastIndex = 0;
|
|
2428
|
+
let match;
|
|
2429
|
+
while ((match = JS_TEST_DECLARATION_PATTERN.exec(content)) !== null) {
|
|
2430
|
+
if (isCommentedLine(content, match.index)) {
|
|
2431
|
+
continue;
|
|
2432
|
+
}
|
|
2433
|
+
const title = readQuotedTitle(content, match.index + match[0].length, match[3]);
|
|
2434
|
+
if (!title) {
|
|
2435
|
+
continue;
|
|
2436
|
+
}
|
|
2437
|
+
const commaIndex = skipWhitespaceAndFindComma(content, title.endIndex + 1);
|
|
2438
|
+
if (commaIndex == null) {
|
|
2439
|
+
continue;
|
|
2440
|
+
}
|
|
2441
|
+
const kind = match[1] === 'describe' ? 'describe' : 'test';
|
|
2442
|
+
const startIndex = match.index;
|
|
2443
|
+
const openBraceIndex = findCallbackOpenBrace(content, commaIndex + 1);
|
|
2444
|
+
if (openBraceIndex == null) {
|
|
2445
|
+
continue;
|
|
2446
|
+
}
|
|
2447
|
+
const closeBraceIndex = findMatchingBrace(content, openBraceIndex);
|
|
2448
|
+
if (closeBraceIndex == null) {
|
|
2449
|
+
continue;
|
|
2450
|
+
}
|
|
2451
|
+
const endIndex = findSnippetEndIndex(content, closeBraceIndex);
|
|
2452
|
+
const snippet = content.slice(startIndex, endIndex).trim();
|
|
2453
|
+
if (!snippet) {
|
|
2454
|
+
continue;
|
|
2455
|
+
}
|
|
2456
|
+
blocks.push({
|
|
2457
|
+
kind,
|
|
2458
|
+
title: title.value.trim(),
|
|
2459
|
+
startIndex,
|
|
2460
|
+
endIndex,
|
|
2461
|
+
startLine: getLineNumber(lineOffsets, startIndex),
|
|
2462
|
+
snippet,
|
|
2463
|
+
});
|
|
2464
|
+
}
|
|
2465
|
+
return blocks;
|
|
2466
|
+
}
|
|
2467
|
+
function rankCandidatesForTest(test, candidates) {
|
|
2468
|
+
const normalizedName = normalizeWhitespace(test.name);
|
|
2469
|
+
const suiteChain = normalizeDescribeChain(test.suite);
|
|
2470
|
+
const exactFullNameMatches = candidates.filter((candidate) => normalizeWhitespace(candidate.fullName) === normalizedName);
|
|
2471
|
+
if (exactFullNameMatches.length > 0) {
|
|
2472
|
+
return exactFullNameMatches;
|
|
2473
|
+
}
|
|
2474
|
+
if (suiteChain) {
|
|
2475
|
+
const suiteMatches = candidates.filter((candidate) => normalizeWhitespace(candidate.title) === normalizedName &&
|
|
2476
|
+
normalizeWhitespace(candidate.describeTitles.join(' ')) === suiteChain);
|
|
2477
|
+
if (suiteMatches.length > 0) {
|
|
2478
|
+
return suiteMatches;
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
const leafTitleMatches = candidates.filter((candidate) => normalizeWhitespace(candidate.title) === normalizedName);
|
|
2482
|
+
if (leafTitleMatches.length > 0) {
|
|
2483
|
+
return leafTitleMatches;
|
|
2484
|
+
}
|
|
2485
|
+
return candidates.filter((candidate) => {
|
|
2486
|
+
const normalizedTitle = normalizeWhitespace(candidate.title);
|
|
2487
|
+
if (!normalizedName.endsWith(normalizedTitle)) {
|
|
2488
|
+
return false;
|
|
2489
|
+
}
|
|
2490
|
+
const prefix = normalizedName
|
|
2491
|
+
.slice(0, normalizedName.length - normalizedTitle.length)
|
|
2492
|
+
.trim();
|
|
2493
|
+
return prefix.length > 0 && normalizeWhitespace(candidate.describeTitles.join(' ')) === prefix;
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
function formatCandidateSnippet(candidates, options) {
|
|
2497
|
+
const combined = candidates.length === 1
|
|
2498
|
+
? candidates[0].snippet
|
|
2499
|
+
: candidates
|
|
2500
|
+
.map((candidate, index) => `Candidate ${index + 1} (line ${candidate.line})\n${candidate.snippet}`)
|
|
2501
|
+
.join('\n\n');
|
|
2502
|
+
const boundedLines = combined.split(/\r?\n/).slice(0, options.maxLines).join('\n').trim();
|
|
2503
|
+
if (boundedLines.length <= options.maxChars) {
|
|
2504
|
+
return boundedLines;
|
|
2505
|
+
}
|
|
2506
|
+
return boundedLines.slice(0, options.maxChars);
|
|
2507
|
+
}
|
|
2508
|
+
function findCallbackOpenBrace(content, fromIndex) {
|
|
2509
|
+
for (let index = fromIndex; index < content.length; index++) {
|
|
2510
|
+
const char = content[index];
|
|
2511
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
2512
|
+
index = skipQuotedString(content, index);
|
|
2513
|
+
continue;
|
|
2514
|
+
}
|
|
2515
|
+
if (char === '/' && content[index + 1] === '/') {
|
|
2516
|
+
index = skipLineComment(content, index + 2);
|
|
2517
|
+
continue;
|
|
2518
|
+
}
|
|
2519
|
+
if (char === '/' && content[index + 1] === '*') {
|
|
2520
|
+
index = skipBlockComment(content, index + 2);
|
|
2521
|
+
continue;
|
|
2522
|
+
}
|
|
2523
|
+
if (content.startsWith('=>', index)) {
|
|
2524
|
+
return findNextBlockBrace(content, index + 2);
|
|
2525
|
+
}
|
|
2526
|
+
if (startsWithWord(content, index, 'function')) {
|
|
2527
|
+
return findNextBlockBrace(content, index + 'function'.length);
|
|
2528
|
+
}
|
|
2529
|
+
if (char === ';') {
|
|
2530
|
+
return undefined;
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
return undefined;
|
|
2534
|
+
}
|
|
2535
|
+
function findNextBlockBrace(content, fromIndex) {
|
|
2536
|
+
for (let index = fromIndex; index < content.length; index++) {
|
|
2537
|
+
const char = content[index];
|
|
2538
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
2539
|
+
index = skipQuotedString(content, index);
|
|
2540
|
+
continue;
|
|
2541
|
+
}
|
|
2542
|
+
if (char === '{') {
|
|
2543
|
+
return index;
|
|
2544
|
+
}
|
|
2545
|
+
if (char === '\n' && looksLikeLineTerminator(content, index + 1)) {
|
|
2546
|
+
return undefined;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
return undefined;
|
|
2550
|
+
}
|
|
2551
|
+
function findMatchingBrace(content, openBraceIndex) {
|
|
2552
|
+
let depth = 0;
|
|
2553
|
+
for (let index = openBraceIndex; index < content.length; index++) {
|
|
2554
|
+
const char = content[index];
|
|
2555
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
2556
|
+
index = skipQuotedString(content, index);
|
|
2557
|
+
continue;
|
|
2558
|
+
}
|
|
2559
|
+
if (char === '/' && content[index + 1] === '/') {
|
|
2560
|
+
index = skipLineComment(content, index + 2);
|
|
2561
|
+
continue;
|
|
2562
|
+
}
|
|
2563
|
+
if (char === '/' && content[index + 1] === '*') {
|
|
2564
|
+
index = skipBlockComment(content, index + 2);
|
|
2565
|
+
continue;
|
|
2566
|
+
}
|
|
2567
|
+
if (char === '{') {
|
|
2568
|
+
depth++;
|
|
2569
|
+
continue;
|
|
2570
|
+
}
|
|
2571
|
+
if (char === '}') {
|
|
2572
|
+
depth--;
|
|
2573
|
+
if (depth === 0) {
|
|
2574
|
+
return index;
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
return undefined;
|
|
2579
|
+
}
|
|
2580
|
+
function readQuotedTitle(content, startIndex, quote) {
|
|
2581
|
+
let value = '';
|
|
2582
|
+
for (let index = startIndex; index < content.length; index++) {
|
|
2583
|
+
const char = content[index];
|
|
2584
|
+
if (char === '\\') {
|
|
2585
|
+
value += char;
|
|
2586
|
+
if (index + 1 < content.length) {
|
|
2587
|
+
index++;
|
|
2588
|
+
value += content[index];
|
|
2589
|
+
}
|
|
2590
|
+
continue;
|
|
2591
|
+
}
|
|
2592
|
+
if (char === quote) {
|
|
2593
|
+
return { value, endIndex: index };
|
|
2594
|
+
}
|
|
2595
|
+
if (char === '\n' && quote !== '`') {
|
|
2596
|
+
return undefined;
|
|
2597
|
+
}
|
|
2598
|
+
value += char;
|
|
2599
|
+
}
|
|
2600
|
+
return undefined;
|
|
2601
|
+
}
|
|
2602
|
+
function skipWhitespaceAndFindComma(content, fromIndex) {
|
|
2603
|
+
for (let index = fromIndex; index < content.length; index++) {
|
|
2604
|
+
const char = content[index];
|
|
2605
|
+
if (/\s/.test(char)) {
|
|
2606
|
+
continue;
|
|
2607
|
+
}
|
|
2608
|
+
return char === ',' ? index : undefined;
|
|
2609
|
+
}
|
|
2610
|
+
return undefined;
|
|
2611
|
+
}
|
|
2612
|
+
function findSnippetEndIndex(content, closeBraceIndex) {
|
|
2613
|
+
let index = closeBraceIndex + 1;
|
|
2614
|
+
while (index < content.length) {
|
|
2615
|
+
const char = content[index];
|
|
2616
|
+
if (char === '\r' || char === '\n') {
|
|
2617
|
+
return index;
|
|
2618
|
+
}
|
|
2619
|
+
index++;
|
|
2620
|
+
}
|
|
2621
|
+
return content.length;
|
|
2622
|
+
}
|
|
2623
|
+
function skipQuotedString(content, startIndex) {
|
|
2624
|
+
const quote = content[startIndex];
|
|
2625
|
+
for (let index = startIndex + 1; index < content.length; index++) {
|
|
2626
|
+
const char = content[index];
|
|
2627
|
+
if (char === '\\') {
|
|
2628
|
+
index++;
|
|
2629
|
+
continue;
|
|
2630
|
+
}
|
|
2631
|
+
if (char === quote) {
|
|
2632
|
+
return index;
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
return content.length - 1;
|
|
2636
|
+
}
|
|
2637
|
+
function skipLineComment(content, startIndex) {
|
|
2638
|
+
for (let index = startIndex; index < content.length; index++) {
|
|
2639
|
+
if (content[index] === '\n') {
|
|
2640
|
+
return index;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
return content.length - 1;
|
|
2644
|
+
}
|
|
2645
|
+
function skipBlockComment(content, startIndex) {
|
|
2646
|
+
for (let index = startIndex; index < content.length - 1; index++) {
|
|
2647
|
+
if (content[index] === '*' && content[index + 1] === '/') {
|
|
2648
|
+
return index + 1;
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
return content.length - 1;
|
|
2652
|
+
}
|
|
2653
|
+
function looksLikeLineTerminator(content, index) {
|
|
2654
|
+
for (let cursor = index; cursor < content.length; cursor++) {
|
|
2655
|
+
const char = content[cursor];
|
|
2656
|
+
if (!/\s/.test(char)) {
|
|
2657
|
+
return char !== '.' && char !== '(';
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
return false;
|
|
2661
|
+
}
|
|
2662
|
+
function buildLineOffsets(content) {
|
|
2663
|
+
const offsets = [0];
|
|
2664
|
+
for (let index = 0; index < content.length; index++) {
|
|
2665
|
+
if (content[index] === '\n') {
|
|
2666
|
+
offsets.push(index + 1);
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
return offsets;
|
|
2670
|
+
}
|
|
2671
|
+
function getLineNumber(lineOffsets, index) {
|
|
2672
|
+
let line = 0;
|
|
2673
|
+
for (let i = 0; i < lineOffsets.length; i++) {
|
|
2674
|
+
if (lineOffsets[i] > index) {
|
|
2675
|
+
break;
|
|
2676
|
+
}
|
|
2677
|
+
line = i;
|
|
2678
|
+
}
|
|
2679
|
+
return line + 1;
|
|
2680
|
+
}
|
|
2681
|
+
function isCommentedLine(content, index) {
|
|
2682
|
+
const lineStart = content.lastIndexOf('\n', index - 1) + 1;
|
|
2683
|
+
const prefix = content.slice(lineStart, index).trimStart();
|
|
2684
|
+
return prefix.startsWith('//') || prefix.startsWith('*');
|
|
2685
|
+
}
|
|
2686
|
+
function startsWithWord(content, index, word) {
|
|
2687
|
+
if (!content.startsWith(word, index)) {
|
|
2688
|
+
return false;
|
|
2689
|
+
}
|
|
2690
|
+
const before = index === 0 ? '' : content[index - 1];
|
|
2691
|
+
const after = content[index + word.length] ?? '';
|
|
2692
|
+
return !isIdentifierChar(before) && !isIdentifierChar(after);
|
|
2693
|
+
}
|
|
2694
|
+
function isIdentifierChar(char) {
|
|
2695
|
+
return /[A-Za-z0-9_$]/.test(char);
|
|
2696
|
+
}
|
|
2697
|
+
function normalizeWhitespace(value) {
|
|
2698
|
+
return (value ?? '').trim().replace(/\s+/g, ' ');
|
|
2699
|
+
}
|
|
2700
|
+
function normalizeDescribeChain(suite) {
|
|
2701
|
+
if (!suite) {
|
|
2702
|
+
return '';
|
|
2703
|
+
}
|
|
2704
|
+
const segments = suite
|
|
2705
|
+
.split('>')
|
|
2706
|
+
.map((segment) => segment.trim())
|
|
2707
|
+
.filter(Boolean);
|
|
2708
|
+
if (segments.length === 0) {
|
|
2709
|
+
return '';
|
|
2710
|
+
}
|
|
2711
|
+
const firstSegmentLooksLikeFile = segments[0].includes('.');
|
|
2712
|
+
const describeSegments = firstSegmentLooksLikeFile ? segments.slice(1) : segments;
|
|
2713
|
+
return normalizeWhitespace(describeSegments.join(' '));
|
|
2714
|
+
}
|
|
2715
|
+
function isInsideSourceRoot(filePath, sourceRoot) {
|
|
2716
|
+
const relative = node_path_1.default.relative(sourceRoot, filePath);
|
|
2717
|
+
return relative.length > 0 && !relative.startsWith('..') && !node_path_1.default.isAbsolute(relative);
|
|
2718
|
+
}
|
|
2719
|
+
//# sourceMappingURL=js-test-name-snippets.js.map
|
|
2720
|
+
|
|
2721
|
+
/***/ }),
|
|
2722
|
+
|
|
2723
|
+
/***/ 9304:
|
|
2724
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
2725
|
+
|
|
2726
|
+
"use strict";
|
|
2727
|
+
|
|
2728
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
2729
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
2730
|
+
};
|
|
2731
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2732
|
+
exports.resolveSourceSnippetOptions = resolveSourceSnippetOptions;
|
|
2733
|
+
exports.enrichReportWithSourceSnippets = enrichReportWithSourceSnippets;
|
|
2734
|
+
const promises_1 = __nccwpck_require__(1455);
|
|
2735
|
+
const node_path_1 = __importDefault(__nccwpck_require__(6760));
|
|
2736
|
+
const DEFAULT_MAX_CHARS = 2000;
|
|
2737
|
+
const DEFAULT_MAX_LINES = 40;
|
|
2738
|
+
function resolveSourceSnippetOptions(options) {
|
|
2739
|
+
return {
|
|
2740
|
+
sourceRoot: node_path_1.default.resolve(options?.sourceRoot ?? process.cwd()),
|
|
2741
|
+
maxChars: normalizePositiveInt(options?.maxChars, DEFAULT_MAX_CHARS),
|
|
2742
|
+
maxLines: normalizePositiveInt(options?.maxLines, DEFAULT_MAX_LINES),
|
|
2743
|
+
};
|
|
2744
|
+
}
|
|
2745
|
+
// This implementation only extracts JS/TS-style test()/it() blocks.
|
|
2746
|
+
// Other languages need reporter-specific snippet logic after that reporter
|
|
2747
|
+
// has supplied file/line metadata for the test.
|
|
2748
|
+
async function enrichReportWithSourceSnippets(report, options) {
|
|
2749
|
+
const resolved = resolveSourceSnippetOptions(options);
|
|
2750
|
+
const fileContentCache = new Map();
|
|
2751
|
+
await Promise.all(report.results.tests.map(async (test) => {
|
|
2752
|
+
if (test.snippet || !test.filePath || !test.line) {
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2755
|
+
const snippet = await tryExtractSnippet(test, resolved, fileContentCache);
|
|
2756
|
+
if (snippet) {
|
|
2757
|
+
test.snippet = snippet;
|
|
2758
|
+
}
|
|
2759
|
+
}));
|
|
2760
|
+
}
|
|
2761
|
+
async function tryExtractSnippet(test, options, fileContentCache) {
|
|
2762
|
+
const filePath = node_path_1.default.resolve(options.sourceRoot, test.filePath);
|
|
2763
|
+
if (!isInsideSourceRoot(filePath, options.sourceRoot)) {
|
|
2764
|
+
return undefined;
|
|
2765
|
+
}
|
|
2766
|
+
const content = await getCachedFileContent(filePath, fileContentCache);
|
|
2767
|
+
if (!content) {
|
|
2768
|
+
return undefined;
|
|
2769
|
+
}
|
|
2770
|
+
return extractEnclosingTestBlock(content, test.line, options);
|
|
2771
|
+
}
|
|
2772
|
+
function getCachedFileContent(filePath, fileContentCache) {
|
|
2773
|
+
let cached = fileContentCache.get(filePath);
|
|
2774
|
+
if (!cached) {
|
|
2775
|
+
cached = (0, promises_1.readFile)(filePath, 'utf-8').catch(() => undefined);
|
|
2776
|
+
fileContentCache.set(filePath, cached);
|
|
2777
|
+
}
|
|
2778
|
+
return cached;
|
|
2779
|
+
}
|
|
2780
|
+
function extractEnclosingTestBlock(content, lineNumber, options) {
|
|
2781
|
+
const lines = content.split(/\r?\n/);
|
|
2782
|
+
const index = Math.max(0, Math.min(lines.length - 1, lineNumber - 1));
|
|
2783
|
+
const start = findTestStart(lines, index);
|
|
2784
|
+
if (start == null) {
|
|
2785
|
+
return undefined;
|
|
2786
|
+
}
|
|
2787
|
+
const selected = [];
|
|
2788
|
+
let braceBalance = 0;
|
|
2789
|
+
let sawOpeningBrace = false;
|
|
2790
|
+
for (let i = start; i < lines.length && selected.length < options.maxLines; i++) {
|
|
2791
|
+
const line = lines[i];
|
|
2792
|
+
selected.push(line);
|
|
2793
|
+
for (const char of line) {
|
|
2794
|
+
if (char === '{') {
|
|
2795
|
+
braceBalance++;
|
|
2796
|
+
sawOpeningBrace = true;
|
|
2797
|
+
}
|
|
2798
|
+
else if (char === '}') {
|
|
2799
|
+
braceBalance--;
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
if (sawOpeningBrace && braceBalance <= 0 && isJsTestBlockTerminator(line)) {
|
|
2803
|
+
break;
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
const snippet = selected.join('\n').trim();
|
|
2807
|
+
if (!snippet) {
|
|
2808
|
+
return undefined;
|
|
2809
|
+
}
|
|
2810
|
+
return snippet.length <= options.maxChars
|
|
2811
|
+
? snippet
|
|
2812
|
+
: snippet.slice(0, options.maxChars);
|
|
2813
|
+
}
|
|
2814
|
+
function findTestStart(lines, fromIndex) {
|
|
2815
|
+
for (let i = fromIndex; i >= 0; i--) {
|
|
2816
|
+
// Walk upward from runner-provided line metadata until we hit a JS/TS
|
|
2817
|
+
// test/it call, including common modifiers used by Vitest/Playwright.
|
|
2818
|
+
if (/\b(?:test|it)(?:\.(?:only|skip|fixme|slow))?\s*\(/.test(lines[i])) {
|
|
2819
|
+
return i;
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
return undefined;
|
|
2823
|
+
}
|
|
2824
|
+
function isJsTestBlockTerminator(line) {
|
|
2825
|
+
let i = line.length - 1;
|
|
2826
|
+
while (i >= 0 && /\s/.test(line[i])) {
|
|
2827
|
+
i--;
|
|
2828
|
+
}
|
|
2829
|
+
if (i >= 0 && line[i] === ';') {
|
|
2830
|
+
i--;
|
|
2831
|
+
}
|
|
2832
|
+
while (i >= 0 && /\s/.test(line[i])) {
|
|
2833
|
+
i--;
|
|
2834
|
+
}
|
|
2835
|
+
if (i < 1 || line[i] !== ')') {
|
|
2836
|
+
return false;
|
|
2837
|
+
}
|
|
2838
|
+
i--;
|
|
2839
|
+
while (i >= 0 && /\s/.test(line[i])) {
|
|
2840
|
+
i--;
|
|
2841
|
+
}
|
|
2842
|
+
return i >= 0 && line[i] === '}';
|
|
2843
|
+
}
|
|
2844
|
+
function isInsideSourceRoot(filePath, sourceRoot) {
|
|
2845
|
+
const relative = node_path_1.default.relative(sourceRoot, filePath);
|
|
2846
|
+
return relative.length > 0 && !relative.startsWith('..') && !node_path_1.default.isAbsolute(relative);
|
|
2847
|
+
}
|
|
2848
|
+
function normalizePositiveInt(value, fallback) {
|
|
2849
|
+
return typeof value === 'number' && Number.isInteger(value) && value > 0
|
|
2850
|
+
? value
|
|
2851
|
+
: fallback;
|
|
2852
|
+
}
|
|
2853
|
+
//# sourceMappingURL=source-snippets.js.map
|
|
2854
|
+
|
|
2855
|
+
/***/ }),
|
|
2856
|
+
|
|
2857
|
+
/***/ 2293:
|
|
2858
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
2859
|
+
|
|
2860
|
+
"use strict";
|
|
2861
|
+
|
|
2862
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2863
|
+
exports.createTestLocationCollector = createTestLocationCollector;
|
|
2864
|
+
/**
|
|
2865
|
+
* Generic name-based location mapper for CTRF reports.
|
|
2866
|
+
*
|
|
2867
|
+
* Different reporters can collect test locations in their own format
|
|
2868
|
+
* (Playwright runtime metadata, parsed JUnit XML, etc.) and then feed
|
|
2869
|
+
* this collector to apply file/line metadata in a consistent FIFO way.
|
|
2870
|
+
*/
|
|
2871
|
+
function createTestLocationCollector() {
|
|
2872
|
+
const locationsByTestName = new Map();
|
|
2873
|
+
return {
|
|
2874
|
+
add(testName, location) {
|
|
2875
|
+
if (!testName || !isValidLocation(location)) {
|
|
2876
|
+
return;
|
|
2877
|
+
}
|
|
2878
|
+
const queue = locationsByTestName.get(testName) ?? [];
|
|
2879
|
+
queue.push(location);
|
|
2880
|
+
locationsByTestName.set(testName, queue);
|
|
2881
|
+
},
|
|
2882
|
+
applyToReport(report) {
|
|
2883
|
+
const queues = new Map([...locationsByTestName.entries()].map(([name, locations]) => [name, [...locations]]));
|
|
2884
|
+
for (const test of report.results.tests) {
|
|
2885
|
+
const queue = queues.get(test.name);
|
|
2886
|
+
const location = queue?.shift();
|
|
2887
|
+
if (!location) {
|
|
2888
|
+
continue;
|
|
2889
|
+
}
|
|
2890
|
+
test.filePath ?? (test.filePath = location.filePath);
|
|
2891
|
+
test.line ?? (test.line = location.line);
|
|
2892
|
+
}
|
|
2893
|
+
},
|
|
2894
|
+
};
|
|
2895
|
+
}
|
|
2896
|
+
function isValidLocation(location) {
|
|
2897
|
+
return Boolean(location.filePath) && Number.isInteger(location.line) && location.line > 0;
|
|
2898
|
+
}
|
|
2899
|
+
//# sourceMappingURL=test-locations.js.map
|
|
2900
|
+
|
|
2901
|
+
/***/ }),
|
|
2902
|
+
|
|
2903
|
+
/***/ 8969:
|
|
2345
2904
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
2346
2905
|
|
|
2347
2906
|
"use strict";
|
|
@@ -2351,10 +2910,12 @@ exports.ensureReportId = ensureReportId;
|
|
|
2351
2910
|
exports.uploadTestRun = uploadTestRun;
|
|
2352
2911
|
exports.mapAttachmentsToTestResults = mapAttachmentsToTestResults;
|
|
2353
2912
|
exports.uploadArtifacts = uploadArtifacts;
|
|
2354
|
-
const ci_detection_1 = __nccwpck_require__(
|
|
2355
|
-
const
|
|
2913
|
+
const ci_detection_1 = __nccwpck_require__(2406);
|
|
2914
|
+
const source_snippets_1 = __nccwpck_require__(9304);
|
|
2915
|
+
const DEFAULT_API_URL = "https://api.testream.app";
|
|
2356
2916
|
function ensureReportId(report) {
|
|
2357
|
-
if (typeof report.reportId ===
|
|
2917
|
+
if (typeof report.reportId === "string" &&
|
|
2918
|
+
report.reportId.trim().length > 0) {
|
|
2358
2919
|
return report.reportId;
|
|
2359
2920
|
}
|
|
2360
2921
|
const reportId = crypto.randomUUID();
|
|
@@ -2373,7 +2934,7 @@ function resolveApiUrl(explicitApiUrl) {
|
|
|
2373
2934
|
return DEFAULT_API_URL;
|
|
2374
2935
|
}
|
|
2375
2936
|
function getEnvApiUrl() {
|
|
2376
|
-
if (typeof process ===
|
|
2937
|
+
if (typeof process === "undefined" || !process?.env) {
|
|
2377
2938
|
return undefined;
|
|
2378
2939
|
}
|
|
2379
2940
|
return normalizeApiUrl(process.env.TESTREAM_API_URL);
|
|
@@ -2386,20 +2947,25 @@ function normalizeApiUrl(value) {
|
|
|
2386
2947
|
if (!trimmed) {
|
|
2387
2948
|
return undefined;
|
|
2388
2949
|
}
|
|
2389
|
-
|
|
2950
|
+
// Use while loop instead of regex for better performance and clarity
|
|
2951
|
+
let result = trimmed;
|
|
2952
|
+
while (result.endsWith("/")) {
|
|
2953
|
+
result = result.slice(0, -1);
|
|
2954
|
+
}
|
|
2955
|
+
return result;
|
|
2390
2956
|
}
|
|
2391
2957
|
function isReportAlreadyExistsConflict(error) {
|
|
2392
|
-
return error.errorCode ===
|
|
2958
|
+
return error.errorCode === "report_already_exists";
|
|
2393
2959
|
}
|
|
2394
2960
|
function formatUploadError(error) {
|
|
2395
|
-
const detail = error.detail || error.title || error.rawBody ||
|
|
2396
|
-
const codeLabel = error.errorCode ? `, code=${error.errorCode}` :
|
|
2961
|
+
const detail = error.detail || error.title || error.rawBody || "Unknown error";
|
|
2962
|
+
const codeLabel = error.errorCode ? `, code=${error.errorCode}` : "";
|
|
2397
2963
|
return `Upload failed (HTTP ${error.statusCode}${codeLabel}): ${detail}`;
|
|
2398
2964
|
}
|
|
2399
2965
|
async function parseHttpError(response) {
|
|
2400
2966
|
const rawBody = await response.text();
|
|
2401
|
-
const contentType = response.headers.get(
|
|
2402
|
-
if (contentType.toLowerCase().includes(
|
|
2967
|
+
const contentType = response.headers.get("content-type") || "";
|
|
2968
|
+
if (contentType.toLowerCase().includes("json") && rawBody.trim().length > 0) {
|
|
2403
2969
|
try {
|
|
2404
2970
|
const parsed = JSON.parse(rawBody);
|
|
2405
2971
|
return {
|
|
@@ -2442,6 +3008,7 @@ async function uploadTestRun(options) {
|
|
|
2442
3008
|
const apiUrl = resolveApiUrl(options.apiUrl);
|
|
2443
3009
|
const reportId = ensureReportId(report);
|
|
2444
3010
|
const uploadContext = resolveUploadContext(options);
|
|
3011
|
+
await (0, source_snippets_1.enrichReportWithSourceSnippets)(report);
|
|
2445
3012
|
// Build type-safe IngestRequest payload
|
|
2446
3013
|
const ingestPayload = {
|
|
2447
3014
|
report,
|
|
@@ -2449,14 +3016,14 @@ async function uploadTestRun(options) {
|
|
|
2449
3016
|
...uploadContext,
|
|
2450
3017
|
};
|
|
2451
3018
|
// Professional logging
|
|
2452
|
-
console.log(
|
|
3019
|
+
console.log("Uploading test results...");
|
|
2453
3020
|
let response;
|
|
2454
3021
|
try {
|
|
2455
3022
|
response = await fetch(`${apiUrl}/api/v1/ingest`, {
|
|
2456
|
-
method:
|
|
3023
|
+
method: "POST",
|
|
2457
3024
|
headers: {
|
|
2458
|
-
|
|
2459
|
-
|
|
3025
|
+
"X-API-KEY": apiKey,
|
|
3026
|
+
"Content-Type": "application/json",
|
|
2460
3027
|
},
|
|
2461
3028
|
body: JSON.stringify(ingestPayload),
|
|
2462
3029
|
});
|
|
@@ -2474,7 +3041,7 @@ async function uploadTestRun(options) {
|
|
|
2474
3041
|
if (!response.ok) {
|
|
2475
3042
|
const parsedError = await parseHttpError(response);
|
|
2476
3043
|
if (response.status === 409 && isReportAlreadyExistsConflict(parsedError)) {
|
|
2477
|
-
console.warn(
|
|
3044
|
+
console.warn("Report already exists (workflow may have been re-run)");
|
|
2478
3045
|
return {
|
|
2479
3046
|
success: true,
|
|
2480
3047
|
reportId,
|
|
@@ -2582,8 +3149,8 @@ async function uploadArtifacts(options) {
|
|
|
2582
3149
|
async function uploadSingleArtifact(options) {
|
|
2583
3150
|
const { testResultId, attachment, reportId, apiKey, apiUrl } = options;
|
|
2584
3151
|
// Dynamically import fs for Node.js environments
|
|
2585
|
-
const fs = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__,
|
|
2586
|
-
const path = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__,
|
|
3152
|
+
const fs = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 1455, 23));
|
|
3153
|
+
const path = await Promise.resolve(/* import() */).then(__nccwpck_require__.t.bind(__nccwpck_require__, 6760, 23));
|
|
2587
3154
|
const filePath = path.resolve(attachment.path);
|
|
2588
3155
|
// Check if file exists
|
|
2589
3156
|
try {
|
|
@@ -2597,7 +3164,7 @@ async function uploadSingleArtifact(options) {
|
|
|
2597
3164
|
let fileBuffer;
|
|
2598
3165
|
let sizeBytes;
|
|
2599
3166
|
const fileName = path.basename(filePath);
|
|
2600
|
-
const contentType = attachment.contentType ||
|
|
3167
|
+
const contentType = attachment.contentType || "application/octet-stream";
|
|
2601
3168
|
try {
|
|
2602
3169
|
fileBuffer = await fs.readFile(filePath);
|
|
2603
3170
|
sizeBytes = fileBuffer.byteLength;
|
|
@@ -2637,7 +3204,7 @@ async function uploadSingleArtifact(options) {
|
|
|
2637
3204
|
}
|
|
2638
3205
|
class LegacyUploadRequiredError extends Error {
|
|
2639
3206
|
constructor() {
|
|
2640
|
-
super(
|
|
3207
|
+
super("Legacy upload endpoint required");
|
|
2641
3208
|
}
|
|
2642
3209
|
}
|
|
2643
3210
|
async function uploadWithPresignedUrl(options) {
|
|
@@ -2650,10 +3217,10 @@ async function uploadWithPresignedUrl(options) {
|
|
|
2650
3217
|
sizeBytes,
|
|
2651
3218
|
};
|
|
2652
3219
|
const initResponse = await fetch(`${apiUrl}/api/v1/artifacts/${reportId}/upload-url`, {
|
|
2653
|
-
method:
|
|
3220
|
+
method: "POST",
|
|
2654
3221
|
headers: {
|
|
2655
|
-
|
|
2656
|
-
|
|
3222
|
+
"X-API-KEY": apiKey,
|
|
3223
|
+
"Content-Type": "application/json",
|
|
2657
3224
|
},
|
|
2658
3225
|
body: JSON.stringify(initPayload),
|
|
2659
3226
|
});
|
|
@@ -2665,12 +3232,14 @@ async function uploadWithPresignedUrl(options) {
|
|
|
2665
3232
|
throw new Error(`Failed to create direct upload URL (HTTP ${initResponse.status}): ${errorText}`);
|
|
2666
3233
|
}
|
|
2667
3234
|
const uploadInitResult = (await initResponse.json());
|
|
2668
|
-
const uploadHeaders = {
|
|
2669
|
-
|
|
2670
|
-
|
|
3235
|
+
const uploadHeaders = {
|
|
3236
|
+
...(uploadInitResult.requiredHeaders),
|
|
3237
|
+
};
|
|
3238
|
+
if (!hasHeaderIgnoreCase(uploadHeaders, "Content-Type")) {
|
|
3239
|
+
uploadHeaders["Content-Type"] = contentType;
|
|
2671
3240
|
}
|
|
2672
3241
|
const directUploadResponse = await fetch(uploadInitResult.uploadUrl, {
|
|
2673
|
-
method:
|
|
3242
|
+
method: "PUT",
|
|
2674
3243
|
headers: uploadHeaders,
|
|
2675
3244
|
body: fileBuffer,
|
|
2676
3245
|
});
|
|
@@ -2687,10 +3256,10 @@ async function uploadWithPresignedUrl(options) {
|
|
|
2687
3256
|
storageKey: uploadInitResult.storageKey,
|
|
2688
3257
|
};
|
|
2689
3258
|
const completeResponse = await fetch(`${apiUrl}/api/v1/artifacts/${reportId}/complete`, {
|
|
2690
|
-
method:
|
|
3259
|
+
method: "POST",
|
|
2691
3260
|
headers: {
|
|
2692
|
-
|
|
2693
|
-
|
|
3261
|
+
"X-API-KEY": apiKey,
|
|
3262
|
+
"Content-Type": "application/json",
|
|
2694
3263
|
},
|
|
2695
3264
|
body: JSON.stringify(completePayload),
|
|
2696
3265
|
});
|
|
@@ -2701,16 +3270,16 @@ async function uploadWithPresignedUrl(options) {
|
|
|
2701
3270
|
return true;
|
|
2702
3271
|
}
|
|
2703
3272
|
async function uploadWithLegacyEndpoint(options) {
|
|
2704
|
-
const { testResultId, attachmentName, reportId, apiKey, apiUrl, fileName, contentType, fileBuffer } = options;
|
|
3273
|
+
const { testResultId, attachmentName, reportId, apiKey, apiUrl, fileName, contentType, fileBuffer, } = options;
|
|
2705
3274
|
const blob = new Blob([new Uint8Array(fileBuffer)], { type: contentType });
|
|
2706
3275
|
const formData = new FormData();
|
|
2707
|
-
formData.append(
|
|
2708
|
-
formData.append(
|
|
2709
|
-
formData.append(
|
|
3276
|
+
formData.append("testResultId", testResultId);
|
|
3277
|
+
formData.append("ctrfAttachmentName", attachmentName);
|
|
3278
|
+
formData.append("file", blob, fileName);
|
|
2710
3279
|
const response = await fetch(`${apiUrl}/api/v1/artifacts/${reportId}`, {
|
|
2711
|
-
method:
|
|
3280
|
+
method: "POST",
|
|
2712
3281
|
headers: {
|
|
2713
|
-
|
|
3282
|
+
"X-API-KEY": apiKey,
|
|
2714
3283
|
},
|
|
2715
3284
|
body: formData,
|
|
2716
3285
|
});
|
|
@@ -2731,7 +3300,7 @@ function hasHeaderIgnoreCase(headers, headerName) {
|
|
|
2731
3300
|
|
|
2732
3301
|
/***/ }),
|
|
2733
3302
|
|
|
2734
|
-
/***/
|
|
3303
|
+
/***/ 4328:
|
|
2735
3304
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
2736
3305
|
|
|
2737
3306
|
"use strict";
|
|
@@ -2771,14 +3340,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
2771
3340
|
})();
|
|
2772
3341
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2773
3342
|
const glob_1 = __nccwpck_require__(447);
|
|
2774
|
-
const path = __importStar(__nccwpck_require__(
|
|
2775
|
-
const fs = __importStar(__nccwpck_require__(
|
|
3343
|
+
const path = __importStar(__nccwpck_require__(6928));
|
|
3344
|
+
const fs = __importStar(__nccwpck_require__(1943));
|
|
2776
3345
|
const os = __importStar(__nccwpck_require__(857));
|
|
2777
|
-
const child_process_1 = __nccwpck_require__(
|
|
2778
|
-
const trx_parser_1 = __nccwpck_require__(
|
|
2779
|
-
const uploader_1 = __nccwpck_require__(
|
|
3346
|
+
const child_process_1 = __nccwpck_require__(5317);
|
|
3347
|
+
const trx_parser_1 = __nccwpck_require__(8914);
|
|
3348
|
+
const uploader_1 = __nccwpck_require__(8010);
|
|
2780
3349
|
function printUsage() {
|
|
2781
|
-
console.log(`
|
|
3350
|
+
console.log(String.raw `
|
|
2782
3351
|
@testream/dotnet-reporter - Run .NET tests and upload results to Testream
|
|
2783
3352
|
|
|
2784
3353
|
Usage:
|
|
@@ -2823,7 +3392,7 @@ Examples:
|
|
|
2823
3392
|
npx @testream/dotnet-reporter -k your-api-key --project ./MyTests
|
|
2824
3393
|
|
|
2825
3394
|
# With environment metadata
|
|
2826
|
-
npx @testream/dotnet-reporter -k your-api-key
|
|
3395
|
+
npx @testream/dotnet-reporter -k your-api-key \
|
|
2827
3396
|
--test-environment staging --app-name MyApp --app-version 1.0.0
|
|
2828
3397
|
|
|
2829
3398
|
# Pass additional arguments to dotnet test
|
|
@@ -2960,15 +3529,15 @@ async function runDotnetTest(projectPath, additionalArgs = []) {
|
|
|
2960
3529
|
const logger = console;
|
|
2961
3530
|
// Create temp directory for TRX output
|
|
2962
3531
|
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'dotnet-reporter-'));
|
|
2963
|
-
const trxFileName = `results-${Date.now()}.trx`;
|
|
2964
3532
|
// Build dotnet test command
|
|
2965
3533
|
const args = ['test'];
|
|
2966
3534
|
if (projectPath) {
|
|
2967
3535
|
args.push(projectPath);
|
|
2968
3536
|
}
|
|
2969
|
-
// Add TRX logger
|
|
2970
|
-
|
|
2971
|
-
|
|
3537
|
+
// Add TRX logger without a fixed filename so each test project gets a unique
|
|
3538
|
+
// TRX file. Specifying LogFileName causes all projects in a solution to write
|
|
3539
|
+
// to the same file, with later projects overwriting earlier ones.
|
|
3540
|
+
args.push('--logger', 'trx', '--results-directory', tempDir);
|
|
2972
3541
|
// Add any additional user-provided args
|
|
2973
3542
|
args.push(...additionalArgs);
|
|
2974
3543
|
logger.info('Running dotnet test...');
|
|
@@ -3094,7 +3663,308 @@ main();
|
|
|
3094
3663
|
|
|
3095
3664
|
/***/ }),
|
|
3096
3665
|
|
|
3097
|
-
/***/
|
|
3666
|
+
/***/ 148:
|
|
3667
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
3668
|
+
|
|
3669
|
+
"use strict";
|
|
3670
|
+
|
|
3671
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3672
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
3673
|
+
};
|
|
3674
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3675
|
+
exports.createDotnetSourceSnippetResolver = createDotnetSourceSnippetResolver;
|
|
3676
|
+
exports.extractDotnetSourceSnippet = extractDotnetSourceSnippet;
|
|
3677
|
+
exports.resolveDotnetSourceSnippet = resolveDotnetSourceSnippet;
|
|
3678
|
+
const promises_1 = __nccwpck_require__(1455);
|
|
3679
|
+
const node_path_1 = __importDefault(__nccwpck_require__(6760));
|
|
3680
|
+
const DEFAULT_MAX_CHARS = 2000;
|
|
3681
|
+
const DEFAULT_MAX_LINES = 40;
|
|
3682
|
+
function createDotnetSourceSnippetResolver() {
|
|
3683
|
+
const cache = {
|
|
3684
|
+
candidateSourceFiles: new Map(),
|
|
3685
|
+
fileContentByPath: new Map(),
|
|
3686
|
+
};
|
|
3687
|
+
return {
|
|
3688
|
+
resolve: (options) => resolveDotnetSourceSnippet(options, cache),
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3691
|
+
async function extractDotnetSourceSnippet(filePath, methodName, lineNumber) {
|
|
3692
|
+
const result = await resolveDotnetSourceSnippet({ filePath, methodName, lineNumber });
|
|
3693
|
+
return result?.snippet;
|
|
3694
|
+
}
|
|
3695
|
+
async function resolveDotnetSourceSnippet(options, cache) {
|
|
3696
|
+
if (!options.filePath || !options.methodName) {
|
|
3697
|
+
return undefined;
|
|
3698
|
+
}
|
|
3699
|
+
const direct = await tryExtractFromSourceFile(options.filePath, options.methodName, options.lineNumber, cache);
|
|
3700
|
+
if (direct) {
|
|
3701
|
+
return direct;
|
|
3702
|
+
}
|
|
3703
|
+
const candidates = await getCandidateSourceFiles(options.filePath, options.className, cache);
|
|
3704
|
+
for (const candidate of candidates) {
|
|
3705
|
+
const resolved = await tryExtractFromSourceFile(candidate, options.methodName, options.lineNumber, cache);
|
|
3706
|
+
if (resolved) {
|
|
3707
|
+
return resolved;
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3710
|
+
return undefined;
|
|
3711
|
+
}
|
|
3712
|
+
async function tryExtractFromSourceFile(filePath, methodName, lineNumber, cache) {
|
|
3713
|
+
if (node_path_1.default.extname(filePath).toLowerCase() !== '.cs') {
|
|
3714
|
+
return undefined;
|
|
3715
|
+
}
|
|
3716
|
+
const resolvedPath = node_path_1.default.resolve(filePath);
|
|
3717
|
+
const content = await getFileContent(resolvedPath, cache);
|
|
3718
|
+
if (!content) {
|
|
3719
|
+
return undefined;
|
|
3720
|
+
}
|
|
3721
|
+
for (const candidateMethodName of getMethodNameCandidates(methodName)) {
|
|
3722
|
+
const extracted = extractCSharpMethodBlock(content, candidateMethodName, lineNumber);
|
|
3723
|
+
if (extracted) {
|
|
3724
|
+
return { filePath: resolvedPath, ...extracted };
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
return undefined;
|
|
3728
|
+
}
|
|
3729
|
+
function getFileContent(filePath, cache) {
|
|
3730
|
+
if (!cache) {
|
|
3731
|
+
return (0, promises_1.readFile)(filePath, 'utf-8').catch(() => undefined);
|
|
3732
|
+
}
|
|
3733
|
+
let cached = cache.fileContentByPath.get(filePath);
|
|
3734
|
+
if (!cached) {
|
|
3735
|
+
cached = (0, promises_1.readFile)(filePath, 'utf-8').catch(() => undefined);
|
|
3736
|
+
cache.fileContentByPath.set(filePath, cached);
|
|
3737
|
+
}
|
|
3738
|
+
return cached;
|
|
3739
|
+
}
|
|
3740
|
+
function extractCSharpMethodBlock(content, methodName, lineNumber) {
|
|
3741
|
+
const lines = content.split(/\r?\n/);
|
|
3742
|
+
const definitionIndex = findMethodDefinitionNearLine(lines, methodName, lineNumber) ??
|
|
3743
|
+
findMethodDefinition(lines, methodName);
|
|
3744
|
+
if (definitionIndex == null) {
|
|
3745
|
+
return undefined;
|
|
3746
|
+
}
|
|
3747
|
+
const start = includeCSharpAttributes(lines, definitionIndex);
|
|
3748
|
+
const selected = [];
|
|
3749
|
+
let braceBalance = 0;
|
|
3750
|
+
let sawOpeningBrace = false;
|
|
3751
|
+
let isExpressionBodied = false;
|
|
3752
|
+
for (let i = start; i < lines.length && selected.length < DEFAULT_MAX_LINES; i++) {
|
|
3753
|
+
const line = lines[i];
|
|
3754
|
+
selected.push(line);
|
|
3755
|
+
if (!sawOpeningBrace && line.includes('=>')) {
|
|
3756
|
+
isExpressionBodied = true;
|
|
3757
|
+
}
|
|
3758
|
+
for (const char of line) {
|
|
3759
|
+
if (char === '{') {
|
|
3760
|
+
braceBalance++;
|
|
3761
|
+
sawOpeningBrace = true;
|
|
3762
|
+
}
|
|
3763
|
+
else if (char === '}') {
|
|
3764
|
+
braceBalance--;
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
if (isExpressionBodied && line.includes(';')) {
|
|
3768
|
+
break;
|
|
3769
|
+
}
|
|
3770
|
+
if (sawOpeningBrace && braceBalance <= 0) {
|
|
3771
|
+
break;
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
const snippet = selected.join('\n').trim();
|
|
3775
|
+
if (!snippet) {
|
|
3776
|
+
return undefined;
|
|
3777
|
+
}
|
|
3778
|
+
return {
|
|
3779
|
+
line: start + 1,
|
|
3780
|
+
snippet: snippet.length <= DEFAULT_MAX_CHARS ? snippet : snippet.slice(0, DEFAULT_MAX_CHARS),
|
|
3781
|
+
};
|
|
3782
|
+
}
|
|
3783
|
+
function findMethodDefinitionNearLine(lines, methodName, lineNumber) {
|
|
3784
|
+
if (!lineNumber) {
|
|
3785
|
+
return undefined;
|
|
3786
|
+
}
|
|
3787
|
+
const startIndex = Math.max(0, Math.min(lines.length - 1, lineNumber - 1));
|
|
3788
|
+
for (let i = startIndex; i >= 0; i--) {
|
|
3789
|
+
if (containsMethodSignatureName(lines[i], methodName)) {
|
|
3790
|
+
return i;
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
return undefined;
|
|
3794
|
+
}
|
|
3795
|
+
function findMethodDefinition(lines, methodName) {
|
|
3796
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3797
|
+
if (containsMethodSignatureName(lines[i], methodName)) {
|
|
3798
|
+
return i;
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
return undefined;
|
|
3802
|
+
}
|
|
3803
|
+
function containsMethodSignatureName(line, methodName) {
|
|
3804
|
+
const nameIndex = line.indexOf(methodName);
|
|
3805
|
+
if (nameIndex < 0) {
|
|
3806
|
+
return false;
|
|
3807
|
+
}
|
|
3808
|
+
const before = nameIndex === 0 ? '' : line[nameIndex - 1];
|
|
3809
|
+
if (before && isIdentifierChar(before)) {
|
|
3810
|
+
return false;
|
|
3811
|
+
}
|
|
3812
|
+
let i = nameIndex + methodName.length;
|
|
3813
|
+
while (i < line.length && /\s/.test(line[i])) {
|
|
3814
|
+
i++;
|
|
3815
|
+
}
|
|
3816
|
+
return line[i] === '(';
|
|
3817
|
+
}
|
|
3818
|
+
function includeCSharpAttributes(lines, definitionIndex) {
|
|
3819
|
+
let start = definitionIndex;
|
|
3820
|
+
while (start > 0) {
|
|
3821
|
+
const previous = lines[start - 1].trim();
|
|
3822
|
+
if (!previous.startsWith('[') || !previous.endsWith(']')) {
|
|
3823
|
+
break;
|
|
3824
|
+
}
|
|
3825
|
+
start--;
|
|
3826
|
+
}
|
|
3827
|
+
return start;
|
|
3828
|
+
}
|
|
3829
|
+
function getMethodNameCandidates(methodName) {
|
|
3830
|
+
const trimmed = methodName.trim();
|
|
3831
|
+
const candidates = [trimmed];
|
|
3832
|
+
const invocationIndex = trimmed.indexOf('(');
|
|
3833
|
+
// NUnit can put TestCase argument values in TestMethod/@name, e.g.
|
|
3834
|
+
// Password_MinimumLength_Validation("pass",False). Source matching needs
|
|
3835
|
+
// the underlying C# method identifier.
|
|
3836
|
+
if (invocationIndex > 0) {
|
|
3837
|
+
const sourceMethodName = trimmed.slice(0, invocationIndex).trim();
|
|
3838
|
+
if (sourceMethodName && sourceMethodName !== trimmed) {
|
|
3839
|
+
candidates.push(sourceMethodName);
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
return candidates;
|
|
3843
|
+
}
|
|
3844
|
+
async function findCandidateSourceFiles(storagePath, className) {
|
|
3845
|
+
const sourceRoot = getProjectSourceRootFromStorage(storagePath);
|
|
3846
|
+
if (!sourceRoot) {
|
|
3847
|
+
return [];
|
|
3848
|
+
}
|
|
3849
|
+
const resolvedSourceRoot = await resolveExistingDirectoryCaseInsensitive(sourceRoot);
|
|
3850
|
+
if (!resolvedSourceRoot) {
|
|
3851
|
+
return [];
|
|
3852
|
+
}
|
|
3853
|
+
const files = await listCSharpFiles(resolvedSourceRoot);
|
|
3854
|
+
const classFileName = getClassFileName(className);
|
|
3855
|
+
if (!classFileName) {
|
|
3856
|
+
return files;
|
|
3857
|
+
}
|
|
3858
|
+
// TRX commonly stores passed tests against the compiled DLL. Prefer the class
|
|
3859
|
+
// filename when available, then fall back to every source file for cases where
|
|
3860
|
+
// a project keeps multiple test classes in one file.
|
|
3861
|
+
return [
|
|
3862
|
+
...files.filter((file) => node_path_1.default.basename(file).toLowerCase() === classFileName),
|
|
3863
|
+
...files.filter((file) => node_path_1.default.basename(file).toLowerCase() !== classFileName),
|
|
3864
|
+
];
|
|
3865
|
+
}
|
|
3866
|
+
function getCandidateSourceFiles(storagePath, className, cache) {
|
|
3867
|
+
if (!cache) {
|
|
3868
|
+
return findCandidateSourceFiles(storagePath, className);
|
|
3869
|
+
}
|
|
3870
|
+
const key = `${node_path_1.default.resolve(storagePath)}\0${className ?? ''}`;
|
|
3871
|
+
let cached = cache.candidateSourceFiles.get(key);
|
|
3872
|
+
if (!cached) {
|
|
3873
|
+
cached = findCandidateSourceFiles(storagePath, className);
|
|
3874
|
+
cache.candidateSourceFiles.set(key, cached);
|
|
3875
|
+
}
|
|
3876
|
+
return cached;
|
|
3877
|
+
}
|
|
3878
|
+
function getProjectSourceRootFromStorage(storagePath) {
|
|
3879
|
+
const resolved = node_path_1.default.resolve(storagePath);
|
|
3880
|
+
const parts = resolved.split(node_path_1.default.sep);
|
|
3881
|
+
// /Project/bin/Debug/net8.0/Project.dll is the normal TRX storage path for
|
|
3882
|
+
// passed tests, so the source root is the directory before bin/.
|
|
3883
|
+
const binIndex = parts.findIndex((part) => part.toLowerCase() === 'bin');
|
|
3884
|
+
if (binIndex <= 0) {
|
|
3885
|
+
return undefined;
|
|
3886
|
+
}
|
|
3887
|
+
return parts.slice(0, binIndex).join(node_path_1.default.sep) || node_path_1.default.sep;
|
|
3888
|
+
}
|
|
3889
|
+
async function resolveExistingDirectoryCaseInsensitive(dirPath) {
|
|
3890
|
+
try {
|
|
3891
|
+
await (0, promises_1.readdir)(dirPath, { withFileTypes: true });
|
|
3892
|
+
return dirPath;
|
|
3893
|
+
}
|
|
3894
|
+
catch {
|
|
3895
|
+
// TRX storage paths can lowercase project output paths on Linux
|
|
3896
|
+
// (`mstesttests/bin/...`) while the checked-out source directory is
|
|
3897
|
+
// case-sensitive (`MSTestTests`). Walk each segment case-insensitively so
|
|
3898
|
+
// passed tests can still resolve their project source root.
|
|
3899
|
+
}
|
|
3900
|
+
const resolved = node_path_1.default.resolve(dirPath);
|
|
3901
|
+
const parsed = node_path_1.default.parse(resolved);
|
|
3902
|
+
const relativeParts = node_path_1.default.relative(parsed.root, resolved).split(node_path_1.default.sep).filter(Boolean);
|
|
3903
|
+
let current = parsed.root;
|
|
3904
|
+
for (const part of relativeParts) {
|
|
3905
|
+
let entries;
|
|
3906
|
+
try {
|
|
3907
|
+
entries = await (0, promises_1.readdir)(current, { withFileTypes: true });
|
|
3908
|
+
}
|
|
3909
|
+
catch {
|
|
3910
|
+
return undefined;
|
|
3911
|
+
}
|
|
3912
|
+
const match = entries.find((entry) => entry.name === part) ??
|
|
3913
|
+
entries.find((entry) => entry.name.toLowerCase() === part.toLowerCase());
|
|
3914
|
+
if (!match) {
|
|
3915
|
+
return undefined;
|
|
3916
|
+
}
|
|
3917
|
+
current = node_path_1.default.join(current, match.name);
|
|
3918
|
+
}
|
|
3919
|
+
try {
|
|
3920
|
+
await (0, promises_1.readdir)(current, { withFileTypes: true });
|
|
3921
|
+
return current;
|
|
3922
|
+
}
|
|
3923
|
+
catch {
|
|
3924
|
+
return undefined;
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
async function listCSharpFiles(root) {
|
|
3928
|
+
const files = [];
|
|
3929
|
+
async function visit(dir) {
|
|
3930
|
+
let entries;
|
|
3931
|
+
try {
|
|
3932
|
+
entries = await (0, promises_1.readdir)(dir, { withFileTypes: true });
|
|
3933
|
+
}
|
|
3934
|
+
catch {
|
|
3935
|
+
return;
|
|
3936
|
+
}
|
|
3937
|
+
for (const entry of entries) {
|
|
3938
|
+
const entryPath = node_path_1.default.join(dir, entry.name);
|
|
3939
|
+
if (entry.isDirectory()) {
|
|
3940
|
+
const lowerName = entry.name.toLowerCase();
|
|
3941
|
+
if (lowerName === 'bin' || lowerName === 'obj') {
|
|
3942
|
+
continue;
|
|
3943
|
+
}
|
|
3944
|
+
await visit(entryPath);
|
|
3945
|
+
continue;
|
|
3946
|
+
}
|
|
3947
|
+
if (entry.isFile() && node_path_1.default.extname(entry.name).toLowerCase() === '.cs') {
|
|
3948
|
+
files.push(entryPath);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
await visit(root);
|
|
3953
|
+
return files;
|
|
3954
|
+
}
|
|
3955
|
+
function getClassFileName(className) {
|
|
3956
|
+
const shortName = className?.split(/[.+]/).filter(Boolean).pop();
|
|
3957
|
+
return shortName ? `${shortName.toLowerCase()}.cs` : undefined;
|
|
3958
|
+
}
|
|
3959
|
+
function isIdentifierChar(char) {
|
|
3960
|
+
// Prevent matching a method name inside another common C# identifier.
|
|
3961
|
+
return /[A-Za-z0-9_]/.test(char);
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
|
|
3965
|
+
/***/ }),
|
|
3966
|
+
|
|
3967
|
+
/***/ 8914:
|
|
3098
3968
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
3099
3969
|
|
|
3100
3970
|
"use strict";
|
|
@@ -3135,16 +4005,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
3135
4005
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3136
4006
|
exports.parseTrxFile = parseTrxFile;
|
|
3137
4007
|
exports.parseTrxFiles = parseTrxFiles;
|
|
3138
|
-
const fs = __importStar(__nccwpck_require__(
|
|
3139
|
-
const fast_xml_parser_1 = __nccwpck_require__(
|
|
4008
|
+
const fs = __importStar(__nccwpck_require__(1455));
|
|
4009
|
+
const fast_xml_parser_1 = __nccwpck_require__(1537);
|
|
4010
|
+
const node_crypto_1 = __nccwpck_require__(7598);
|
|
4011
|
+
const source_snippets_1 = __nccwpck_require__(148);
|
|
3140
4012
|
const TOOL_NAME = 'dotnet';
|
|
3141
|
-
//
|
|
4013
|
+
// Use crypto.randomUUID() for secure UUID generation (available in Node.js 15.7.0+)
|
|
3142
4014
|
function generateUUID() {
|
|
3143
|
-
return
|
|
3144
|
-
const r = (Math.random() * 16) | 0;
|
|
3145
|
-
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
3146
|
-
return v.toString(16);
|
|
3147
|
-
});
|
|
4015
|
+
return (0, node_crypto_1.randomUUID)();
|
|
3148
4016
|
}
|
|
3149
4017
|
/**
|
|
3150
4018
|
* Parse TRX duration string (HH:MM:SS.mmmmmmm) to milliseconds
|
|
@@ -3152,13 +4020,22 @@ function generateUUID() {
|
|
|
3152
4020
|
function parseDuration(duration) {
|
|
3153
4021
|
if (!duration)
|
|
3154
4022
|
return 0;
|
|
3155
|
-
|
|
3156
|
-
|
|
4023
|
+
// Use split() instead of regex to avoid ReDoS vulnerability
|
|
4024
|
+
const parts = duration.split(':');
|
|
4025
|
+
if (parts.length !== 3)
|
|
3157
4026
|
return 0;
|
|
3158
|
-
const hours = parseInt(
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
const
|
|
4027
|
+
const hours = parseInt(parts[0], 10);
|
|
4028
|
+
if (Number.isNaN(hours))
|
|
4029
|
+
return 0;
|
|
4030
|
+
const minutes = parseInt(parts[1], 10);
|
|
4031
|
+
if (Number.isNaN(minutes))
|
|
4032
|
+
return 0;
|
|
4033
|
+
// Handle seconds and fractional part (may contain decimal point)
|
|
4034
|
+
const secondsParts = parts[2].split('.');
|
|
4035
|
+
const seconds = Number.parseInt(secondsParts[0], 10);
|
|
4036
|
+
if (Number.isNaN(seconds))
|
|
4037
|
+
return 0;
|
|
4038
|
+
const fraction = secondsParts[1] ? parseFloat(`0.${secondsParts[1]}`) * 1000 : 0;
|
|
3162
4039
|
return hours * 3600000 + minutes * 60000 + seconds * 1000 + Math.round(fraction);
|
|
3163
4040
|
}
|
|
3164
4041
|
/**
|
|
@@ -3168,7 +4045,7 @@ function parseTimestamp(dateStr) {
|
|
|
3168
4045
|
if (!dateStr)
|
|
3169
4046
|
return Date.now();
|
|
3170
4047
|
const date = new Date(dateStr);
|
|
3171
|
-
return isNaN(date.getTime()) ? Date.now() : date.getTime();
|
|
4048
|
+
return Number.isNaN(date.getTime()) ? Date.now() : date.getTime();
|
|
3172
4049
|
}
|
|
3173
4050
|
/**
|
|
3174
4051
|
* Map TRX outcome to CTRF status
|
|
@@ -3196,9 +4073,9 @@ function extractLineNumber(stackTrace) {
|
|
|
3196
4073
|
if (!stackTrace)
|
|
3197
4074
|
return undefined;
|
|
3198
4075
|
// Match patterns like ":line 79" or ".cs:79"
|
|
3199
|
-
const match =
|
|
4076
|
+
const match = new RegExp(/:line (\d+)|\.cs:(\d+)/i).exec(stackTrace);
|
|
3200
4077
|
if (match) {
|
|
3201
|
-
return parseInt(match[1] || match[2], 10);
|
|
4078
|
+
return Number.parseInt(match[1] || match[2], 10);
|
|
3202
4079
|
}
|
|
3203
4080
|
return undefined;
|
|
3204
4081
|
}
|
|
@@ -3208,8 +4085,8 @@ function extractLineNumber(stackTrace) {
|
|
|
3208
4085
|
function extractFilePath(stackTrace) {
|
|
3209
4086
|
if (!stackTrace)
|
|
3210
4087
|
return undefined;
|
|
3211
|
-
// Match file paths ending in .cs
|
|
3212
|
-
const match =
|
|
4088
|
+
// Match file paths ending in .cs with bounded length to prevent ReDoS
|
|
4089
|
+
const match = new RegExp(/([A-Za-z]:\\[^\s:]{1,256}\.cs|\/[^\s:]{1,256}\.cs)/).exec(stackTrace);
|
|
3213
4090
|
return match ? match[1] : undefined;
|
|
3214
4091
|
}
|
|
3215
4092
|
/**
|
|
@@ -3243,6 +4120,7 @@ async function parseTrxFile(trxPath) {
|
|
|
3243
4120
|
// Parse test results
|
|
3244
4121
|
const results = testRun.Results?.UnitTestResult || [];
|
|
3245
4122
|
const tests = [];
|
|
4123
|
+
const sourceSnippetResolver = (0, source_snippets_1.createDotnetSourceSnippetResolver)();
|
|
3246
4124
|
let passed = 0;
|
|
3247
4125
|
let failed = 0;
|
|
3248
4126
|
let skipped = 0;
|
|
@@ -3280,6 +4158,15 @@ async function parseTrxFile(trxPath) {
|
|
|
3280
4158
|
const stackTrace = result.Output?.ErrorInfo?.StackTrace;
|
|
3281
4159
|
const stdout = result.Output?.StdOut;
|
|
3282
4160
|
const stderr = result.Output?.StdErr;
|
|
4161
|
+
const stackTraceFilePath = extractFilePath(stackTrace);
|
|
4162
|
+
const storagePath = testDef?.['@_storage'];
|
|
4163
|
+
const line = extractLineNumber(stackTrace);
|
|
4164
|
+
const sourceSnippet = await sourceSnippetResolver.resolve({
|
|
4165
|
+
filePath: stackTraceFilePath || storagePath,
|
|
4166
|
+
className,
|
|
4167
|
+
methodName: testDef?.TestMethod?.['@_name'],
|
|
4168
|
+
lineNumber: line,
|
|
4169
|
+
});
|
|
3283
4170
|
const test = {
|
|
3284
4171
|
name: result['@_testName'],
|
|
3285
4172
|
status,
|
|
@@ -3296,8 +4183,9 @@ async function parseTrxFile(trxPath) {
|
|
|
3296
4183
|
stderr: stderr ? [stderr] : [],
|
|
3297
4184
|
message: errorMessage,
|
|
3298
4185
|
trace: stackTrace,
|
|
3299
|
-
line:
|
|
3300
|
-
filePath:
|
|
4186
|
+
line: line ?? sourceSnippet?.line,
|
|
4187
|
+
filePath: sourceSnippet?.filePath ?? stackTraceFilePath ?? storagePath,
|
|
4188
|
+
snippet: sourceSnippet?.snippet,
|
|
3301
4189
|
};
|
|
3302
4190
|
tests.push(test);
|
|
3303
4191
|
}
|
|
@@ -3401,7 +4289,7 @@ async function parseTrxFiles(trxPaths) {
|
|
|
3401
4289
|
|
|
3402
4290
|
/***/ }),
|
|
3403
4291
|
|
|
3404
|
-
/***/
|
|
4292
|
+
/***/ 8010:
|
|
3405
4293
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
3406
4294
|
|
|
3407
4295
|
"use strict";
|
|
@@ -3409,7 +4297,7 @@ async function parseTrxFiles(trxPaths) {
|
|
|
3409
4297
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3410
4298
|
exports.detectGitContext = void 0;
|
|
3411
4299
|
exports.uploadToApi = uploadToApi;
|
|
3412
|
-
const shared_types_1 = __nccwpck_require__(
|
|
4300
|
+
const shared_types_1 = __nccwpck_require__(7322);
|
|
3413
4301
|
/**
|
|
3414
4302
|
* Upload CTRF report to Testream API
|
|
3415
4303
|
*/
|
|
@@ -3436,7 +4324,7 @@ exports.detectGitContext = shared_types_1.detectCIContext;
|
|
|
3436
4324
|
|
|
3437
4325
|
/***/ }),
|
|
3438
4326
|
|
|
3439
|
-
/***/
|
|
4327
|
+
/***/ 5317:
|
|
3440
4328
|
/***/ ((module) => {
|
|
3441
4329
|
|
|
3442
4330
|
"use strict";
|
|
@@ -3444,7 +4332,7 @@ module.exports = require("child_process");
|
|
|
3444
4332
|
|
|
3445
4333
|
/***/ }),
|
|
3446
4334
|
|
|
3447
|
-
/***/
|
|
4335
|
+
/***/ 9896:
|
|
3448
4336
|
/***/ ((module) => {
|
|
3449
4337
|
|
|
3450
4338
|
"use strict";
|
|
@@ -3452,7 +4340,7 @@ module.exports = require("fs");
|
|
|
3452
4340
|
|
|
3453
4341
|
/***/ }),
|
|
3454
4342
|
|
|
3455
|
-
/***/
|
|
4343
|
+
/***/ 1943:
|
|
3456
4344
|
/***/ ((module) => {
|
|
3457
4345
|
|
|
3458
4346
|
"use strict";
|
|
@@ -3460,7 +4348,15 @@ module.exports = require("fs/promises");
|
|
|
3460
4348
|
|
|
3461
4349
|
/***/ }),
|
|
3462
4350
|
|
|
3463
|
-
/***/
|
|
4351
|
+
/***/ 7598:
|
|
4352
|
+
/***/ ((module) => {
|
|
4353
|
+
|
|
4354
|
+
"use strict";
|
|
4355
|
+
module.exports = require("node:crypto");
|
|
4356
|
+
|
|
4357
|
+
/***/ }),
|
|
4358
|
+
|
|
4359
|
+
/***/ 8474:
|
|
3464
4360
|
/***/ ((module) => {
|
|
3465
4361
|
|
|
3466
4362
|
"use strict";
|
|
@@ -3468,7 +4364,7 @@ module.exports = require("node:events");
|
|
|
3468
4364
|
|
|
3469
4365
|
/***/ }),
|
|
3470
4366
|
|
|
3471
|
-
/***/
|
|
4367
|
+
/***/ 3024:
|
|
3472
4368
|
/***/ ((module) => {
|
|
3473
4369
|
|
|
3474
4370
|
"use strict";
|
|
@@ -3476,7 +4372,7 @@ module.exports = require("node:fs");
|
|
|
3476
4372
|
|
|
3477
4373
|
/***/ }),
|
|
3478
4374
|
|
|
3479
|
-
/***/
|
|
4375
|
+
/***/ 1455:
|
|
3480
4376
|
/***/ ((module) => {
|
|
3481
4377
|
|
|
3482
4378
|
"use strict";
|
|
@@ -3484,7 +4380,7 @@ module.exports = require("node:fs/promises");
|
|
|
3484
4380
|
|
|
3485
4381
|
/***/ }),
|
|
3486
4382
|
|
|
3487
|
-
/***/
|
|
4383
|
+
/***/ 6760:
|
|
3488
4384
|
/***/ ((module) => {
|
|
3489
4385
|
|
|
3490
4386
|
"use strict";
|
|
@@ -3492,7 +4388,7 @@ module.exports = require("node:path");
|
|
|
3492
4388
|
|
|
3493
4389
|
/***/ }),
|
|
3494
4390
|
|
|
3495
|
-
/***/
|
|
4391
|
+
/***/ 7075:
|
|
3496
4392
|
/***/ ((module) => {
|
|
3497
4393
|
|
|
3498
4394
|
"use strict";
|
|
@@ -3500,7 +4396,7 @@ module.exports = require("node:stream");
|
|
|
3500
4396
|
|
|
3501
4397
|
/***/ }),
|
|
3502
4398
|
|
|
3503
|
-
/***/
|
|
4399
|
+
/***/ 6193:
|
|
3504
4400
|
/***/ ((module) => {
|
|
3505
4401
|
|
|
3506
4402
|
"use strict";
|
|
@@ -3508,7 +4404,7 @@ module.exports = require("node:string_decoder");
|
|
|
3508
4404
|
|
|
3509
4405
|
/***/ }),
|
|
3510
4406
|
|
|
3511
|
-
/***/
|
|
4407
|
+
/***/ 3136:
|
|
3512
4408
|
/***/ ((module) => {
|
|
3513
4409
|
|
|
3514
4410
|
"use strict";
|
|
@@ -3524,7 +4420,7 @@ module.exports = require("os");
|
|
|
3524
4420
|
|
|
3525
4421
|
/***/ }),
|
|
3526
4422
|
|
|
3527
|
-
/***/
|
|
4423
|
+
/***/ 6928:
|
|
3528
4424
|
/***/ ((module) => {
|
|
3529
4425
|
|
|
3530
4426
|
"use strict";
|
|
@@ -3532,7 +4428,7 @@ module.exports = require("path");
|
|
|
3532
4428
|
|
|
3533
4429
|
/***/ }),
|
|
3534
4430
|
|
|
3535
|
-
/***/
|
|
4431
|
+
/***/ 7080:
|
|
3536
4432
|
/***/ ((__unused_webpack_module, exports) => {
|
|
3537
4433
|
|
|
3538
4434
|
"use strict";
|
|
@@ -3598,14 +4494,14 @@ exports.range = range;
|
|
|
3598
4494
|
|
|
3599
4495
|
/***/ }),
|
|
3600
4496
|
|
|
3601
|
-
/***/
|
|
4497
|
+
/***/ 2339:
|
|
3602
4498
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
3603
4499
|
|
|
3604
4500
|
"use strict";
|
|
3605
4501
|
|
|
3606
4502
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3607
4503
|
exports.expand = expand;
|
|
3608
|
-
const balanced_match_1 = __nccwpck_require__(
|
|
4504
|
+
const balanced_match_1 = __nccwpck_require__(7080);
|
|
3609
4505
|
const escSlash = '\0SLASH' + Math.random() + '\0';
|
|
3610
4506
|
const escOpen = '\0OPEN' + Math.random() + '\0';
|
|
3611
4507
|
const escClose = '\0CLOSE' + Math.random() + '\0';
|
|
@@ -3801,18 +4697,18 @@ function expand_(str, isTop) {
|
|
|
3801
4697
|
|
|
3802
4698
|
/***/ }),
|
|
3803
4699
|
|
|
3804
|
-
/***/
|
|
4700
|
+
/***/ 8809:
|
|
3805
4701
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
3806
4702
|
|
|
3807
4703
|
"use strict";
|
|
3808
4704
|
|
|
3809
4705
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3810
4706
|
exports.Glob = void 0;
|
|
3811
|
-
const minimatch_1 = __nccwpck_require__(
|
|
3812
|
-
const node_url_1 = __nccwpck_require__(
|
|
3813
|
-
const path_scurry_1 = __nccwpck_require__(
|
|
3814
|
-
const pattern_js_1 = __nccwpck_require__(
|
|
3815
|
-
const walker_js_1 = __nccwpck_require__(
|
|
4707
|
+
const minimatch_1 = __nccwpck_require__(6647);
|
|
4708
|
+
const node_url_1 = __nccwpck_require__(3136);
|
|
4709
|
+
const path_scurry_1 = __nccwpck_require__(5125);
|
|
4710
|
+
const pattern_js_1 = __nccwpck_require__(2841);
|
|
4711
|
+
const walker_js_1 = __nccwpck_require__(6089);
|
|
3816
4712
|
// if no process global, just call it linux.
|
|
3817
4713
|
// so we default to case-sensitive, / separators
|
|
3818
4714
|
const defaultPlatform = (typeof process === 'object' &&
|
|
@@ -4055,14 +4951,14 @@ exports.Glob = Glob;
|
|
|
4055
4951
|
|
|
4056
4952
|
/***/ }),
|
|
4057
4953
|
|
|
4058
|
-
/***/
|
|
4954
|
+
/***/ 6233:
|
|
4059
4955
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
4060
4956
|
|
|
4061
4957
|
"use strict";
|
|
4062
4958
|
|
|
4063
4959
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4064
4960
|
exports.hasMagic = void 0;
|
|
4065
|
-
const minimatch_1 = __nccwpck_require__(
|
|
4961
|
+
const minimatch_1 = __nccwpck_require__(6647);
|
|
4066
4962
|
/**
|
|
4067
4963
|
* Return true if the patterns provided contain any magic glob characters,
|
|
4068
4964
|
* given the options provided.
|
|
@@ -4089,7 +4985,7 @@ exports.hasMagic = hasMagic;
|
|
|
4089
4985
|
|
|
4090
4986
|
/***/ }),
|
|
4091
4987
|
|
|
4092
|
-
/***/
|
|
4988
|
+
/***/ 6449:
|
|
4093
4989
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
4094
4990
|
|
|
4095
4991
|
"use strict";
|
|
@@ -4100,8 +4996,8 @@ exports.hasMagic = hasMagic;
|
|
|
4100
4996
|
// Ignores are always parsed in dot:true mode
|
|
4101
4997
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4102
4998
|
exports.Ignore = void 0;
|
|
4103
|
-
const minimatch_1 = __nccwpck_require__(
|
|
4104
|
-
const pattern_js_1 = __nccwpck_require__(
|
|
4999
|
+
const minimatch_1 = __nccwpck_require__(6647);
|
|
5000
|
+
const pattern_js_1 = __nccwpck_require__(2841);
|
|
4105
5001
|
const defaultPlatform = (typeof process === 'object' &&
|
|
4106
5002
|
process &&
|
|
4107
5003
|
typeof process.platform === 'string') ?
|
|
@@ -4227,17 +5123,17 @@ exports.globStream = globStream;
|
|
|
4227
5123
|
exports.globSync = globSync;
|
|
4228
5124
|
exports.globIterateSync = globIterateSync;
|
|
4229
5125
|
exports.globIterate = globIterate;
|
|
4230
|
-
const minimatch_1 = __nccwpck_require__(
|
|
4231
|
-
const glob_js_1 = __nccwpck_require__(
|
|
4232
|
-
const has_magic_js_1 = __nccwpck_require__(
|
|
4233
|
-
var minimatch_2 = __nccwpck_require__(
|
|
5126
|
+
const minimatch_1 = __nccwpck_require__(6647);
|
|
5127
|
+
const glob_js_1 = __nccwpck_require__(8809);
|
|
5128
|
+
const has_magic_js_1 = __nccwpck_require__(6233);
|
|
5129
|
+
var minimatch_2 = __nccwpck_require__(6647);
|
|
4234
5130
|
Object.defineProperty(exports, "escape", ({ enumerable: true, get: function () { return minimatch_2.escape; } }));
|
|
4235
5131
|
Object.defineProperty(exports, "unescape", ({ enumerable: true, get: function () { return minimatch_2.unescape; } }));
|
|
4236
|
-
var glob_js_2 = __nccwpck_require__(
|
|
5132
|
+
var glob_js_2 = __nccwpck_require__(8809);
|
|
4237
5133
|
Object.defineProperty(exports, "Glob", ({ enumerable: true, get: function () { return glob_js_2.Glob; } }));
|
|
4238
|
-
var has_magic_js_2 = __nccwpck_require__(
|
|
5134
|
+
var has_magic_js_2 = __nccwpck_require__(6233);
|
|
4239
5135
|
Object.defineProperty(exports, "hasMagic", ({ enumerable: true, get: function () { return has_magic_js_2.hasMagic; } }));
|
|
4240
|
-
var ignore_js_1 = __nccwpck_require__(
|
|
5136
|
+
var ignore_js_1 = __nccwpck_require__(6449);
|
|
4241
5137
|
Object.defineProperty(exports, "Ignore", ({ enumerable: true, get: function () { return ignore_js_1.Ignore; } }));
|
|
4242
5138
|
function globStreamSync(pattern, options = {}) {
|
|
4243
5139
|
return new glob_js_1.Glob(pattern, options).streamSync();
|
|
@@ -4290,7 +5186,7 @@ exports.glob.glob = exports.glob;
|
|
|
4290
5186
|
|
|
4291
5187
|
/***/ }),
|
|
4292
5188
|
|
|
4293
|
-
/***/
|
|
5189
|
+
/***/ 2841:
|
|
4294
5190
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
4295
5191
|
|
|
4296
5192
|
"use strict";
|
|
@@ -4298,7 +5194,7 @@ exports.glob.glob = exports.glob;
|
|
|
4298
5194
|
// this is just a very light wrapper around 2 arrays with an offset index
|
|
4299
5195
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4300
5196
|
exports.Pattern = void 0;
|
|
4301
|
-
const minimatch_1 = __nccwpck_require__(
|
|
5197
|
+
const minimatch_1 = __nccwpck_require__(6647);
|
|
4302
5198
|
const isPatternList = (pl) => pl.length >= 1;
|
|
4303
5199
|
const isGlobList = (gl) => gl.length >= 1;
|
|
4304
5200
|
/**
|
|
@@ -4516,7 +5412,7 @@ exports.Pattern = Pattern;
|
|
|
4516
5412
|
|
|
4517
5413
|
/***/ }),
|
|
4518
5414
|
|
|
4519
|
-
/***/
|
|
5415
|
+
/***/ 7999:
|
|
4520
5416
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
4521
5417
|
|
|
4522
5418
|
"use strict";
|
|
@@ -4524,7 +5420,7 @@ exports.Pattern = Pattern;
|
|
|
4524
5420
|
// synchronous utility for filtering entries and calculating subwalks
|
|
4525
5421
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4526
5422
|
exports.Processor = exports.SubWalks = exports.MatchRecord = exports.HasWalkedCache = void 0;
|
|
4527
|
-
const minimatch_1 = __nccwpck_require__(
|
|
5423
|
+
const minimatch_1 = __nccwpck_require__(6647);
|
|
4528
5424
|
/**
|
|
4529
5425
|
* A cache of which patterns have been processed for a given Path
|
|
4530
5426
|
*/
|
|
@@ -4824,7 +5720,7 @@ exports.Processor = Processor;
|
|
|
4824
5720
|
|
|
4825
5721
|
/***/ }),
|
|
4826
5722
|
|
|
4827
|
-
/***/
|
|
5723
|
+
/***/ 6089:
|
|
4828
5724
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
4829
5725
|
|
|
4830
5726
|
"use strict";
|
|
@@ -4837,9 +5733,9 @@ exports.GlobStream = exports.GlobWalker = exports.GlobUtil = void 0;
|
|
|
4837
5733
|
*
|
|
4838
5734
|
* @module
|
|
4839
5735
|
*/
|
|
4840
|
-
const minipass_1 = __nccwpck_require__(
|
|
4841
|
-
const ignore_js_1 = __nccwpck_require__(
|
|
4842
|
-
const processor_js_1 = __nccwpck_require__(
|
|
5736
|
+
const minipass_1 = __nccwpck_require__(1031);
|
|
5737
|
+
const ignore_js_1 = __nccwpck_require__(6449);
|
|
5738
|
+
const processor_js_1 = __nccwpck_require__(7999);
|
|
4843
5739
|
const makeIgnore = (ignore, opts) => typeof ignore === 'string' ? new ignore_js_1.Ignore([ignore], opts)
|
|
4844
5740
|
: Array.isArray(ignore) ? new ignore_js_1.Ignore(ignore, opts)
|
|
4845
5741
|
: ignore;
|
|
@@ -5218,7 +6114,7 @@ exports.GlobStream = GlobStream;
|
|
|
5218
6114
|
|
|
5219
6115
|
/***/ }),
|
|
5220
6116
|
|
|
5221
|
-
/***/
|
|
6117
|
+
/***/ 3481:
|
|
5222
6118
|
/***/ ((__unused_webpack_module, exports) => {
|
|
5223
6119
|
|
|
5224
6120
|
"use strict";
|
|
@@ -6831,7 +7727,7 @@ exports.assertValidPattern = assertValidPattern;
|
|
|
6831
7727
|
|
|
6832
7728
|
/***/ }),
|
|
6833
7729
|
|
|
6834
|
-
/***/
|
|
7730
|
+
/***/ 8743:
|
|
6835
7731
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6836
7732
|
|
|
6837
7733
|
"use strict";
|
|
@@ -6839,8 +7735,8 @@ exports.assertValidPattern = assertValidPattern;
|
|
|
6839
7735
|
// parse a single path portion
|
|
6840
7736
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6841
7737
|
exports.AST = void 0;
|
|
6842
|
-
const brace_expressions_js_1 = __nccwpck_require__(
|
|
6843
|
-
const unescape_js_1 = __nccwpck_require__(
|
|
7738
|
+
const brace_expressions_js_1 = __nccwpck_require__(6694);
|
|
7739
|
+
const unescape_js_1 = __nccwpck_require__(7967);
|
|
6844
7740
|
const types = new Set(['!', '?', '+', '*', '@']);
|
|
6845
7741
|
const isExtglobType = (c) => types.has(c);
|
|
6846
7742
|
// Patterns that get prepended to bind to the start of either the
|
|
@@ -7429,7 +8325,7 @@ exports.AST = AST;
|
|
|
7429
8325
|
|
|
7430
8326
|
/***/ }),
|
|
7431
8327
|
|
|
7432
|
-
/***/
|
|
8328
|
+
/***/ 6694:
|
|
7433
8329
|
/***/ ((__unused_webpack_module, exports) => {
|
|
7434
8330
|
|
|
7435
8331
|
"use strict";
|
|
@@ -7588,7 +8484,7 @@ exports.parseClass = parseClass;
|
|
|
7588
8484
|
|
|
7589
8485
|
/***/ }),
|
|
7590
8486
|
|
|
7591
|
-
/***/
|
|
8487
|
+
/***/ 7516:
|
|
7592
8488
|
/***/ ((__unused_webpack_module, exports) => {
|
|
7593
8489
|
|
|
7594
8490
|
"use strict";
|
|
@@ -7625,18 +8521,18 @@ exports.escape = escape;
|
|
|
7625
8521
|
|
|
7626
8522
|
/***/ }),
|
|
7627
8523
|
|
|
7628
|
-
/***/
|
|
8524
|
+
/***/ 6647:
|
|
7629
8525
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
7630
8526
|
|
|
7631
8527
|
"use strict";
|
|
7632
8528
|
|
|
7633
8529
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
7634
8530
|
exports.unescape = exports.escape = exports.AST = exports.Minimatch = exports.match = exports.makeRe = exports.braceExpand = exports.defaults = exports.filter = exports.GLOBSTAR = exports.sep = exports.minimatch = void 0;
|
|
7635
|
-
const brace_expansion_1 = __nccwpck_require__(
|
|
8531
|
+
const brace_expansion_1 = __nccwpck_require__(2339);
|
|
7636
8532
|
const assert_valid_pattern_js_1 = __nccwpck_require__(557);
|
|
7637
|
-
const ast_js_1 = __nccwpck_require__(
|
|
7638
|
-
const escape_js_1 = __nccwpck_require__(
|
|
7639
|
-
const unescape_js_1 = __nccwpck_require__(
|
|
8533
|
+
const ast_js_1 = __nccwpck_require__(8743);
|
|
8534
|
+
const escape_js_1 = __nccwpck_require__(7516);
|
|
8535
|
+
const unescape_js_1 = __nccwpck_require__(7967);
|
|
7640
8536
|
const minimatch = (p, pattern, options = {}) => {
|
|
7641
8537
|
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
7642
8538
|
// shortcut: comments match nothing.
|
|
@@ -8646,11 +9542,11 @@ class Minimatch {
|
|
|
8646
9542
|
}
|
|
8647
9543
|
exports.Minimatch = Minimatch;
|
|
8648
9544
|
/* c8 ignore start */
|
|
8649
|
-
var ast_js_2 = __nccwpck_require__(
|
|
9545
|
+
var ast_js_2 = __nccwpck_require__(8743);
|
|
8650
9546
|
Object.defineProperty(exports, "AST", ({ enumerable: true, get: function () { return ast_js_2.AST; } }));
|
|
8651
|
-
var escape_js_2 = __nccwpck_require__(
|
|
9547
|
+
var escape_js_2 = __nccwpck_require__(7516);
|
|
8652
9548
|
Object.defineProperty(exports, "escape", ({ enumerable: true, get: function () { return escape_js_2.escape; } }));
|
|
8653
|
-
var unescape_js_2 = __nccwpck_require__(
|
|
9549
|
+
var unescape_js_2 = __nccwpck_require__(7967);
|
|
8654
9550
|
Object.defineProperty(exports, "unescape", ({ enumerable: true, get: function () { return unescape_js_2.unescape; } }));
|
|
8655
9551
|
/* c8 ignore stop */
|
|
8656
9552
|
exports.minimatch.AST = ast_js_1.AST;
|
|
@@ -8661,7 +9557,7 @@ exports.minimatch.unescape = unescape_js_1.unescape;
|
|
|
8661
9557
|
|
|
8662
9558
|
/***/ }),
|
|
8663
9559
|
|
|
8664
|
-
/***/
|
|
9560
|
+
/***/ 7967:
|
|
8665
9561
|
/***/ ((__unused_webpack_module, exports) => {
|
|
8666
9562
|
|
|
8667
9563
|
"use strict";
|
|
@@ -8706,7 +9602,7 @@ exports.unescape = unescape;
|
|
|
8706
9602
|
|
|
8707
9603
|
/***/ }),
|
|
8708
9604
|
|
|
8709
|
-
/***/
|
|
9605
|
+
/***/ 1031:
|
|
8710
9606
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
8711
9607
|
|
|
8712
9608
|
"use strict";
|
|
@@ -8722,9 +9618,9 @@ const proc = typeof process === 'object' && process
|
|
|
8722
9618
|
stdout: null,
|
|
8723
9619
|
stderr: null,
|
|
8724
9620
|
};
|
|
8725
|
-
const node_events_1 = __nccwpck_require__(
|
|
8726
|
-
const node_stream_1 = __importDefault(__nccwpck_require__(
|
|
8727
|
-
const node_string_decoder_1 = __nccwpck_require__(
|
|
9621
|
+
const node_events_1 = __nccwpck_require__(8474);
|
|
9622
|
+
const node_stream_1 = __importDefault(__nccwpck_require__(7075));
|
|
9623
|
+
const node_string_decoder_1 = __nccwpck_require__(6193);
|
|
8728
9624
|
/**
|
|
8729
9625
|
* Return true if the argument is a Minipass stream, Node stream, or something
|
|
8730
9626
|
* else that Minipass can interact with.
|
|
@@ -9741,7 +10637,7 @@ exports.Minipass = Minipass;
|
|
|
9741
10637
|
|
|
9742
10638
|
/***/ }),
|
|
9743
10639
|
|
|
9744
|
-
/***/
|
|
10640
|
+
/***/ 5125:
|
|
9745
10641
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
9746
10642
|
|
|
9747
10643
|
"use strict";
|
|
@@ -9771,16 +10667,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
9771
10667
|
};
|
|
9772
10668
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9773
10669
|
exports.PathScurry = exports.Path = exports.PathScurryDarwin = exports.PathScurryPosix = exports.PathScurryWin32 = exports.PathScurryBase = exports.PathPosix = exports.PathWin32 = exports.PathBase = exports.ChildrenCache = exports.ResolveCache = void 0;
|
|
9774
|
-
const lru_cache_1 = __nccwpck_require__(
|
|
9775
|
-
const node_path_1 = __nccwpck_require__(
|
|
9776
|
-
const node_url_1 = __nccwpck_require__(
|
|
9777
|
-
const fs_1 = __nccwpck_require__(
|
|
9778
|
-
const actualFS = __importStar(__nccwpck_require__(
|
|
10670
|
+
const lru_cache_1 = __nccwpck_require__(3481);
|
|
10671
|
+
const node_path_1 = __nccwpck_require__(6760);
|
|
10672
|
+
const node_url_1 = __nccwpck_require__(3136);
|
|
10673
|
+
const fs_1 = __nccwpck_require__(9896);
|
|
10674
|
+
const actualFS = __importStar(__nccwpck_require__(3024));
|
|
9779
10675
|
const realpathSync = fs_1.realpathSync.native;
|
|
9780
10676
|
// TODO: test perf of fs/promises realpath vs realpathCB,
|
|
9781
10677
|
// since the promises one uses realpath.native
|
|
9782
|
-
const promises_1 = __nccwpck_require__(
|
|
9783
|
-
const minipass_1 = __nccwpck_require__(
|
|
10678
|
+
const promises_1 = __nccwpck_require__(1455);
|
|
10679
|
+
const minipass_1 = __nccwpck_require__(1031);
|
|
9784
10680
|
const defaultFS = {
|
|
9785
10681
|
lstatSync: fs_1.lstatSync,
|
|
9786
10682
|
readdir: fs_1.readdir,
|
|
@@ -11866,7 +12762,7 @@ exports.PathScurry = process.platform === 'win32' ? PathScurryWin32
|
|
|
11866
12762
|
/******/ // startup
|
|
11867
12763
|
/******/ // Load entry module and return exports
|
|
11868
12764
|
/******/ // This entry module is referenced by other modules so it can't be inlined
|
|
11869
|
-
/******/ var __webpack_exports__ = __nccwpck_require__(
|
|
12765
|
+
/******/ var __webpack_exports__ = __nccwpck_require__(4328);
|
|
11870
12766
|
/******/ module.exports = __webpack_exports__;
|
|
11871
12767
|
/******/
|
|
11872
12768
|
/******/ })()
|