ado-sync 0.1.24 → 0.1.27

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.
Files changed (46) hide show
  1. package/README.md +240 -678
  2. package/dist/azure/client.d.ts +3 -0
  3. package/dist/azure/client.js +6 -0
  4. package/dist/azure/client.js.map +1 -1
  5. package/dist/azure/test-cases.d.ts +8 -3
  6. package/dist/azure/test-cases.js +406 -25
  7. package/dist/azure/test-cases.js.map +1 -1
  8. package/dist/cli.js +51 -4
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config.js +111 -5
  11. package/dist/config.js.map +1 -1
  12. package/dist/parsers/csharp.d.ts +30 -0
  13. package/dist/parsers/csharp.js +257 -0
  14. package/dist/parsers/csharp.js.map +1 -0
  15. package/dist/parsers/gherkin.d.ts +4 -1
  16. package/dist/parsers/gherkin.js +19 -4
  17. package/dist/parsers/gherkin.js.map +1 -1
  18. package/dist/parsers/java.d.ts +40 -0
  19. package/dist/parsers/java.js +329 -0
  20. package/dist/parsers/java.js.map +1 -0
  21. package/dist/parsers/javascript.d.ts +33 -0
  22. package/dist/parsers/javascript.js +261 -0
  23. package/dist/parsers/javascript.js.map +1 -0
  24. package/dist/parsers/markdown.d.ts +4 -1
  25. package/dist/parsers/markdown.js +5 -3
  26. package/dist/parsers/markdown.js.map +1 -1
  27. package/dist/parsers/python.d.ts +34 -0
  28. package/dist/parsers/python.js +305 -0
  29. package/dist/parsers/python.js.map +1 -0
  30. package/dist/parsers/shared.d.ts +18 -0
  31. package/dist/parsers/shared.js +40 -0
  32. package/dist/parsers/shared.js.map +1 -1
  33. package/dist/sync/engine.js +114 -5
  34. package/dist/sync/engine.js.map +1 -1
  35. package/dist/sync/publish-results.d.ts +49 -0
  36. package/dist/sync/publish-results.js +476 -0
  37. package/dist/sync/publish-results.js.map +1 -0
  38. package/dist/sync/writeback.d.ts +57 -1
  39. package/dist/sync/writeback.js +243 -0
  40. package/dist/sync/writeback.js.map +1 -1
  41. package/dist/types.d.ts +159 -2
  42. package/docs/advanced.md +350 -0
  43. package/docs/configuration.md +293 -0
  44. package/docs/publish-test-results.md +317 -0
  45. package/docs/spec-formats.md +595 -0
  46. package/package.json +1 -1
@@ -0,0 +1,476 @@
1
+ "use strict";
2
+ /**
3
+ * Publish test results to Azure DevOps test runs.
4
+ *
5
+ * Parses TRX, JUnit, NUnit XML, and Cucumber JSON result files then creates a
6
+ * test run with results mapped back to Azure DevOps test cases.
7
+ *
8
+ * TC ID extraction strategy (in priority order):
9
+ *
10
+ * 1. Direct TC ID from result file:
11
+ * - TRX (MSTest): [TestProperty("tc","12345")] → TestDefinitions/UnitTest/Properties/Property
12
+ * - NUnit XML: [Property("tc","12345")] → test-case/properties/property[@name="tc"]
13
+ * - JUnit XML: <property name="tc" value="12345"/> inside <testcase><properties>
14
+ * (pytest: add record_property hook in conftest.py; jest: custom reporter)
15
+ * - Cucumber JSON: @tc:12345 tag on scenario
16
+ *
17
+ * 2. AutomatedTestName matching (fallback):
18
+ * When no TC ID is found, the result is published with automatedTestName set to the
19
+ * FQMN (testName). Azure DevOps links it to a TC via AutomatedTestName if markAutomated
20
+ * was used on push.
21
+ *
22
+ * NUnit TRX (via NUnit3TestAdapter) does NOT include [Property] values in the TRX format.
23
+ * Use `--logger "nunit3;LogFileName=results.xml"` to get the native NUnit XML with properties.
24
+ */
25
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ var desc = Object.getOwnPropertyDescriptor(m, k);
28
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
29
+ desc = { enumerable: true, get: function() { return m[k]; } };
30
+ }
31
+ Object.defineProperty(o, k2, desc);
32
+ }) : (function(o, m, k, k2) {
33
+ if (k2 === undefined) k2 = k;
34
+ o[k2] = m[k];
35
+ }));
36
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
37
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
38
+ }) : function(o, v) {
39
+ o["default"] = v;
40
+ });
41
+ var __importStar = (this && this.__importStar) || (function () {
42
+ var ownKeys = function(o) {
43
+ ownKeys = Object.getOwnPropertyNames || function (o) {
44
+ var ar = [];
45
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
46
+ return ar;
47
+ };
48
+ return ownKeys(o);
49
+ };
50
+ return function (mod) {
51
+ if (mod && mod.__esModule) return mod;
52
+ var result = {};
53
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
54
+ __setModuleDefault(result, mod);
55
+ return result;
56
+ };
57
+ })();
58
+ Object.defineProperty(exports, "__esModule", { value: true });
59
+ exports.publishTestResults = publishTestResults;
60
+ const fast_xml_parser_1 = require("fast-xml-parser");
61
+ const fs = __importStar(require("fs"));
62
+ const path = __importStar(require("path"));
63
+ const client_1 = require("../azure/client");
64
+ /** Normalise outcome strings from various formats to Azure DevOps valid values. */
65
+ function normaliseOutcome(raw, treatInconclusiveAs) {
66
+ const lower = raw.toLowerCase();
67
+ if (lower === 'passed' || lower === 'pass' || lower === 'success')
68
+ return 'Passed';
69
+ if (lower === 'failed' || lower === 'fail' || lower === 'failure' || lower === 'error')
70
+ return 'Failed';
71
+ if (lower === 'skipped' || lower === 'ignored' || lower === 'pending' || lower === 'notexecuted')
72
+ return 'NotExecuted';
73
+ if (lower === 'inconclusive')
74
+ return treatInconclusiveAs ?? 'Inconclusive';
75
+ return raw;
76
+ }
77
+ // ─── TRX parser (MSTest) ──────────────────────────────────────────────────────
78
+ //
79
+ // TRX structure relevant to TC ID extraction:
80
+ //
81
+ // <TestRun>
82
+ // <TestDefinitions>
83
+ // <UnitTest name="..." id="GUID">
84
+ // <Properties>
85
+ // <Property><Key>tc</Key><Value>12345</Value></Property>
86
+ // </Properties>
87
+ // <TestMethod className="Namespace.ClassName" name="MethodName" />
88
+ // </UnitTest>
89
+ // </TestDefinitions>
90
+ // <Results>
91
+ // <UnitTestResult testId="GUID" testName="..." outcome="Passed" .../>
92
+ // </Results>
93
+ // </TestRun>
94
+ //
95
+ // UnitTestResult.testId → UnitTest.id → Properties → tc value
96
+ function parseTrx(content, tagPrefix, treatInconclusiveAs) {
97
+ const parser = new fast_xml_parser_1.XMLParser({
98
+ ignoreAttributes: false,
99
+ attributeNamePrefix: '@_',
100
+ isArray: (name) => ['UnitTest', 'UnitTestResult', 'Property'].includes(name),
101
+ });
102
+ const doc = parser.parse(content);
103
+ const testRun = doc.TestRun ?? doc.testRun;
104
+ if (!testRun)
105
+ return [];
106
+ // Build map: testId (GUID) → Azure TC id, from [TestProperty("tc","...")] values
107
+ const testIdToTcId = new Map();
108
+ const definitions = testRun.TestDefinitions ?? testRun.testDefinitions;
109
+ if (definitions) {
110
+ let unitTests = definitions.UnitTest ?? definitions.unitTest ?? [];
111
+ if (!Array.isArray(unitTests))
112
+ unitTests = [unitTests];
113
+ for (const ut of unitTests) {
114
+ const testId = ut['@_id'] ?? '';
115
+ if (!testId)
116
+ continue;
117
+ const propsNode = ut.Properties ?? ut.properties;
118
+ if (!propsNode)
119
+ continue;
120
+ let props = propsNode.Property ?? propsNode.property ?? [];
121
+ if (!Array.isArray(props))
122
+ props = [props];
123
+ for (const prop of props) {
124
+ const key = String(prop.Key ?? prop.key ?? '');
125
+ const val = String(prop.Value ?? prop.value ?? '');
126
+ if (key === tagPrefix) {
127
+ const id = parseInt(val, 10);
128
+ if (!isNaN(id))
129
+ testIdToTcId.set(testId, id);
130
+ break;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ // Parse UnitTestResult entries
136
+ const resultsNode = testRun.Results ?? testRun.results;
137
+ if (!resultsNode)
138
+ return [];
139
+ let unitResults = resultsNode.UnitTestResult ?? resultsNode.unitTestResult ?? [];
140
+ if (!Array.isArray(unitResults))
141
+ unitResults = [unitResults];
142
+ return unitResults.map((r) => {
143
+ const duration = r['@_duration'] ?? '00:00:00';
144
+ const parts = duration.split(':');
145
+ const durationMs = parts.length === 3
146
+ ? (parseInt(parts[0]) * 3600 + parseInt(parts[1]) * 60 + parseFloat(parts[2])) * 1000
147
+ : 0;
148
+ const output = r.Output ?? r.output;
149
+ const errorInfo = output?.ErrorInfo ?? output?.errorInfo;
150
+ // Look up TC id by testId → TestDefinitions → Properties
151
+ const testId = r['@_testId'] ?? '';
152
+ const testCaseId = testId ? testIdToTcId.get(testId) : undefined;
153
+ return {
154
+ testName: r['@_testName'] ?? '',
155
+ outcome: normaliseOutcome(r['@_outcome'] ?? 'Unspecified', treatInconclusiveAs),
156
+ durationMs: Math.round(durationMs),
157
+ errorMessage: errorInfo?.Message ?? errorInfo?.message,
158
+ stackTrace: errorInfo?.StackTrace ?? errorInfo?.stackTrace,
159
+ testCaseId,
160
+ };
161
+ });
162
+ }
163
+ // ─── NUnit XML parser ─────────────────────────────────────────────────────────
164
+ //
165
+ // NUnit's native XML format (produced by --logger "nunit3;LogFileName=results.xml")
166
+ // includes [Property] values in each <test-case>, unlike the TRX format via NUnit3TestAdapter.
167
+ //
168
+ // <test-run>
169
+ // <test-suite type="TestFixture" fullname="Ns.Fixture">
170
+ // <test-case fullname="Ns.Fixture.MethodName" result="Passed" duration="0.123">
171
+ // <properties>
172
+ // <property name="tc" value="12345" />
173
+ // </properties>
174
+ // </test-case>
175
+ // <test-case fullname="Ns.Fixture.FailTest" result="Failed" duration="0.001">
176
+ // <failure>
177
+ // <message>Expected 1 but was 2</message>
178
+ // <stack-trace>...</stack-trace>
179
+ // </failure>
180
+ // </test-case>
181
+ // </test-suite>
182
+ // </test-run>
183
+ function parseNUnitXml(content, tagPrefix, treatInconclusiveAs) {
184
+ const parser = new fast_xml_parser_1.XMLParser({
185
+ ignoreAttributes: false,
186
+ attributeNamePrefix: '@_',
187
+ isArray: (name) => ['test-suite', 'test-case', 'property'].includes(name),
188
+ });
189
+ const doc = parser.parse(content);
190
+ const results = [];
191
+ function walkNode(node) {
192
+ // Collect test-cases at this level
193
+ const cases = node['test-case'] ?? [];
194
+ for (const tc of cases) {
195
+ const fullName = tc['@_fullname'] ?? tc['@_name'] ?? '';
196
+ const result = tc['@_result'] ?? 'Inconclusive';
197
+ const duration = parseFloat(tc['@_duration'] ?? '0');
198
+ // Extract TC id from <properties>/<property name="tc" value="..."/>
199
+ let testCaseId;
200
+ const props = tc.properties?.property ?? [];
201
+ for (const prop of props) {
202
+ if (String(prop['@_name'] ?? '') === tagPrefix) {
203
+ const id = parseInt(String(prop['@_value'] ?? ''), 10);
204
+ if (!isNaN(id)) {
205
+ testCaseId = id;
206
+ break;
207
+ }
208
+ }
209
+ }
210
+ // Failure / error details
211
+ let errorMessage;
212
+ let stackTrace;
213
+ const failure = tc.failure;
214
+ if (failure) {
215
+ errorMessage = String(failure.message ?? '');
216
+ stackTrace = String(failure['stack-trace'] ?? '');
217
+ }
218
+ results.push({
219
+ testName: fullName,
220
+ outcome: normaliseOutcome(result, treatInconclusiveAs),
221
+ durationMs: Math.round(duration * 1000),
222
+ errorMessage: errorMessage || undefined,
223
+ stackTrace: stackTrace || undefined,
224
+ testCaseId,
225
+ });
226
+ }
227
+ // Recurse into nested test-suites
228
+ const suites = node['test-suite'] ?? [];
229
+ for (const suite of suites)
230
+ walkNode(suite);
231
+ }
232
+ const testRunNode = doc['test-run'];
233
+ if (testRunNode)
234
+ walkNode(testRunNode);
235
+ return results;
236
+ }
237
+ // ─── JUnit parser ─────────────────────────────────────────────────────────────
238
+ //
239
+ // Supports JUnit XML from:
240
+ // - Maven Surefire / Failsafe (Java JUnit 4/5, TestNG)
241
+ // - pytest --junitxml (Python)
242
+ // - jest-junit (Jest / Jasmine / WebdriverIO)
243
+ //
244
+ // TC ID extraction:
245
+ // - From <testcase><properties><property name="tc" value="N"/></properties></testcase>
246
+ // (pytest: add record_property in conftest.py; jest: custom reporter)
247
+ //
248
+ // AutomatedTestName mapping:
249
+ // - Uses testcase[@classname].testcase[@name] when classname is present.
250
+ // This matches the automatedTestName format used by the Java and Python parsers
251
+ // (e.g. "com.example.MyClass.myMethod" or "tests.module.TestClass.test_foo").
252
+ // - Falls back to suite[@name].testcase[@name] when classname is absent.
253
+ function parseJUnit(content, tagPrefix, treatInconclusiveAs) {
254
+ const parser = new fast_xml_parser_1.XMLParser({
255
+ ignoreAttributes: false,
256
+ attributeNamePrefix: '@_',
257
+ isArray: (name) => ['testsuite', 'testcase', 'property'].includes(name),
258
+ });
259
+ const doc = parser.parse(content);
260
+ const results = [];
261
+ const suites = doc.testsuites?.testsuite ?? (doc.testsuite ? [doc.testsuite] : []);
262
+ for (const suite of suites) {
263
+ let cases = suite.testcase ?? [];
264
+ if (!Array.isArray(cases))
265
+ cases = [cases];
266
+ for (const tc of cases) {
267
+ let outcome = 'Passed';
268
+ let errorMessage;
269
+ let stackTrace;
270
+ if (tc.failure) {
271
+ outcome = 'Failed';
272
+ const fail = typeof tc.failure === 'string' ? tc.failure : (tc.failure['#text'] ?? '');
273
+ errorMessage = tc.failure['@_message'] ?? fail;
274
+ stackTrace = typeof tc.failure === 'string' ? tc.failure : tc.failure['#text'];
275
+ }
276
+ else if (tc.error) {
277
+ outcome = 'Failed';
278
+ errorMessage = tc.error['@_message'] ?? '';
279
+ stackTrace = typeof tc.error === 'string' ? tc.error : tc.error['#text'];
280
+ }
281
+ else if (tc.skipped !== undefined) {
282
+ outcome = 'NotExecuted';
283
+ }
284
+ // Build automatedTestName: prefer classname.name (matches Java/Python parsers),
285
+ // fall back to suiteName.name.
286
+ const className = tc['@_classname'] ?? '';
287
+ const testCase = tc['@_name'] ?? '';
288
+ const suiteName = suite['@_name'] ?? '';
289
+ const testName = className
290
+ ? `${className}.${testCase}`
291
+ : `${suiteName}.${testCase}`.replace(/^\./, '');
292
+ // Extract TC ID from <properties><property name="tc" value="N"/></properties>
293
+ // (e.g. added by a pytest conftest.py record_property hook or jest custom reporter)
294
+ let testCaseId;
295
+ const props = tc.properties?.property ?? [];
296
+ for (const prop of props) {
297
+ if (String(prop['@_name'] ?? '') === tagPrefix) {
298
+ const id = parseInt(String(prop['@_value'] ?? ''), 10);
299
+ if (!isNaN(id)) {
300
+ testCaseId = id;
301
+ break;
302
+ }
303
+ }
304
+ }
305
+ results.push({
306
+ testName,
307
+ outcome: normaliseOutcome(outcome, treatInconclusiveAs),
308
+ durationMs: Math.round(parseFloat(tc['@_time'] ?? '0') * 1000),
309
+ errorMessage,
310
+ stackTrace,
311
+ testCaseId,
312
+ });
313
+ }
314
+ }
315
+ return results;
316
+ }
317
+ // ─── Cucumber JSON parser ─────────────────────────────────────────────────────
318
+ function parseCucumberJson(content, tagPrefix, treatInconclusiveAs) {
319
+ const features = JSON.parse(content);
320
+ const results = [];
321
+ for (const feature of features) {
322
+ for (const element of feature.elements ?? []) {
323
+ if (element.type !== 'scenario')
324
+ continue;
325
+ let totalDuration = 0;
326
+ let worstOutcome = 'Passed';
327
+ let errorMsg;
328
+ for (const step of element.steps ?? []) {
329
+ const result = step.result ?? {};
330
+ totalDuration += result.duration ?? 0;
331
+ const status = result.status ?? 'undefined';
332
+ if (status === 'failed' && worstOutcome !== 'Failed') {
333
+ worstOutcome = 'Failed';
334
+ errorMsg = result.error_message;
335
+ }
336
+ else if (status === 'skipped' || status === 'pending' || status === 'undefined') {
337
+ if (worstOutcome === 'Passed')
338
+ worstOutcome = 'NotExecuted';
339
+ }
340
+ }
341
+ // Extract TC id from @tc:NNN tag on the scenario
342
+ let testCaseId;
343
+ const tcPrefix = `@${tagPrefix}:`;
344
+ for (const tag of element.tags ?? []) {
345
+ if (tag.name?.startsWith(tcPrefix)) {
346
+ const id = parseInt(tag.name.slice(tcPrefix.length), 10);
347
+ if (!isNaN(id)) {
348
+ testCaseId = id;
349
+ break;
350
+ }
351
+ }
352
+ }
353
+ results.push({
354
+ testName: `${feature.name}: ${element.name}`,
355
+ outcome: normaliseOutcome(worstOutcome, treatInconclusiveAs),
356
+ durationMs: Math.round(totalDuration / 1e6), // cucumber reports in nanoseconds
357
+ errorMessage: errorMsg,
358
+ testCaseId,
359
+ });
360
+ }
361
+ }
362
+ return results;
363
+ }
364
+ // ─── Auto-detect format ───────────────────────────────────────────────────────
365
+ function detectFormat(filePath, content) {
366
+ const ext = path.extname(filePath).toLowerCase();
367
+ if (ext === '.trx')
368
+ return 'trx';
369
+ if (ext === '.json')
370
+ return 'cucumberJson';
371
+ if (content.trimStart().startsWith('<')) {
372
+ if (content.includes('<TestRun') || content.includes('<testRun'))
373
+ return 'trx';
374
+ if (content.includes('<test-run'))
375
+ return 'nunitXml';
376
+ if (content.includes('<testsuites') || content.includes('<testsuite'))
377
+ return 'junit';
378
+ }
379
+ return 'junit';
380
+ }
381
+ async function publishTestResults(config, configDir, opts = {}) {
382
+ const pubConfig = config.publishTestResults;
383
+ if (!pubConfig && !opts.resultFiles?.length) {
384
+ throw new Error('No publishTestResults configuration and no --testResult files specified.');
385
+ }
386
+ const tagPrefix = config.sync?.tagPrefix ?? 'tc';
387
+ // Gather result files
388
+ const sources = [];
389
+ if (opts.resultFiles?.length) {
390
+ for (const f of opts.resultFiles) {
391
+ sources.push({ filePath: path.resolve(configDir, f), format: opts.resultFormat });
392
+ }
393
+ }
394
+ else if (pubConfig?.testResult?.sources) {
395
+ for (const src of pubConfig.testResult.sources) {
396
+ sources.push({ filePath: path.resolve(configDir, src.value), format: src.format });
397
+ }
398
+ }
399
+ // Parse all result files
400
+ const allResults = [];
401
+ const treatInconclusiveAs = pubConfig?.treatInconclusiveAs;
402
+ for (const src of sources) {
403
+ if (!fs.existsSync(src.filePath)) {
404
+ throw new Error(`Test result file not found: ${src.filePath}`);
405
+ }
406
+ const content = fs.readFileSync(src.filePath, 'utf8');
407
+ const format = src.format ?? detectFormat(src.filePath, content);
408
+ switch (format) {
409
+ case 'trx':
410
+ allResults.push(...parseTrx(content, tagPrefix, treatInconclusiveAs));
411
+ break;
412
+ case 'nunitXml':
413
+ allResults.push(...parseNUnitXml(content, tagPrefix, treatInconclusiveAs));
414
+ break;
415
+ case 'junit':
416
+ allResults.push(...parseJUnit(content, tagPrefix, treatInconclusiveAs));
417
+ break;
418
+ case 'cucumberJson':
419
+ allResults.push(...parseCucumberJson(content, tagPrefix, treatInconclusiveAs));
420
+ break;
421
+ default:
422
+ throw new Error(`Unsupported test result format: ${format}`);
423
+ }
424
+ }
425
+ if (!allResults.length) {
426
+ throw new Error('No test results found in the specified files.');
427
+ }
428
+ const passed = allResults.filter((r) => r.outcome === 'Passed').length;
429
+ const failed = allResults.filter((r) => r.outcome === 'Failed').length;
430
+ const other = allResults.length - passed - failed;
431
+ if (opts.dryRun) {
432
+ return { runId: 0, runUrl: '', totalResults: allResults.length, passed, failed, other };
433
+ }
434
+ const client = await client_1.AzureClient.create(config);
435
+ const testApi = await client.getTestApi();
436
+ const runSettings = pubConfig?.testRunSettings;
437
+ const runName = opts.runName ?? runSettings?.name ?? `ado-sync ${new Date().toISOString()}`;
438
+ const runModel = {
439
+ name: runName,
440
+ plan: { id: String(config.testPlan.id) },
441
+ automated: runSettings?.runType === 'Manual' ? false : true,
442
+ configurationIds: pubConfig?.testConfiguration?.id ? [pubConfig.testConfiguration.id] : [],
443
+ };
444
+ if (runSettings?.comment)
445
+ runModel.comment = runSettings.comment;
446
+ if (opts.buildId)
447
+ runModel.build = { id: String(opts.buildId) };
448
+ const run = await testApi.createTestRun(runModel, config.project);
449
+ const runId = run.id;
450
+ const testCaseResults = allResults.map((r) => {
451
+ const result = {
452
+ automatedTestName: r.testName,
453
+ testCaseTitle: r.testName,
454
+ outcome: r.outcome,
455
+ state: 'Completed',
456
+ durationInMs: r.durationMs,
457
+ };
458
+ if (r.errorMessage)
459
+ result.errorMessage = r.errorMessage;
460
+ if (r.stackTrace)
461
+ result.stackTrace = r.stackTrace;
462
+ // When a TC id was extracted from the result file, link directly by id.
463
+ // This is more reliable than AutomatedTestName matching and works even when
464
+ // the FQMN has changed since the TC was last pushed.
465
+ if (r.testCaseId)
466
+ result.testCase = { id: String(r.testCaseId) };
467
+ if (pubConfig?.testResultSettings?.comment)
468
+ result.comment = pubConfig.testResultSettings.comment;
469
+ return result;
470
+ });
471
+ await testApi.addTestResultsToTestRun(testCaseResults, config.project, runId);
472
+ await testApi.updateTestRun({ state: 'Completed' }, config.project, runId);
473
+ const runUrl = `${config.orgUrl}/${config.project}/_testManagement/runs?runId=${runId}`;
474
+ return { runId, runUrl, totalResults: allResults.length, passed, failed, other };
475
+ }
476
+ //# sourceMappingURL=publish-results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-results.js","sourceRoot":"","sources":["../../src/sync/publish-results.ts"],"names":[],"mappings":"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"}
@@ -33,4 +33,60 @@ export declare function writebackGherkin(test: ParsedTest, id: number, tagPrefix
33
33
  * 4. If not found, insert immediately after the heading line.
34
34
  */
35
35
  export declare function writebackMarkdown(test: ParsedTest, id: number, tagPrefix: string): void;
36
- export declare function writebackId(test: ParsedTest, id: number, localType: 'gherkin' | 'markdown' | 'csv' | 'excel', tagPrefix: string): Promise<void>;
36
+ /**
37
+ * Write (or update) [TestProperty("tc", "ID")] in a .cs file for a given [TestMethod].
38
+ *
39
+ * Strategy:
40
+ * 1. Locate [TestMethod] at test.line (1-based).
41
+ * 2. Scan forward up to 20 lines for an existing [TestProperty("<tagPrefix>", "...")] — replace it.
42
+ * 3. If not found, insert immediately after the [TestMethod] line, matching indentation.
43
+ *
44
+ * Only the value is replaced on an existing attribute; all other attributes are untouched.
45
+ */
46
+ export declare function writebackCsharp(test: ParsedTest, id: number, tagPrefix: string): void;
47
+ /**
48
+ * Write (or update) the TC ID comment in a .js / .ts file for a given
49
+ * it() / test() call (Jest, Jasmine, WebdriverIO).
50
+ *
51
+ * Format: // @tc:12345 inserted immediately above the it() / test() line.
52
+ * No extra dependency required.
53
+ *
54
+ * Strategy:
55
+ * 1. Locate the it()/test() line at test.line (1-based).
56
+ * 2. Scan backward (up to 25 lines) for an existing // @{tagPrefix}:N comment.
57
+ * 3. If found, replace in place.
58
+ * 4. If not found, insert immediately above the it()/test() line.
59
+ */
60
+ export declare function writebackJavaScript(test: ParsedTest, id: number, tagPrefix: string): void;
61
+ /**
62
+ * Write (or update) the TC ID in a .py file for a given def test_* function.
63
+ *
64
+ * Format: @pytest.mark.{tagPrefix}(12345) inserted immediately above the
65
+ * def line, below any other existing marks.
66
+ *
67
+ * No extra Python dependency — pytest is already on the test path.
68
+ *
69
+ * Strategy:
70
+ * 1. Locate the def line at test.line (1-based).
71
+ * 2. Scan backward (up to 30 lines) for an existing @pytest.mark.{tagPrefix}(N).
72
+ * Also recognises the comment fallback # @tc:N and replaces it with the mark.
73
+ * 3. If found, update in place.
74
+ * 4. If not found, insert @pytest.mark.{tagPrefix}(N) immediately above the def line.
75
+ */
76
+ export declare function writebackPython(test: ParsedTest, id: number, tagPrefix: string): void;
77
+ /**
78
+ * Write (or update) the TC ID in a .java file for a given @Test method.
79
+ *
80
+ * Strategy by framework (detected from import statements):
81
+ *
82
+ * JUnit 5 → @Tag("tc:12345") inserted/updated in the annotation block above @Test.
83
+ * @Tag is already in junit-jupiter-api — no extra dependency.
84
+ * Scans both above and below @Test for an existing @Tag("tc:N") to update.
85
+ *
86
+ * JUnit 4 → // @tc:12345 comment inserted/updated immediately above @Test.
87
+ * TestNG → // @tc:12345 comment inserted/updated immediately above @Test.
88
+ * Note: @Test(tc="...") is not valid TestNG syntax.
89
+ * unknown → comment fallback (same as JUnit 4/TestNG).
90
+ */
91
+ export declare function writebackJava(test: ParsedTest, id: number, tagPrefix: string): void;
92
+ export declare function writebackId(test: ParsedTest, id: number, localType: 'gherkin' | 'markdown' | 'csv' | 'excel' | 'csharp' | 'java' | 'python' | 'javascript', tagPrefix: string): Promise<void>;