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.
- package/README.md +240 -678
- package/dist/azure/client.d.ts +3 -0
- package/dist/azure/client.js +6 -0
- package/dist/azure/client.js.map +1 -1
- package/dist/azure/test-cases.d.ts +8 -3
- package/dist/azure/test-cases.js +406 -25
- package/dist/azure/test-cases.js.map +1 -1
- package/dist/cli.js +51 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.js +111 -5
- package/dist/config.js.map +1 -1
- package/dist/parsers/csharp.d.ts +30 -0
- package/dist/parsers/csharp.js +257 -0
- package/dist/parsers/csharp.js.map +1 -0
- package/dist/parsers/gherkin.d.ts +4 -1
- package/dist/parsers/gherkin.js +19 -4
- package/dist/parsers/gherkin.js.map +1 -1
- package/dist/parsers/java.d.ts +40 -0
- package/dist/parsers/java.js +329 -0
- package/dist/parsers/java.js.map +1 -0
- package/dist/parsers/javascript.d.ts +33 -0
- package/dist/parsers/javascript.js +261 -0
- package/dist/parsers/javascript.js.map +1 -0
- package/dist/parsers/markdown.d.ts +4 -1
- package/dist/parsers/markdown.js +5 -3
- package/dist/parsers/markdown.js.map +1 -1
- package/dist/parsers/python.d.ts +34 -0
- package/dist/parsers/python.js +305 -0
- package/dist/parsers/python.js.map +1 -0
- package/dist/parsers/shared.d.ts +18 -0
- package/dist/parsers/shared.js +40 -0
- package/dist/parsers/shared.js.map +1 -1
- package/dist/sync/engine.js +114 -5
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/publish-results.d.ts +49 -0
- package/dist/sync/publish-results.js +476 -0
- package/dist/sync/publish-results.js.map +1 -0
- package/dist/sync/writeback.d.ts +57 -1
- package/dist/sync/writeback.js +243 -0
- package/dist/sync/writeback.js.map +1 -1
- package/dist/types.d.ts +159 -2
- package/docs/advanced.md +350 -0
- package/docs/configuration.md +293 -0
- package/docs/publish-test-results.md +317 -0
- package/docs/spec-formats.md +595 -0
- package/package.json +1 -1
package/dist/parsers/markdown.js
CHANGED
|
@@ -133,7 +133,7 @@ function splitIntoScenarios(lines) {
|
|
|
133
133
|
blocks.push(current);
|
|
134
134
|
return blocks;
|
|
135
135
|
}
|
|
136
|
-
function parseScenarioBlock(block, filePath, tagPrefix, pathTags, linkConfigs) {
|
|
136
|
+
function parseScenarioBlock(block, filePath, tagPrefix, pathTags, linkConfigs, attachmentPrefixes) {
|
|
137
137
|
const lines = block.lines;
|
|
138
138
|
const blockText = lines.join('\n');
|
|
139
139
|
// Find ID — plain "@tc:12345" line (new) or legacy HTML comment (backward compat)
|
|
@@ -235,14 +235,16 @@ function parseScenarioBlock(block, filePath, tagPrefix, pathTags, linkConfigs) {
|
|
|
235
235
|
azureId,
|
|
236
236
|
line: block.startLine,
|
|
237
237
|
linkRefs: (0, shared_1.extractLinkRefs)(allTags, linkConfigs),
|
|
238
|
+
attachmentRefs: (0, shared_1.extractAttachmentRefs)(allTags, attachmentPrefixes),
|
|
238
239
|
};
|
|
239
240
|
}
|
|
240
|
-
function parseMarkdownFile(filePath, tagPrefix, linkConfigs) {
|
|
241
|
+
function parseMarkdownFile(filePath, tagPrefix, linkConfigs, attachmentsConfig) {
|
|
241
242
|
const source = fs.readFileSync(filePath, 'utf8');
|
|
242
243
|
const lines = source.split('\n');
|
|
243
244
|
const blocks = splitIntoScenarios(lines);
|
|
244
245
|
// Path-based auto-tags (same as Gherkin)
|
|
245
246
|
const pathTags = (0, shared_1.extractPathTags)(filePath);
|
|
246
|
-
|
|
247
|
+
const attachmentPrefixes = (0, shared_1.getAttachmentPrefixes)(attachmentsConfig);
|
|
248
|
+
return blocks.map((b) => parseScenarioBlock(b, filePath, tagPrefix, pathTags, linkConfigs, attachmentPrefixes));
|
|
247
249
|
}
|
|
248
250
|
//# sourceMappingURL=markdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/parsers/markdown.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/parsers/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python pytest parser for azure-test-sync.
|
|
3
|
+
*
|
|
4
|
+
* Detects def test_* functions (both module-level and inside test classes).
|
|
5
|
+
*
|
|
6
|
+
* Source mapping:
|
|
7
|
+
* Docstring first non-numbered line → TC Title
|
|
8
|
+
* Numbered lines "N. text" → TC Steps (action)
|
|
9
|
+
* "N. Check: text" → TC Steps (expected result column)
|
|
10
|
+
* @pytest.mark.xxx → TC Tags (user-defined marks)
|
|
11
|
+
* @pytest.mark.{tagPrefix}(N) → Azure TC ID (preferred writeback form)
|
|
12
|
+
* # @{tagPrefix}:N above the def → Azure TC ID (comment fallback)
|
|
13
|
+
* module.ClassName.method_name → automatedTestName
|
|
14
|
+
*
|
|
15
|
+
* ID writeback:
|
|
16
|
+
* Inserts / updates @pytest.mark.{tagPrefix}(12345) immediately above the
|
|
17
|
+
* def test_* line (below any existing marks).
|
|
18
|
+
* No extra Python dependency — pytest is already on the test path.
|
|
19
|
+
*
|
|
20
|
+
* Built-in pytest marks that are NOT treated as user tags:
|
|
21
|
+
* parametrize, skip, skipif, xfail, usefixtures, filterwarnings
|
|
22
|
+
*
|
|
23
|
+
* Path-based auto-tagging: directory segments starting with '@' become tags.
|
|
24
|
+
*/
|
|
25
|
+
import { LinkConfig, ParsedTest } from '../types';
|
|
26
|
+
/**
|
|
27
|
+
* Derive a dotted Python module path from the file path.
|
|
28
|
+
* Looks for a common root directory (tests / test / src / lib) and uses the
|
|
29
|
+
* path from that directory onward, stripping the .py extension.
|
|
30
|
+
*
|
|
31
|
+
* e.g. /project/tests/login/test_login.py → tests.login.test_login
|
|
32
|
+
*/
|
|
33
|
+
export declare function derivePythonModulePath(filePath: string): string;
|
|
34
|
+
export declare function parsePythonFile(filePath: string, tagPrefix: string, linkConfigs?: LinkConfig[]): ParsedTest[];
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Python pytest parser for azure-test-sync.
|
|
4
|
+
*
|
|
5
|
+
* Detects def test_* functions (both module-level and inside test classes).
|
|
6
|
+
*
|
|
7
|
+
* Source mapping:
|
|
8
|
+
* Docstring first non-numbered line → TC Title
|
|
9
|
+
* Numbered lines "N. text" → TC Steps (action)
|
|
10
|
+
* "N. Check: text" → TC Steps (expected result column)
|
|
11
|
+
* @pytest.mark.xxx → TC Tags (user-defined marks)
|
|
12
|
+
* @pytest.mark.{tagPrefix}(N) → Azure TC ID (preferred writeback form)
|
|
13
|
+
* # @{tagPrefix}:N above the def → Azure TC ID (comment fallback)
|
|
14
|
+
* module.ClassName.method_name → automatedTestName
|
|
15
|
+
*
|
|
16
|
+
* ID writeback:
|
|
17
|
+
* Inserts / updates @pytest.mark.{tagPrefix}(12345) immediately above the
|
|
18
|
+
* def test_* line (below any existing marks).
|
|
19
|
+
* No extra Python dependency — pytest is already on the test path.
|
|
20
|
+
*
|
|
21
|
+
* Built-in pytest marks that are NOT treated as user tags:
|
|
22
|
+
* parametrize, skip, skipif, xfail, usefixtures, filterwarnings
|
|
23
|
+
*
|
|
24
|
+
* Path-based auto-tagging: directory segments starting with '@' become tags.
|
|
25
|
+
*/
|
|
26
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
29
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
30
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
31
|
+
}
|
|
32
|
+
Object.defineProperty(o, k2, desc);
|
|
33
|
+
}) : (function(o, m, k, k2) {
|
|
34
|
+
if (k2 === undefined) k2 = k;
|
|
35
|
+
o[k2] = m[k];
|
|
36
|
+
}));
|
|
37
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
38
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
39
|
+
}) : function(o, v) {
|
|
40
|
+
o["default"] = v;
|
|
41
|
+
});
|
|
42
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
43
|
+
var ownKeys = function(o) {
|
|
44
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
45
|
+
var ar = [];
|
|
46
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
47
|
+
return ar;
|
|
48
|
+
};
|
|
49
|
+
return ownKeys(o);
|
|
50
|
+
};
|
|
51
|
+
return function (mod) {
|
|
52
|
+
if (mod && mod.__esModule) return mod;
|
|
53
|
+
var result = {};
|
|
54
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
55
|
+
__setModuleDefault(result, mod);
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
})();
|
|
59
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
+
exports.derivePythonModulePath = derivePythonModulePath;
|
|
61
|
+
exports.parsePythonFile = parsePythonFile;
|
|
62
|
+
const fs = __importStar(require("fs"));
|
|
63
|
+
const shared_1 = require("./shared");
|
|
64
|
+
// ─── Module path derivation ───────────────────────────────────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* Derive a dotted Python module path from the file path.
|
|
67
|
+
* Looks for a common root directory (tests / test / src / lib) and uses the
|
|
68
|
+
* path from that directory onward, stripping the .py extension.
|
|
69
|
+
*
|
|
70
|
+
* e.g. /project/tests/login/test_login.py → tests.login.test_login
|
|
71
|
+
*/
|
|
72
|
+
function derivePythonModulePath(filePath) {
|
|
73
|
+
const parts = filePath.replace(/\\/g, '/').split('/');
|
|
74
|
+
const fileNameNoExt = (parts.pop() ?? '').replace(/\.py$/, '');
|
|
75
|
+
const rootNames = new Set(['tests', 'test', 'src', 'lib']);
|
|
76
|
+
let rootIdx = -1;
|
|
77
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
78
|
+
if (rootNames.has(parts[i])) {
|
|
79
|
+
rootIdx = i;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (rootIdx >= 0)
|
|
84
|
+
return [...parts.slice(rootIdx), fileNameNoExt].join('.');
|
|
85
|
+
return fileNameNoExt;
|
|
86
|
+
}
|
|
87
|
+
// ─── Enclosing class detection ────────────────────────────────────────────────
|
|
88
|
+
/**
|
|
89
|
+
* Walk backward from the def line to find a class definition at a lower
|
|
90
|
+
* indentation level. Returns the class name, or '' for module-level functions.
|
|
91
|
+
*/
|
|
92
|
+
function findEnclosingClass(lines, defLineIdx) {
|
|
93
|
+
const defIndent = (lines[defLineIdx].match(/^(\s*)/) ?? ['', ''])[1].length;
|
|
94
|
+
for (let i = defLineIdx - 1; i >= 0; i--) {
|
|
95
|
+
const line = lines[i];
|
|
96
|
+
const trimmed = line.trim();
|
|
97
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
98
|
+
continue;
|
|
99
|
+
const lineIndent = (line.match(/^(\s*)/) ?? ['', ''])[1].length;
|
|
100
|
+
if (lineIndent < defIndent) {
|
|
101
|
+
const m = trimmed.match(/^class\s+(\w+)/);
|
|
102
|
+
return m ? m[1] : '';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return '';
|
|
106
|
+
}
|
|
107
|
+
// ─── Test function detection ──────────────────────────────────────────────────
|
|
108
|
+
function isTestFunction(trimmedLine) {
|
|
109
|
+
return /^(?:async\s+)?def\s+test_\w+\s*\(/.test(trimmedLine);
|
|
110
|
+
}
|
|
111
|
+
function extractMethodName(trimmedLine) {
|
|
112
|
+
const m = trimmedLine.match(/^(?:async\s+)?def\s+(test_\w+)\s*\(/);
|
|
113
|
+
return m ? m[1] : '';
|
|
114
|
+
}
|
|
115
|
+
// ─── Docstring extraction ─────────────────────────────────────────────────────
|
|
116
|
+
/**
|
|
117
|
+
* Find and return the lines inside the docstring immediately following a
|
|
118
|
+
* def statement. Handles both single-line and multi-line """ / ''' forms.
|
|
119
|
+
*/
|
|
120
|
+
function extractDocstring(lines, defLineIdx) {
|
|
121
|
+
let i = defLineIdx + 1;
|
|
122
|
+
// Skip the rest of the def signature if it spans multiple lines
|
|
123
|
+
while (i < lines.length && !lines[i - 1].trim().endsWith(':') && lines[i].trim() === '')
|
|
124
|
+
i++;
|
|
125
|
+
// Skip blank lines between def and body
|
|
126
|
+
while (i < lines.length && lines[i].trim() === '')
|
|
127
|
+
i++;
|
|
128
|
+
if (i >= lines.length)
|
|
129
|
+
return [];
|
|
130
|
+
const firstLine = lines[i].trim();
|
|
131
|
+
let quote;
|
|
132
|
+
if (firstLine.startsWith('"""'))
|
|
133
|
+
quote = '"""';
|
|
134
|
+
else if (firstLine.startsWith("'''"))
|
|
135
|
+
quote = "'''";
|
|
136
|
+
else
|
|
137
|
+
return [];
|
|
138
|
+
const afterOpen = firstLine.slice(3);
|
|
139
|
+
// Single-line: """text"""
|
|
140
|
+
if (afterOpen.endsWith(quote)) {
|
|
141
|
+
const text = afterOpen.slice(0, afterOpen.length - 3).trim();
|
|
142
|
+
return text ? [text] : [];
|
|
143
|
+
}
|
|
144
|
+
// Opening triple-quote with immediate text on same line
|
|
145
|
+
const content = [];
|
|
146
|
+
if (afterOpen.trim())
|
|
147
|
+
content.push(afterOpen.trim());
|
|
148
|
+
i++;
|
|
149
|
+
while (i < lines.length) {
|
|
150
|
+
const trimmed = lines[i].trim();
|
|
151
|
+
if (trimmed.endsWith(quote)) {
|
|
152
|
+
const before = trimmed.slice(0, trimmed.length - 3).trim();
|
|
153
|
+
if (before)
|
|
154
|
+
content.push(before);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
content.push(trimmed);
|
|
158
|
+
i++;
|
|
159
|
+
}
|
|
160
|
+
// Drop leading/trailing blank lines inside the docstring
|
|
161
|
+
while (content.length && content[0] === '')
|
|
162
|
+
content.shift();
|
|
163
|
+
while (content.length && content[content.length - 1] === '')
|
|
164
|
+
content.pop();
|
|
165
|
+
return content;
|
|
166
|
+
}
|
|
167
|
+
// ─── Decorator block scanning ─────────────────────────────────────────────────
|
|
168
|
+
// pytest built-in marks that should NOT be treated as user-defined tags
|
|
169
|
+
const PYTEST_BUILTINS = new Set([
|
|
170
|
+
'parametrize', 'skip', 'skipif', 'xfail', 'usefixtures', 'filterwarnings',
|
|
171
|
+
]);
|
|
172
|
+
/**
|
|
173
|
+
* Scan backward from defLineIdx to collect pytest marks and a TC ID.
|
|
174
|
+
*
|
|
175
|
+
* Stops at:
|
|
176
|
+
* - blank lines (decorators in Python must be adjacent to def)
|
|
177
|
+
* - another function or class definition
|
|
178
|
+
* - any non-decorator, non-comment source line
|
|
179
|
+
*
|
|
180
|
+
* Multi-line decorator arguments (e.g. multi-line @parametrize) are skipped
|
|
181
|
+
* over using a parenthesis depth counter so the scan continues correctly.
|
|
182
|
+
*/
|
|
183
|
+
function extractDecoratorsAbove(lines, defLineIdx, tagPrefix) {
|
|
184
|
+
const marks = [];
|
|
185
|
+
let azureId;
|
|
186
|
+
const idMarkRe = new RegExp(`^@pytest\\.mark\\.${tagPrefix}\\((\\d+)\\)\\s*$`);
|
|
187
|
+
const markRe = /^@pytest\.mark\.(\w+)(?:\s*\(.*)?$/;
|
|
188
|
+
const commentIdRe = new RegExp(`#\\s*@${tagPrefix}:(\\d+)`);
|
|
189
|
+
let parenDepth = 0; // track open parens for multi-line decorators
|
|
190
|
+
for (let i = defLineIdx - 1; i >= 0 && i >= defLineIdx - 50; i--) {
|
|
191
|
+
const line = lines[i];
|
|
192
|
+
const trimmed = line.trim();
|
|
193
|
+
// Track parenthesis depth (scanning backward, so ) opens, ( closes)
|
|
194
|
+
for (const ch of trimmed) {
|
|
195
|
+
if (ch === ')')
|
|
196
|
+
parenDepth++;
|
|
197
|
+
if (ch === '(')
|
|
198
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
199
|
+
}
|
|
200
|
+
// While inside a multi-line decorator argument, keep going
|
|
201
|
+
if (parenDepth > 0)
|
|
202
|
+
continue;
|
|
203
|
+
// Blank line — decorators must be adjacent
|
|
204
|
+
if (trimmed === '')
|
|
205
|
+
break;
|
|
206
|
+
// Another function or class definition
|
|
207
|
+
if (/^(?:async\s+)?def\s+/.test(trimmed) || /^class\s+/.test(trimmed))
|
|
208
|
+
break;
|
|
209
|
+
// Comment with an ID: # @tc:12345
|
|
210
|
+
const cmtMatch = trimmed.match(commentIdRe);
|
|
211
|
+
if (cmtMatch && azureId === undefined) {
|
|
212
|
+
azureId = parseInt(cmtMatch[1], 10);
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
// Decorator line
|
|
216
|
+
if (trimmed.startsWith('@')) {
|
|
217
|
+
// ID mark: @pytest.mark.tc(12345)
|
|
218
|
+
const idMatch = trimmed.match(idMarkRe);
|
|
219
|
+
if (idMatch) {
|
|
220
|
+
if (azureId === undefined)
|
|
221
|
+
azureId = parseInt(idMatch[1], 10);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
// Regular mark: @pytest.mark.smoke
|
|
225
|
+
const markMatch = trimmed.match(markRe);
|
|
226
|
+
if (markMatch) {
|
|
227
|
+
const name = markMatch[1];
|
|
228
|
+
if (!PYTEST_BUILTINS.has(name) && name !== tagPrefix)
|
|
229
|
+
marks.push(name);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
// Other decorator (@staticmethod, @classmethod, etc.) — ignore
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
// Any other source line → stop
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
return { marks, azureId };
|
|
239
|
+
}
|
|
240
|
+
// ─── Docstring → title + steps ────────────────────────────────────────────────
|
|
241
|
+
const NUMBERED_STEP_RE = /^\d+\.\s+(.+)$/;
|
|
242
|
+
const CHECK_RE = /^[Cc]heck:\s+(.+)$/;
|
|
243
|
+
const META_RE = /^(?:test\s+case|user\s+story)[\s:]/i;
|
|
244
|
+
function parseSummary(docLines, methodName) {
|
|
245
|
+
let title = '';
|
|
246
|
+
const steps = [];
|
|
247
|
+
for (const line of docLines) {
|
|
248
|
+
if (!line || META_RE.test(line))
|
|
249
|
+
continue;
|
|
250
|
+
const numMatch = NUMBERED_STEP_RE.exec(line);
|
|
251
|
+
if (numMatch) {
|
|
252
|
+
const content = numMatch[1].trim();
|
|
253
|
+
const checkMatch = CHECK_RE.exec(content);
|
|
254
|
+
if (checkMatch) {
|
|
255
|
+
steps.push({ keyword: 'Then', text: checkMatch[1].trim() });
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
steps.push({ keyword: 'Step', text: content });
|
|
259
|
+
}
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (!title)
|
|
263
|
+
title = line;
|
|
264
|
+
}
|
|
265
|
+
if (!title) {
|
|
266
|
+
// Convert snake_case to readable words: test_user_login → user login
|
|
267
|
+
title = methodName.replace(/^test_/, '').replace(/_/g, ' ');
|
|
268
|
+
}
|
|
269
|
+
return { title, steps };
|
|
270
|
+
}
|
|
271
|
+
// ─── Public parser ────────────────────────────────────────────────────────────
|
|
272
|
+
function parsePythonFile(filePath, tagPrefix, linkConfigs) {
|
|
273
|
+
const source = fs.readFileSync(filePath, 'utf8');
|
|
274
|
+
const lines = source.split('\n');
|
|
275
|
+
const modulePath = derivePythonModulePath(filePath);
|
|
276
|
+
const pathTags = (0, shared_1.extractPathTags)(filePath);
|
|
277
|
+
const results = [];
|
|
278
|
+
for (let i = 0; i < lines.length; i++) {
|
|
279
|
+
const trimmed = lines[i].trim();
|
|
280
|
+
if (!isTestFunction(trimmed))
|
|
281
|
+
continue;
|
|
282
|
+
const defLineIdx = i;
|
|
283
|
+
const methodName = extractMethodName(trimmed);
|
|
284
|
+
if (!methodName)
|
|
285
|
+
continue;
|
|
286
|
+
const className = findEnclosingClass(lines, defLineIdx);
|
|
287
|
+
const docLines = extractDocstring(lines, defLineIdx);
|
|
288
|
+
const { marks, azureId } = extractDecoratorsAbove(lines, defLineIdx, tagPrefix);
|
|
289
|
+
const allTags = [...new Set([...pathTags, ...marks])];
|
|
290
|
+
const { title, steps } = parseSummary(docLines, methodName);
|
|
291
|
+
const fqmn = [modulePath, className, methodName].filter(Boolean).join('.');
|
|
292
|
+
results.push({
|
|
293
|
+
filePath,
|
|
294
|
+
title,
|
|
295
|
+
steps,
|
|
296
|
+
tags: allTags,
|
|
297
|
+
azureId: azureId !== undefined && !isNaN(azureId) ? azureId : undefined,
|
|
298
|
+
line: defLineIdx + 1, // 1-based; writeback targets this def line
|
|
299
|
+
linkRefs: (0, shared_1.extractLinkRefs)(allTags, linkConfigs),
|
|
300
|
+
automatedTestName: fqmn || undefined,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
return results;
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=python.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python.js","sourceRoot":"","sources":["../../src/parsers/python.ts"],"names":[],"mappings":"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"}
|
package/dist/parsers/shared.d.ts
CHANGED
|
@@ -18,3 +18,21 @@ export declare function extractLinkRefs(tags: string[], linkConfigs: Array<{
|
|
|
18
18
|
prefix: string;
|
|
19
19
|
id: number;
|
|
20
20
|
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Extract attachment file references from tags.
|
|
23
|
+
* Default prefix is 'attachment'. Additional prefixes can be configured.
|
|
24
|
+
* e.g. tags=['attachment:screen.png', 'wireframe:mock.pdf'], prefixes=['wireframe']
|
|
25
|
+
* → [{ prefix:'attachment', filePath:'screen.png' }, { prefix:'wireframe', filePath:'mock.pdf' }]
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractAttachmentRefs(tags: string[], attachmentPrefixes: string[]): Array<{
|
|
28
|
+
prefix: string;
|
|
29
|
+
filePath: string;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Get the effective list of attachment tag prefixes from config.
|
|
33
|
+
* Always includes 'attachment' as the default prefix when attachments are enabled.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getAttachmentPrefixes(attachmentsConfig?: {
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
tagPrefixes?: string[];
|
|
38
|
+
}): string[];
|
package/dist/parsers/shared.js
CHANGED
|
@@ -38,6 +38,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.extractPathTags = extractPathTags;
|
|
40
40
|
exports.extractLinkRefs = extractLinkRefs;
|
|
41
|
+
exports.extractAttachmentRefs = extractAttachmentRefs;
|
|
42
|
+
exports.getAttachmentPrefixes = getAttachmentPrefixes;
|
|
41
43
|
const path = __importStar(require("path"));
|
|
42
44
|
/**
|
|
43
45
|
* Extract auto-tags from directory segments that start with '@'.
|
|
@@ -78,4 +80,42 @@ function extractLinkRefs(tags, linkConfigs) {
|
|
|
78
80
|
}
|
|
79
81
|
return refs;
|
|
80
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Extract attachment file references from tags.
|
|
85
|
+
* Default prefix is 'attachment'. Additional prefixes can be configured.
|
|
86
|
+
* e.g. tags=['attachment:screen.png', 'wireframe:mock.pdf'], prefixes=['wireframe']
|
|
87
|
+
* → [{ prefix:'attachment', filePath:'screen.png' }, { prefix:'wireframe', filePath:'mock.pdf' }]
|
|
88
|
+
*/
|
|
89
|
+
function extractAttachmentRefs(tags, attachmentPrefixes) {
|
|
90
|
+
if (!attachmentPrefixes.length)
|
|
91
|
+
return [];
|
|
92
|
+
const refs = [];
|
|
93
|
+
for (const prefix of attachmentPrefixes) {
|
|
94
|
+
const pfx = prefix + ':';
|
|
95
|
+
for (const tag of tags) {
|
|
96
|
+
if (tag.startsWith(pfx)) {
|
|
97
|
+
const fp = tag.slice(pfx.length);
|
|
98
|
+
if (fp)
|
|
99
|
+
refs.push({ prefix, filePath: fp });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return refs;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get the effective list of attachment tag prefixes from config.
|
|
107
|
+
* Always includes 'attachment' as the default prefix when attachments are enabled.
|
|
108
|
+
*/
|
|
109
|
+
function getAttachmentPrefixes(attachmentsConfig) {
|
|
110
|
+
if (!attachmentsConfig?.enabled)
|
|
111
|
+
return [];
|
|
112
|
+
const prefixes = ['attachment'];
|
|
113
|
+
if (attachmentsConfig.tagPrefixes?.length) {
|
|
114
|
+
for (const p of attachmentsConfig.tagPrefixes) {
|
|
115
|
+
if (!prefixes.includes(p))
|
|
116
|
+
prefixes.push(p);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return prefixes;
|
|
120
|
+
}
|
|
81
121
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/parsers/shared.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUH,0CAYC;AAMD,0CAgBC;
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/parsers/shared.ts"],"names":[],"mappings":"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"}
|