ado-sync 0.1.30 → 0.1.31

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.
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ /**
3
+ * Dart / Flutter test parser for azure-test-sync.
4
+ *
5
+ * Handles Flutter widget tests and unit tests written with the
6
+ * `flutter_test` / `test` packages.
7
+ *
8
+ * Detected test functions:
9
+ * testWidgets('title', (WidgetTester tester) async { ... })
10
+ * test('title', () { ... })
11
+ * testUI('title', () { ... }) ← integration_test alias
12
+ *
13
+ * Detected group blocks (used as the describe / suite equivalent):
14
+ * group('Group title', () { ... })
15
+ *
16
+ * Source mapping:
17
+ * /// Dart doc comment above testWidgets → TC Title (first non-numbered line)
18
+ * JSDoc /** ... * / doc comment → TC Title + Steps (same format)
19
+ * Numbered lines "N. text" → TC Steps (action)
20
+ * "N. Check: text" → TC Steps (expected result column)
21
+ * // @tags: smoke, regression → TC Tags (comma-separated list)
22
+ * // @smoke → TC Tag (single-word shorthand)
23
+ * // @{tagPrefix}:N → Azure TC ID (written back after push)
24
+ * {fileBasename} > {group} > {title} → automatedTestName
25
+ *
26
+ * ID writeback:
27
+ * Inserts / updates // @tc:12345 immediately above the testWidgets() / test() line.
28
+ *
29
+ * Path-based auto-tagging: directory segments starting with '@' become tags.
30
+ */
31
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
32
+ if (k2 === undefined) k2 = k;
33
+ var desc = Object.getOwnPropertyDescriptor(m, k);
34
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
35
+ desc = { enumerable: true, get: function() { return m[k]; } };
36
+ }
37
+ Object.defineProperty(o, k2, desc);
38
+ }) : (function(o, m, k, k2) {
39
+ if (k2 === undefined) k2 = k;
40
+ o[k2] = m[k];
41
+ }));
42
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
43
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
44
+ }) : function(o, v) {
45
+ o["default"] = v;
46
+ });
47
+ var __importStar = (this && this.__importStar) || (function () {
48
+ var ownKeys = function(o) {
49
+ ownKeys = Object.getOwnPropertyNames || function (o) {
50
+ var ar = [];
51
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
52
+ return ar;
53
+ };
54
+ return ownKeys(o);
55
+ };
56
+ return function (mod) {
57
+ if (mod && mod.__esModule) return mod;
58
+ var result = {};
59
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
60
+ __setModuleDefault(result, mod);
61
+ return result;
62
+ };
63
+ })();
64
+ Object.defineProperty(exports, "__esModule", { value: true });
65
+ exports.parseDartFile = parseDartFile;
66
+ const fs = __importStar(require("fs"));
67
+ const path = __importStar(require("path"));
68
+ const shared_1 = require("./shared");
69
+ // ─── Test / group detection ────────────────────────────────────────────────────
70
+ const TEST_CALL_RE = /^(?:testWidgets|testUI|test)\s*\(/;
71
+ const TEST_TITLE_RE = /^(?:testWidgets|testUI|test)\s*\(\s*(['"`])((?:\\.|[^\\])*?)\1/;
72
+ const GROUP_TITLE_RE = /^group\s*\(\s*(['"`])((?:\\.|[^\\])*?)\1/;
73
+ // ─── Indentation helpers ──────────────────────────────────────────────────────
74
+ function getIndentLength(line) {
75
+ return (line.match(/^(\s*)/) ?? ['', ''])[1].length;
76
+ }
77
+ // ─── Enclosing group blocks ───────────────────────────────────────────────────
78
+ function findEnclosingGroups(lines, testLineIdx) {
79
+ const groups = [];
80
+ let targetIndent = getIndentLength(lines[testLineIdx]);
81
+ for (let i = testLineIdx - 1; i >= 0; i--) {
82
+ const line = lines[i];
83
+ const trimmed = line.trim();
84
+ if (!trimmed)
85
+ continue;
86
+ const lineIndent = getIndentLength(line);
87
+ if (lineIndent < targetIndent) {
88
+ const m = trimmed.match(GROUP_TITLE_RE);
89
+ if (m) {
90
+ groups.unshift(m[2].replace(/\\'/g, "'").replace(/\\"/g, '"').replace(/\\`/g, '`'));
91
+ targetIndent = lineIndent;
92
+ }
93
+ }
94
+ }
95
+ return groups;
96
+ }
97
+ // ─── Doc comment extraction ───────────────────────────────────────────────────
98
+ /**
99
+ * Extract Dart doc comments above testWidgets() / test().
100
+ * Supports triple-slash (///) Dart idiomatic style and block (/* * /) style.
101
+ */
102
+ function extractDocBefore(lines, testLineIdx) {
103
+ let i = testLineIdx - 1;
104
+ // Skip blank lines and regular single-line comments
105
+ while (i >= 0) {
106
+ const t = lines[i].trim();
107
+ if (t === '' || (t.startsWith('//') && !t.startsWith('///'))) {
108
+ i--;
109
+ continue;
110
+ }
111
+ break;
112
+ }
113
+ if (i < 0)
114
+ return [];
115
+ // /// triple-slash style (Dart idiomatic)
116
+ if (lines[i].trim().startsWith('///')) {
117
+ const docLines = [];
118
+ while (i >= 0 && lines[i].trim().startsWith('///')) {
119
+ docLines.unshift(lines[i].trim().replace(/^\/\/\/\s?/, ''));
120
+ i--;
121
+ }
122
+ return docLines.filter((l) => l !== '');
123
+ }
124
+ // /** ... */ block style
125
+ if (!lines[i].trim().endsWith('*/'))
126
+ return [];
127
+ const raw = [];
128
+ raw.unshift(lines[i]);
129
+ i--;
130
+ while (i >= 0) {
131
+ raw.unshift(lines[i]);
132
+ if (lines[i].trim().startsWith('/**') || lines[i].trim().startsWith('/*'))
133
+ break;
134
+ i--;
135
+ }
136
+ return raw
137
+ .map((l) => l
138
+ .replace(/^\s*\/\*\*?\s?/, '')
139
+ .replace(/\s*\*\/\s*$/, '')
140
+ .replace(/^\s*\*\s?/, '')
141
+ .trim())
142
+ .filter((l) => l !== '');
143
+ }
144
+ function extractCommentMetadataAbove(lines, testLineIdx, tagPrefix) {
145
+ const tags = [];
146
+ let azureId;
147
+ const idRe = new RegExp(`//\\s*@${tagPrefix}:(\\d+)`);
148
+ const tagsListRe = /\/\/\s*@tags?\s*:\s*(.+)/i;
149
+ const singleTagRe = /\/\/\s*@(\w+)\s*$/;
150
+ for (let i = testLineIdx - 1; i >= 0 && i >= testLineIdx - 25; i--) {
151
+ const trimmed = lines[i].trim();
152
+ if (trimmed === '')
153
+ break;
154
+ if (!trimmed.startsWith('//') && !trimmed.startsWith('*') && !trimmed.startsWith('/*'))
155
+ break;
156
+ const idMatch = trimmed.match(idRe);
157
+ if (idMatch && azureId === undefined) {
158
+ azureId = parseInt(idMatch[1], 10);
159
+ continue;
160
+ }
161
+ const tagsMatch = trimmed.match(tagsListRe);
162
+ if (tagsMatch) {
163
+ tags.push(...tagsMatch[1].split(',').map((t) => t.trim()).filter(Boolean));
164
+ continue;
165
+ }
166
+ const singleTag = trimmed.match(singleTagRe);
167
+ if (singleTag && singleTag[1] !== tagPrefix) {
168
+ tags.push(singleTag[1]);
169
+ continue;
170
+ }
171
+ }
172
+ return { azureId, tags };
173
+ }
174
+ // ─── Doc → title + steps ─────────────────────────────────────────────────────
175
+ const NUMBERED_STEP_RE = /^\d+\.\s+(.+)$/;
176
+ const CHECK_RE = /^[Cc]heck:\s+(.+)$/;
177
+ const META_RE = /^(?:test\s+case|user\s+story)[\s:]/i;
178
+ function parseSummary(docLines, fallbackTitle) {
179
+ let title = '';
180
+ const steps = [];
181
+ for (const line of docLines) {
182
+ if (!line || META_RE.test(line))
183
+ continue;
184
+ const numMatch = NUMBERED_STEP_RE.exec(line);
185
+ if (numMatch) {
186
+ const content = numMatch[1].trim();
187
+ const checkMatch = CHECK_RE.exec(content);
188
+ if (checkMatch) {
189
+ steps.push({ keyword: 'Then', text: checkMatch[1].trim() });
190
+ }
191
+ else {
192
+ steps.push({ keyword: 'Step', text: content });
193
+ }
194
+ continue;
195
+ }
196
+ if (!title)
197
+ title = line;
198
+ }
199
+ return { title: title || fallbackTitle, steps };
200
+ }
201
+ // ─── Public parser ────────────────────────────────────────────────────────────
202
+ function parseDartFile(filePath, tagPrefix, linkConfigs) {
203
+ const source = fs.readFileSync(filePath, 'utf8');
204
+ const lines = source.split('\n');
205
+ // Strip _test.dart / .dart suffixes for a clean base name
206
+ const fileBaseName = path.basename(filePath)
207
+ .replace(/_test\.dart$/, '')
208
+ .replace(/\.dart$/, '');
209
+ const pathTags = (0, shared_1.extractPathTags)(filePath);
210
+ const results = [];
211
+ for (let i = 0; i < lines.length; i++) {
212
+ const trimmed = lines[i].trim();
213
+ if (!TEST_CALL_RE.test(trimmed))
214
+ continue;
215
+ const testLineIdx = i;
216
+ const m = trimmed.match(TEST_TITLE_RE);
217
+ if (!m)
218
+ continue;
219
+ const callTitle = m[2]
220
+ .replace(/\\'/g, "'")
221
+ .replace(/\\"/g, '"')
222
+ .replace(/\\`/g, '`');
223
+ if (!callTitle)
224
+ continue;
225
+ const docLines = extractDocBefore(lines, testLineIdx);
226
+ const { azureId, tags: cTags } = extractCommentMetadataAbove(lines, testLineIdx, tagPrefix);
227
+ const groups = findEnclosingGroups(lines, testLineIdx);
228
+ const allTags = [...new Set([...pathTags, ...cTags])];
229
+ const { title, steps } = parseSummary(docLines, callTitle);
230
+ // automatedTestName mirrors Flutter test result format
231
+ const automatedTestName = [fileBaseName, ...groups, callTitle].join(' > ');
232
+ results.push({
233
+ filePath,
234
+ title,
235
+ steps,
236
+ tags: allTags,
237
+ azureId: azureId !== undefined && !isNaN(azureId) ? azureId : undefined,
238
+ line: testLineIdx + 1,
239
+ linkRefs: (0, shared_1.extractLinkRefs)(allTags, linkConfigs),
240
+ automatedTestName,
241
+ });
242
+ }
243
+ return results;
244
+ }
245
+ //# sourceMappingURL=dart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dart.js","sourceRoot":"","sources":["../../src/parsers/dart.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,28 @@
1
1
  /**
2
2
  * JavaScript / TypeScript test parser for azure-test-sync.
3
3
  *
4
- * Supports Jest, Jasmine, and WebdriverIO (which uses Jest or Jasmine as its
5
- * underlying test runner). All three frameworks share the same
6
- * describe() / it() / test() API for test organisation, so a single parser
7
- * handles all of them.
4
+ * Supports Jest, Jasmine, WebdriverIO, Playwright Test, Puppeteer (Mocha/Jest),
5
+ * and Cypress. All frameworks share the same describe() / it() / test() API for
6
+ * test organisation, so a single parser handles all of them.
8
7
  *
9
8
  * Cucumber (.feature files) is already handled by the existing 'gherkin' type.
9
+ * TestCafe uses a fixture/test API and is handled by the separate 'testcafe' type.
10
10
  *
11
11
  * Detected test functions:
12
- * it(title, fn) test(title, fn)
13
- * it.only / test.only it.skip / test.skip
14
- * xit / xtest (Jasmine skip — still synced to Azure)
12
+ * it(title, fn) test(title, fn)
13
+ * it.only / test.only it.skip / test.skip
14
+ * xit / xtest (Jasmine skip — still synced to Azure)
15
15
  * it.concurrent / test.concurrent
16
+ * test.fixme(title, fn) (Playwright — annotates test as fixme)
17
+ * test.fail(title, fn) (Playwright — marks test as expected to fail)
18
+ * specify(title, fn) specify.only / specify.skip (Cypress alias for it)
19
+ *
20
+ * Detected describe functions (for nesting):
21
+ * describe() describe.only() describe.skip() describe.concurrent()
22
+ * test.describe() (Playwright)
23
+ * test.describe.only() test.describe.skip()
24
+ * test.describe.parallel() test.describe.serial()
25
+ * context() context.only() context.skip() (Cypress alias for describe)
16
26
  *
17
27
  * Source mapping:
18
28
  * JSDoc /** ... * / first non-numbered line → TC Title
@@ -2,18 +2,28 @@
2
2
  /**
3
3
  * JavaScript / TypeScript test parser for azure-test-sync.
4
4
  *
5
- * Supports Jest, Jasmine, and WebdriverIO (which uses Jest or Jasmine as its
6
- * underlying test runner). All three frameworks share the same
7
- * describe() / it() / test() API for test organisation, so a single parser
8
- * handles all of them.
5
+ * Supports Jest, Jasmine, WebdriverIO, Playwright Test, Puppeteer (Mocha/Jest),
6
+ * and Cypress. All frameworks share the same describe() / it() / test() API for
7
+ * test organisation, so a single parser handles all of them.
9
8
  *
10
9
  * Cucumber (.feature files) is already handled by the existing 'gherkin' type.
10
+ * TestCafe uses a fixture/test API and is handled by the separate 'testcafe' type.
11
11
  *
12
12
  * Detected test functions:
13
- * it(title, fn) test(title, fn)
14
- * it.only / test.only it.skip / test.skip
15
- * xit / xtest (Jasmine skip — still synced to Azure)
13
+ * it(title, fn) test(title, fn)
14
+ * it.only / test.only it.skip / test.skip
15
+ * xit / xtest (Jasmine skip — still synced to Azure)
16
16
  * it.concurrent / test.concurrent
17
+ * test.fixme(title, fn) (Playwright — annotates test as fixme)
18
+ * test.fail(title, fn) (Playwright — marks test as expected to fail)
19
+ * specify(title, fn) specify.only / specify.skip (Cypress alias for it)
20
+ *
21
+ * Detected describe functions (for nesting):
22
+ * describe() describe.only() describe.skip() describe.concurrent()
23
+ * test.describe() (Playwright)
24
+ * test.describe.only() test.describe.skip()
25
+ * test.describe.parallel() test.describe.serial()
26
+ * context() context.only() context.skip() (Cypress alias for describe)
17
27
  *
18
28
  * Source mapping:
19
29
  * JSDoc /** ... * / first non-numbered line → TC Title
@@ -69,10 +79,11 @@ const fs = __importStar(require("fs"));
69
79
  const path = __importStar(require("path"));
70
80
  const shared_1 = require("./shared");
71
81
  // ─── Test function detection ──────────────────────────────────────────────────
72
- const TEST_FN_PREFIX = '(?:it|test|xit|xtest|it\\.only|test\\.only|it\\.skip|test\\.skip|it\\.concurrent|test\\.concurrent)';
82
+ const TEST_FN_PREFIX = '(?:it|test|xit|xtest|specify|it\\.only|test\\.only|specify\\.only|it\\.skip|test\\.skip|specify\\.skip|it\\.concurrent|test\\.concurrent|test\\.fixme|test\\.fail)';
73
83
  const TEST_CALL_RE = new RegExp(`^${TEST_FN_PREFIX}\\s*\\(`);
74
84
  const TEST_TITLE_RE = new RegExp(`^${TEST_FN_PREFIX}\\s*\\(\\s*(['"\`])((?:\\\\.|[^\\\\])*?)\\1`);
75
- const DESCRIBE_TITLE_RE = /^describe(?:\.(?:only|skip|concurrent))?\s*\(\s*(['"`])((?:\\.|[^\\])*?)\1/;
85
+ // context() and context.only/skip are Cypress aliases for describe()
86
+ const DESCRIBE_TITLE_RE = /^(?:describe(?:\.(?:only|skip|concurrent))?|context(?:\.(?:only|skip))?|test\.describe(?:\.(?:only|skip|parallel|serial|configure))?)\s*\(\s*(['"`])((?:\\.|[^\\])*?)\1/;
76
87
  function isTestLine(trimmedLine) {
77
88
  return TEST_CALL_RE.test(trimmedLine);
78
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../src/parsers/javascript.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6MH,kDAiDC;AA5PD,uCAAyB;AACzB,2CAA6B;AAG7B,qCAA4D;AAE5D,iFAAiF;AAEjF,MAAM,cAAc,GAClB,qGAAqG,CAAC;AAExG,MAAM,YAAY,GAAQ,IAAI,MAAM,CAAC,IAAI,cAAc,SAAS,CAAC,CAAC;AAClE,MAAM,aAAa,GAAO,IAAI,MAAM,CAClC,IAAI,cAAc,6CAA6C,CAChE,CAAC;AACF,MAAM,iBAAiB,GACrB,4EAA4E,CAAC;AAE/E,SAAS,UAAU,CAAC,WAAmB;IACrC,OAAO,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACxC,CAAC;AAED,gFAAgF;AAChF,SAAS,oBAAoB,CAAC,WAAmB;IAC/C,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC3C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClB,OAAO,CAAC,CAAC,CAAC,CAAC;SACR,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,iFAAiF;AAEjF,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACtD,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,SAAS,sBAAsB,CAAC,KAAe,EAAE,SAAiB;IAChE,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAErD,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,GAAM,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QAEvB,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,UAAU,GAAG,YAAY,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YAC3C,IAAI,CAAC,EAAE,CAAC;gBACN,SAAS,CAAC,OAAO,CACf,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CACpE,CAAC;gBACF,YAAY,GAAG,UAAU,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,SAAS,kBAAkB,CAAC,KAAe,EAAE,SAAiB;IAC5D,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;IAEtB,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAAC,CAAC,EAAE,CAAC;YAAC,SAAS;QAAC,CAAC;QACtD,MAAM;IACR,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAExD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC,EAAE,CAAC;IACJ,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACd,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,MAAM;QAC7C,CAAC,EAAE,CAAC;IACN,CAAC;IAED,OAAO,GAAG;SACP,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,CAAC;SACE,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;SACxB,IAAI,EAAE,CACV;SACA,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;AAC7B,CAAC;AASD;;;;;;;GAOG;AACH,SAAS,2BAA2B,CAClC,KAAe,EACf,SAAiB,EACjB,SAAiB;IAEjB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAA2B,CAAC;IAEhC,MAAM,IAAI,GAAQ,IAAI,MAAM,CAAC,UAAU,SAAS,SAAS,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,2BAA2B,CAAC;IAC/C,MAAM,WAAW,GAAG,mBAAmB,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEhC,kDAAkD;QAClD,IAAI,OAAO,KAAK,EAAE;YAAE,MAAM;QAE1B,8CAA8C;QAC9C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM;QAE9F,aAAa;QACb,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,OAAO,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACrC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnC,SAAS;QACX,CAAC;QAED,yCAAyC;QACzC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3E,SAAS;QACX,CAAC;QAED,kCAAkC;QAClC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC7C,IAAI,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACxB,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,iFAAiF;AAEjF,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAC1C,MAAM,QAAQ,GAAW,oBAAoB,CAAC;AAC9C,MAAM,OAAO,GAAY,qCAAqC,CAAC;AAE/D,SAAS,YAAY,CACnB,UAAoB,EACpB,aAAqB;IAErB,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,MAAM,KAAK,GAAiB,EAAE,CAAC;IAE/B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAE1C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,OAAO,GAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1C,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK;YAAE,KAAK,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,aAAa,EAAE,KAAK,EAAE,CAAC;AAClD,CAAC;AAED,iFAAiF;AAEjF,SAAgB,mBAAmB,CACjC,QAAgB,EAChB,SAAiB,EACjB,WAA0B;IAE1B,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,KAAK,GAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,uEAAuE;IACvE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;SACzC,OAAO,CAAC,iCAAiC,EAAE,EAAE,CAAC;SAC9C,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAErC,MAAM,QAAQ,GAAG,IAAA,wBAAe,EAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,SAAS;QAEnC,MAAM,SAAS,GAAG,CAAC,CAAC;QACpB,MAAM,SAAS,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAEhD,wEAAwE;QACxE,IAAI,CAAC,SAAS;YAAE,SAAS;QAEzB,MAAM,UAAU,GAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACrE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,2BAA2B,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC1F,MAAM,SAAS,GAAiB,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAEzE,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAE7D,oEAAoE;QACpE,MAAM,iBAAiB,GAAG,CAAC,YAAY,EAAE,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE9E,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ;YACR,KAAK;YACL,KAAK;YACL,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,OAAO,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YACvE,IAAI,EAAE,SAAS,GAAG,CAAC,EAAE,mDAAmD;YACxE,QAAQ,EAAE,IAAA,wBAAe,EAAC,OAAO,EAAE,WAAW,CAAC;YAC/C,iBAAiB;SAClB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../src/parsers/javascript.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Swift / XCUITest parser for azure-test-sync.
3
+ *
4
+ * Handles iOS and macOS UI-automation tests written with Apple's XCTest framework.
5
+ * Tests are `func test*()` methods inside classes that extend `XCTestCase`.
6
+ *
7
+ * Detected test functions:
8
+ * func testUserCanLogin() { ... }
9
+ * func test_login_succeeds() { ... }
10
+ *
11
+ * Detected class blocks (used as the test group / describe equivalent):
12
+ * class LoginTests: XCTestCase { ... }
13
+ *
14
+ * Source mapping:
15
+ * /// Swift doc comment above func test* → TC Title (first non-numbered line)
16
+ * JSDoc /** ... * / doc comment above func test* → TC Title + Steps (same format)
17
+ * Numbered lines "N. text" → TC Steps (action)
18
+ * "N. Check: text" → TC Steps (expected result column)
19
+ * // @tags: smoke, regression → TC Tags (comma-separated list)
20
+ * // @smoke → TC Tag (single-word shorthand)
21
+ * // @{tagPrefix}:N comment above func → Azure TC ID (written back after push)
22
+ * {fileBasename} > {ClassName} > {method} → automatedTestName
23
+ *
24
+ * Method name → title fallback:
25
+ * "testUserCanLogin" → "User can login"
26
+ * "test_submit_form" → "Submit form"
27
+ *
28
+ * ID writeback:
29
+ * Inserts / updates // @tc:12345 immediately above the func test*() line.
30
+ *
31
+ * Path-based auto-tagging: directory segments starting with '@' become tags.
32
+ */
33
+ import { LinkConfig, ParsedTest } from '../types';
34
+ export declare function parseSwiftFile(filePath: string, tagPrefix: string, linkConfigs?: LinkConfig[]): ParsedTest[];
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /**
3
+ * Swift / XCUITest parser for azure-test-sync.
4
+ *
5
+ * Handles iOS and macOS UI-automation tests written with Apple's XCTest framework.
6
+ * Tests are `func test*()` methods inside classes that extend `XCTestCase`.
7
+ *
8
+ * Detected test functions:
9
+ * func testUserCanLogin() { ... }
10
+ * func test_login_succeeds() { ... }
11
+ *
12
+ * Detected class blocks (used as the test group / describe equivalent):
13
+ * class LoginTests: XCTestCase { ... }
14
+ *
15
+ * Source mapping:
16
+ * /// Swift doc comment above func test* → TC Title (first non-numbered line)
17
+ * JSDoc /** ... * / doc comment above func test* → TC Title + Steps (same format)
18
+ * Numbered lines "N. text" → TC Steps (action)
19
+ * "N. Check: text" → TC Steps (expected result column)
20
+ * // @tags: smoke, regression → TC Tags (comma-separated list)
21
+ * // @smoke → TC Tag (single-word shorthand)
22
+ * // @{tagPrefix}:N comment above func → Azure TC ID (written back after push)
23
+ * {fileBasename} > {ClassName} > {method} → automatedTestName
24
+ *
25
+ * Method name → title fallback:
26
+ * "testUserCanLogin" → "User can login"
27
+ * "test_submit_form" → "Submit form"
28
+ *
29
+ * ID writeback:
30
+ * Inserts / updates // @tc:12345 immediately above the func test*() line.
31
+ *
32
+ * Path-based auto-tagging: directory segments starting with '@' become tags.
33
+ */
34
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
35
+ if (k2 === undefined) k2 = k;
36
+ var desc = Object.getOwnPropertyDescriptor(m, k);
37
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
38
+ desc = { enumerable: true, get: function() { return m[k]; } };
39
+ }
40
+ Object.defineProperty(o, k2, desc);
41
+ }) : (function(o, m, k, k2) {
42
+ if (k2 === undefined) k2 = k;
43
+ o[k2] = m[k];
44
+ }));
45
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
46
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
47
+ }) : function(o, v) {
48
+ o["default"] = v;
49
+ });
50
+ var __importStar = (this && this.__importStar) || (function () {
51
+ var ownKeys = function(o) {
52
+ ownKeys = Object.getOwnPropertyNames || function (o) {
53
+ var ar = [];
54
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
55
+ return ar;
56
+ };
57
+ return ownKeys(o);
58
+ };
59
+ return function (mod) {
60
+ if (mod && mod.__esModule) return mod;
61
+ var result = {};
62
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
63
+ __setModuleDefault(result, mod);
64
+ return result;
65
+ };
66
+ })();
67
+ Object.defineProperty(exports, "__esModule", { value: true });
68
+ exports.parseSwiftFile = parseSwiftFile;
69
+ const fs = __importStar(require("fs"));
70
+ const path = __importStar(require("path"));
71
+ const shared_1 = require("./shared");
72
+ // ─── Test method detection ────────────────────────────────────────────────────
73
+ const TEST_METHOD_RE = /^\s*func\s+(test\w+)\s*\(/;
74
+ const CLASS_RE = /^\s*(?:(?:open|final|public|internal|private)\s+)*class\s+(\w+)\s*(?::\s*[\w, ]+)?/;
75
+ // ─── Indentation helpers ──────────────────────────────────────────────────────
76
+ function getIndentLength(line) {
77
+ return (line.match(/^(\s*)/) ?? ['', ''])[1].length;
78
+ }
79
+ // ─── Enclosing class ──────────────────────────────────────────────────────────
80
+ function findEnclosingClass(lines, methodLineIdx) {
81
+ const methodIndent = getIndentLength(lines[methodLineIdx]);
82
+ for (let i = methodLineIdx - 1; i >= 0; i--) {
83
+ const lineIndent = getIndentLength(lines[i]);
84
+ if (lineIndent < methodIndent) {
85
+ const m = lines[i].trim().match(CLASS_RE);
86
+ if (m)
87
+ return m[1];
88
+ }
89
+ }
90
+ return undefined;
91
+ }
92
+ // ─── Doc comment extraction ───────────────────────────────────────────────────
93
+ /**
94
+ * Extract Swift doc comments above func test*().
95
+ * Handles both triple-slash (///) single-line and block (/* * /) style.
96
+ * Skips blank lines and single-line // comments on the way up.
97
+ */
98
+ function extractDocBefore(lines, methodLineIdx) {
99
+ let i = methodLineIdx - 1;
100
+ // Skip blank lines and non-doc single-line comments
101
+ while (i >= 0) {
102
+ const t = lines[i].trim();
103
+ if (t === '' || (t.startsWith('//') && !t.startsWith('///'))) {
104
+ i--;
105
+ continue;
106
+ }
107
+ break;
108
+ }
109
+ if (i < 0)
110
+ return [];
111
+ // /// triple-slash style (Swift idiomatic)
112
+ if (lines[i].trim().startsWith('///')) {
113
+ const docLines = [];
114
+ while (i >= 0 && lines[i].trim().startsWith('///')) {
115
+ docLines.unshift(lines[i].trim().replace(/^\/\/\/\s?/, ''));
116
+ i--;
117
+ }
118
+ return docLines.filter((l) => l !== '');
119
+ }
120
+ // /** ... */ block style
121
+ if (!lines[i].trim().endsWith('*/'))
122
+ return [];
123
+ const raw = [];
124
+ raw.unshift(lines[i]);
125
+ i--;
126
+ while (i >= 0) {
127
+ raw.unshift(lines[i]);
128
+ if (lines[i].trim().startsWith('/**') || lines[i].trim().startsWith('/*'))
129
+ break;
130
+ i--;
131
+ }
132
+ return raw
133
+ .map((l) => l
134
+ .replace(/^\s*\/\*\*?\s?/, '')
135
+ .replace(/\s*\*\/\s*$/, '')
136
+ .replace(/^\s*\*\s?/, '')
137
+ .trim())
138
+ .filter((l) => l !== '');
139
+ }
140
+ function extractCommentMetadataAbove(lines, methodLineIdx, tagPrefix) {
141
+ const tags = [];
142
+ let azureId;
143
+ const idRe = new RegExp(`//\\s*@${tagPrefix}:(\\d+)`);
144
+ const tagsListRe = /\/\/\s*@tags?\s*:\s*(.+)/i;
145
+ const singleTagRe = /\/\/\s*@(\w+)\s*$/;
146
+ for (let i = methodLineIdx - 1; i >= 0 && i >= methodLineIdx - 25; i--) {
147
+ const trimmed = lines[i].trim();
148
+ if (trimmed === '')
149
+ break;
150
+ if (!trimmed.startsWith('//') && !trimmed.startsWith('*') && !trimmed.startsWith('/*'))
151
+ break;
152
+ const idMatch = trimmed.match(idRe);
153
+ if (idMatch && azureId === undefined) {
154
+ azureId = parseInt(idMatch[1], 10);
155
+ continue;
156
+ }
157
+ const tagsMatch = trimmed.match(tagsListRe);
158
+ if (tagsMatch) {
159
+ tags.push(...tagsMatch[1].split(',').map((t) => t.trim()).filter(Boolean));
160
+ continue;
161
+ }
162
+ const singleTag = trimmed.match(singleTagRe);
163
+ if (singleTag && singleTag[1] !== tagPrefix) {
164
+ tags.push(singleTag[1]);
165
+ continue;
166
+ }
167
+ }
168
+ return { azureId, tags };
169
+ }
170
+ // ─── Method name → human-readable title ──────────────────────────────────────
171
+ /**
172
+ * Convert a Swift test method name to a sentence-style title.
173
+ * testUserCanLogin → "User can login"
174
+ * testLoginFails_badPassword → "Login fails bad password"
175
+ * test_submit_form → "Submit form"
176
+ */
177
+ function methodNameToTitle(name) {
178
+ let s = name.replace(/^test_?/, '');
179
+ if (!s)
180
+ return name;
181
+ // snake_case → words
182
+ s = s.replace(/_/g, ' ');
183
+ // camelCase → words
184
+ s = s.replace(/([a-z])([A-Z])/g, '$1 $2').replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2');
185
+ s = s.toLowerCase().replace(/^./, (c) => c.toUpperCase());
186
+ return s;
187
+ }
188
+ // ─── Doc → title + steps ─────────────────────────────────────────────────────
189
+ const NUMBERED_STEP_RE = /^\d+\.\s+(.+)$/;
190
+ const CHECK_RE = /^[Cc]heck:\s+(.+)$/;
191
+ const META_RE = /^(?:test\s+case|user\s+story)[\s:]/i;
192
+ function parseSummary(docLines, fallbackTitle) {
193
+ let title = '';
194
+ const steps = [];
195
+ for (const line of docLines) {
196
+ if (!line || META_RE.test(line))
197
+ continue;
198
+ const numMatch = NUMBERED_STEP_RE.exec(line);
199
+ if (numMatch) {
200
+ const content = numMatch[1].trim();
201
+ const checkMatch = CHECK_RE.exec(content);
202
+ if (checkMatch) {
203
+ steps.push({ keyword: 'Then', text: checkMatch[1].trim() });
204
+ }
205
+ else {
206
+ steps.push({ keyword: 'Step', text: content });
207
+ }
208
+ continue;
209
+ }
210
+ if (!title)
211
+ title = line;
212
+ }
213
+ return { title: title || fallbackTitle, steps };
214
+ }
215
+ // ─── Public parser ────────────────────────────────────────────────────────────
216
+ function parseSwiftFile(filePath, tagPrefix, linkConfigs) {
217
+ const source = fs.readFileSync(filePath, 'utf8');
218
+ const lines = source.split('\n');
219
+ const fileBaseName = path.basename(filePath).replace(/\.swift$/, '');
220
+ const pathTags = (0, shared_1.extractPathTags)(filePath);
221
+ const results = [];
222
+ for (let i = 0; i < lines.length; i++) {
223
+ const m = lines[i].match(TEST_METHOD_RE);
224
+ if (!m)
225
+ continue;
226
+ const methodName = m[1];
227
+ const methodLineIdx = i;
228
+ const docLines = extractDocBefore(lines, methodLineIdx);
229
+ const { azureId, tags: cTags } = extractCommentMetadataAbove(lines, methodLineIdx, tagPrefix);
230
+ const className = findEnclosingClass(lines, methodLineIdx);
231
+ const allTags = [...new Set([...pathTags, ...cTags])];
232
+ const fallbackTitle = methodNameToTitle(methodName);
233
+ const { title, steps } = parseSummary(docLines, fallbackTitle);
234
+ const automatedTestName = className
235
+ ? [fileBaseName, className, methodName].join(' > ')
236
+ : [fileBaseName, methodName].join(' > ');
237
+ results.push({
238
+ filePath,
239
+ title,
240
+ steps,
241
+ tags: allTags,
242
+ azureId: azureId !== undefined && !isNaN(azureId) ? azureId : undefined,
243
+ line: methodLineIdx + 1,
244
+ linkRefs: (0, shared_1.extractLinkRefs)(allTags, linkConfigs),
245
+ automatedTestName,
246
+ });
247
+ }
248
+ return results;
249
+ }
250
+ //# sourceMappingURL=swift.js.map