@tayo-dev/rtl 1.0.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.
Files changed (150) hide show
  1. package/README.md +250 -0
  2. package/dist/analyzer/mocks/detector.d.ts +59 -0
  3. package/dist/analyzer/mocks/detector.d.ts.map +1 -0
  4. package/dist/analyzer/mocks/detector.js +264 -0
  5. package/dist/analyzer/mocks/detector.js.map +1 -0
  6. package/dist/analyzer/mocks/target-analyzer.d.ts +92 -0
  7. package/dist/analyzer/mocks/target-analyzer.d.ts.map +1 -0
  8. package/dist/analyzer/mocks/target-analyzer.js +305 -0
  9. package/dist/analyzer/mocks/target-analyzer.js.map +1 -0
  10. package/dist/analyzer/visual/element-analyzer.d.ts +44 -0
  11. package/dist/analyzer/visual/element-analyzer.d.ts.map +1 -0
  12. package/dist/analyzer/visual/element-analyzer.js +176 -0
  13. package/dist/analyzer/visual/element-analyzer.js.map +1 -0
  14. package/dist/analyzer/visual/inspector.d.ts +49 -0
  15. package/dist/analyzer/visual/inspector.d.ts.map +1 -0
  16. package/dist/analyzer/visual/inspector.js +109 -0
  17. package/dist/analyzer/visual/inspector.js.map +1 -0
  18. package/dist/cli/commands/generate.d.ts +13 -0
  19. package/dist/cli/commands/generate.d.ts.map +1 -0
  20. package/dist/cli/commands/generate.js +417 -0
  21. package/dist/cli/commands/generate.js.map +1 -0
  22. package/dist/core/generator.d.ts +32 -0
  23. package/dist/core/generator.d.ts.map +1 -0
  24. package/dist/core/generator.js +173 -0
  25. package/dist/core/generator.js.map +1 -0
  26. package/dist/core/js-parser.d.ts +48 -0
  27. package/dist/core/js-parser.d.ts.map +1 -0
  28. package/dist/core/js-parser.js +244 -0
  29. package/dist/core/js-parser.js.map +1 -0
  30. package/dist/core/mock-intelligence.d.ts +14 -0
  31. package/dist/core/mock-intelligence.d.ts.map +1 -0
  32. package/dist/core/mock-intelligence.js +140 -0
  33. package/dist/core/mock-intelligence.js.map +1 -0
  34. package/dist/core/orchestrator.d.ts +49 -0
  35. package/dist/core/orchestrator.d.ts.map +1 -0
  36. package/dist/core/orchestrator.js +315 -0
  37. package/dist/core/orchestrator.js.map +1 -0
  38. package/dist/core/parser.d.ts +9 -0
  39. package/dist/core/parser.d.ts.map +1 -0
  40. package/dist/core/parser.js +120 -0
  41. package/dist/core/parser.js.map +1 -0
  42. package/dist/core/recording-intelligence.d.ts +15 -0
  43. package/dist/core/recording-intelligence.d.ts.map +1 -0
  44. package/dist/core/recording-intelligence.js +178 -0
  45. package/dist/core/recording-intelligence.js.map +1 -0
  46. package/dist/core/resolver.d.ts +58 -0
  47. package/dist/core/resolver.d.ts.map +1 -0
  48. package/dist/core/resolver.js +291 -0
  49. package/dist/core/resolver.js.map +1 -0
  50. package/dist/core/scanner.d.ts +51 -0
  51. package/dist/core/scanner.d.ts.map +1 -0
  52. package/dist/core/scanner.js +310 -0
  53. package/dist/core/scanner.js.map +1 -0
  54. package/dist/core/scorer.d.ts +8 -0
  55. package/dist/core/scorer.d.ts.map +1 -0
  56. package/dist/core/scorer.js +76 -0
  57. package/dist/core/scorer.js.map +1 -0
  58. package/dist/core/validator.d.ts +134 -0
  59. package/dist/core/validator.d.ts.map +1 -0
  60. package/dist/core/validator.js +44 -0
  61. package/dist/core/validator.js.map +1 -0
  62. package/dist/core/verifier.d.ts +10 -0
  63. package/dist/core/verifier.d.ts.map +1 -0
  64. package/dist/core/verifier.js +30 -0
  65. package/dist/core/verifier.js.map +1 -0
  66. package/dist/core/writer.d.ts +15 -0
  67. package/dist/core/writer.d.ts.map +1 -0
  68. package/dist/core/writer.js +43 -0
  69. package/dist/core/writer.js.map +1 -0
  70. package/dist/generator/mocks/builder.d.ts +47 -0
  71. package/dist/generator/mocks/builder.d.ts.map +1 -0
  72. package/dist/generator/mocks/builder.js +335 -0
  73. package/dist/generator/mocks/builder.js.map +1 -0
  74. package/dist/generator/transforms/dialog-transform.d.ts +35 -0
  75. package/dist/generator/transforms/dialog-transform.d.ts.map +1 -0
  76. package/dist/generator/transforms/dialog-transform.js +293 -0
  77. package/dist/generator/transforms/dialog-transform.js.map +1 -0
  78. package/dist/index.d.ts +7 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +18 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/learner/analyzer.d.ts +13 -0
  83. package/dist/learner/analyzer.d.ts.map +1 -0
  84. package/dist/learner/analyzer.js +484 -0
  85. package/dist/learner/analyzer.js.map +1 -0
  86. package/dist/learner/index.d.ts +66 -0
  87. package/dist/learner/index.d.ts.map +1 -0
  88. package/dist/learner/index.js +247 -0
  89. package/dist/learner/index.js.map +1 -0
  90. package/dist/learner/storage.d.ts +68 -0
  91. package/dist/learner/storage.d.ts.map +1 -0
  92. package/dist/learner/storage.js +201 -0
  93. package/dist/learner/storage.js.map +1 -0
  94. package/dist/learner/types.d.ts +41 -0
  95. package/dist/learner/types.d.ts.map +1 -0
  96. package/dist/learner/types.js +31 -0
  97. package/dist/learner/types.js.map +1 -0
  98. package/dist/parser/recorder-parser.d.ts +40 -0
  99. package/dist/parser/recorder-parser.d.ts.map +1 -0
  100. package/dist/parser/recorder-parser.js +139 -0
  101. package/dist/parser/recorder-parser.js.map +1 -0
  102. package/dist/parser/steps/deduplicator.d.ts +19 -0
  103. package/dist/parser/steps/deduplicator.d.ts.map +1 -0
  104. package/dist/parser/steps/deduplicator.js +75 -0
  105. package/dist/parser/steps/deduplicator.js.map +1 -0
  106. package/dist/parser/steps/dialog-detector.d.ts +38 -0
  107. package/dist/parser/steps/dialog-detector.d.ts.map +1 -0
  108. package/dist/parser/steps/dialog-detector.js +290 -0
  109. package/dist/parser/steps/dialog-detector.js.map +1 -0
  110. package/dist/parser/steps/noise-filter.d.ts +21 -0
  111. package/dist/parser/steps/noise-filter.d.ts.map +1 -0
  112. package/dist/parser/steps/noise-filter.js +138 -0
  113. package/dist/parser/steps/noise-filter.js.map +1 -0
  114. package/dist/scorer/index.d.ts +43 -0
  115. package/dist/scorer/index.d.ts.map +1 -0
  116. package/dist/scorer/index.js +82 -0
  117. package/dist/scorer/index.js.map +1 -0
  118. package/dist/scorer/post-verify.d.ts +17 -0
  119. package/dist/scorer/post-verify.d.ts.map +1 -0
  120. package/dist/scorer/post-verify.js +163 -0
  121. package/dist/scorer/post-verify.js.map +1 -0
  122. package/dist/scorer/pre-audit.d.ts +32 -0
  123. package/dist/scorer/pre-audit.d.ts.map +1 -0
  124. package/dist/scorer/pre-audit.js +99 -0
  125. package/dist/scorer/pre-audit.js.map +1 -0
  126. package/dist/scorer/quality-gates.d.ts +17 -0
  127. package/dist/scorer/quality-gates.d.ts.map +1 -0
  128. package/dist/scorer/quality-gates.js +304 -0
  129. package/dist/scorer/quality-gates.js.map +1 -0
  130. package/dist/scorer/types.d.ts +27 -0
  131. package/dist/scorer/types.d.ts.map +1 -0
  132. package/dist/scorer/types.js +5 -0
  133. package/dist/scorer/types.js.map +1 -0
  134. package/dist/templates/test-template.d.ts +21 -0
  135. package/dist/templates/test-template.d.ts.map +1 -0
  136. package/dist/templates/test-template.js +92 -0
  137. package/dist/templates/test-template.js.map +1 -0
  138. package/dist/types/conventions.d.ts +49 -0
  139. package/dist/types/conventions.d.ts.map +1 -0
  140. package/dist/types/conventions.js +13 -0
  141. package/dist/types/conventions.js.map +1 -0
  142. package/dist/types/recording.d.ts +143 -0
  143. package/dist/types/recording.d.ts.map +1 -0
  144. package/dist/types/recording.js +5 -0
  145. package/dist/types/recording.js.map +1 -0
  146. package/dist/types/score.d.ts +18 -0
  147. package/dist/types/score.d.ts.map +1 -0
  148. package/dist/types/score.js +2 -0
  149. package/dist/types/score.js.map +1 -0
  150. package/package.json +51 -0
@@ -0,0 +1,178 @@
1
+ function hasPointerMetadata(step) {
2
+ return [step.x, step.y, step.offsetX, step.offsetY].some((value) => typeof value === 'number');
3
+ }
4
+ function isDoubleClickVariant(step) {
5
+ return /doubleclick|dblclick|tripleclick/i.test(step.originalType);
6
+ }
7
+ function isMovementType(step) {
8
+ return /hover|mousemove|pointermove|movemouse/i.test(step.originalType);
9
+ }
10
+ function isCursorWanderStep(step) {
11
+ if (isMovementType(step)) {
12
+ return true;
13
+ }
14
+ if (step.action === 'unknown' && (hasPointerMetadata(step) || !step.target)) {
15
+ return true;
16
+ }
17
+ return step.action === 'scroll' && !step.target && !step.value;
18
+ }
19
+ function normalizedTarget(target) {
20
+ const trimmed = target?.trim();
21
+ return trimmed ? trimmed : undefined;
22
+ }
23
+ function isSameClickTarget(current, candidate) {
24
+ return (current.action === 'click' &&
25
+ candidate.action === 'click' &&
26
+ normalizedTarget(current.target) !== undefined &&
27
+ normalizedTarget(current.target) === normalizedTarget(candidate.target));
28
+ }
29
+ function pickRepresentativeClick(cluster) {
30
+ return cluster.find((step) => !isDoubleClickVariant(step)) ?? cluster[0];
31
+ }
32
+ function deriveIntentLabel(steps) {
33
+ const navigateStep = steps.find((step) => step.action === 'navigate');
34
+ if (navigateStep) {
35
+ return navigateStep.target ? `navigate to ${navigateStep.target}` : 'navigation flow';
36
+ }
37
+ const submitStep = steps.find((step) => step.action === 'click' &&
38
+ /save|submit|confirm|continue|done|create|update/i.test(step.target ?? ''));
39
+ if (submitStep?.target) {
40
+ return `submit ${submitStep.target}`;
41
+ }
42
+ const fillStep = steps.find((step) => step.action === 'fill' || step.action === 'select');
43
+ if (fillStep?.target) {
44
+ return `edit ${fillStep.target}`;
45
+ }
46
+ const clickStep = steps.find((step) => step.action === 'click');
47
+ if (clickStep?.target && steps.some((step) => step.action === 'assert')) {
48
+ return `confirm ${clickStep.target}`;
49
+ }
50
+ if (clickStep?.target) {
51
+ return `interact with ${clickStep.target}`;
52
+ }
53
+ return 'recorded flow';
54
+ }
55
+ function isDialogLikeText(value) {
56
+ return /dialog|modal|drawer|sheet|popover/i.test(value ?? '');
57
+ }
58
+ function findGroupSelector(group) {
59
+ return group.steps.find((step) => step.action !== 'navigate' && step.target)?.target;
60
+ }
61
+ export function inferIntentGroups(steps) {
62
+ if (steps.length === 0) {
63
+ return [];
64
+ }
65
+ const groups = [];
66
+ let currentGroup = [];
67
+ const flushGroup = () => {
68
+ if (currentGroup.length === 0) {
69
+ return;
70
+ }
71
+ groups.push({
72
+ name: deriveIntentLabel(currentGroup),
73
+ steps: [...currentGroup],
74
+ });
75
+ currentGroup = [];
76
+ };
77
+ for (const step of steps) {
78
+ if (step.action === 'navigate') {
79
+ flushGroup();
80
+ currentGroup = [step];
81
+ continue;
82
+ }
83
+ if (currentGroup.length === 1 && currentGroup[0]?.action === 'navigate') {
84
+ flushGroup();
85
+ }
86
+ currentGroup.push(step);
87
+ if (step.action === 'assert') {
88
+ flushGroup();
89
+ }
90
+ }
91
+ flushGroup();
92
+ return groups;
93
+ }
94
+ export function findVisualCaptureCandidates(analyzedRecording) {
95
+ return analyzedRecording.intentGroups.flatMap((group) => {
96
+ const joinedTargets = group.steps
97
+ .map((step) => step.target ?? '')
98
+ .join(' ');
99
+ const hasDialogState = isDialogLikeText(group.name) ||
100
+ isDialogLikeText(joinedTargets) ||
101
+ group.steps.some((step) => step.action === 'assert' &&
102
+ /open|confirm|add|dialog|modal/i.test(step.target ?? ''));
103
+ if (!hasDialogState) {
104
+ return [];
105
+ }
106
+ return [
107
+ {
108
+ groupName: group.name,
109
+ reason: 'dialog-state',
110
+ selector: findGroupSelector(group),
111
+ },
112
+ ];
113
+ });
114
+ }
115
+ export function filterNoiseSteps(steps) {
116
+ let removedRedundantClicks = 0;
117
+ let removedDoubleClickNoise = 0;
118
+ let removedCursorWander = 0;
119
+ const filtered = [];
120
+ for (let index = 0; index < steps.length; index += 1) {
121
+ const step = steps[index];
122
+ if (isCursorWanderStep(step)) {
123
+ removedCursorWander += 1;
124
+ continue;
125
+ }
126
+ if (step.action !== 'click' || !normalizedTarget(step.target)) {
127
+ filtered.push(step);
128
+ continue;
129
+ }
130
+ const cluster = [step];
131
+ for (let nextIndex = index + 1; nextIndex < steps.length; nextIndex += 1) {
132
+ const candidate = steps[nextIndex];
133
+ if (isCursorWanderStep(candidate)) {
134
+ removedCursorWander += 1;
135
+ index = nextIndex;
136
+ continue;
137
+ }
138
+ if (!isSameClickTarget(step, candidate)) {
139
+ break;
140
+ }
141
+ cluster.push(candidate);
142
+ index = nextIndex;
143
+ }
144
+ const extraClicks = cluster.length - 1;
145
+ if (extraClicks > 0) {
146
+ const removedDoubleClicks = cluster
147
+ .slice(1)
148
+ .filter((candidate) => isDoubleClickVariant(candidate)).length;
149
+ removedDoubleClickNoise += removedDoubleClicks;
150
+ removedRedundantClicks += extraClicks - removedDoubleClicks;
151
+ }
152
+ filtered.push(pickRepresentativeClick(cluster));
153
+ }
154
+ return {
155
+ steps: filtered,
156
+ diagnostics: {
157
+ removedCursorWander,
158
+ removedDoubleClickNoise,
159
+ removedRedundantClicks,
160
+ },
161
+ };
162
+ }
163
+ export function analyzeRecording(recording) {
164
+ const filtered = filterNoiseSteps(recording.steps);
165
+ const intentGroups = inferIntentGroups(filtered.steps);
166
+ return {
167
+ ...recording,
168
+ steps: filtered.steps,
169
+ diagnostics: {
170
+ ...filtered.diagnostics,
171
+ rawStepCount: recording.rawStepCount,
172
+ filteredStepCount: filtered.steps.length,
173
+ intentGroupCount: intentGroups.length,
174
+ },
175
+ intentGroups,
176
+ };
177
+ }
178
+ //# sourceMappingURL=recording-intelligence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recording-intelligence.js","sourceRoot":"","sources":["../../src/core/recording-intelligence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { Page } from 'playwright';
2
+ import type { DialogState, ElementInfo, QueryResult, VisualState } from '../types/recording.js';
3
+ export declare function extractDialogState(page: Page): Promise<DialogState | null>;
4
+ export interface CaptureVisualStateOptions {
5
+ reason: string;
6
+ screenshotDir?: string;
7
+ selector?: string;
8
+ timeoutMs?: number;
9
+ }
10
+ /**
11
+ * Captures a structured visual-state artifact for a page and optional selector.
12
+ */
13
+ export declare function captureVisualState(url: string, options: CaptureVisualStateOptions): Promise<VisualState | null>;
14
+ /**
15
+ * Builds the highest-priority RTL query for an element based on its accessibility properties.
16
+ * Priority: getByRole > getByLabelText > getByText > getByPlaceholderText > getByTestId
17
+ *
18
+ * @param info - Element information from DOM inspection
19
+ * @param selector - Original CSS selector
20
+ * @returns QueryResult with query string, quality rating, and method name
21
+ */
22
+ export declare function buildQuery(info: ElementInfo, selector: string): QueryResult;
23
+ /**
24
+ * Selects the most appropriate RTL matcher based on element type and action.
25
+ *
26
+ * @param info - Element information from DOM inspection
27
+ * @param action - The action being performed (fill, assert, etc.)
28
+ * @returns Matcher string (e.g., '.toHaveValue()', '.toBeChecked()')
29
+ */
30
+ export declare function selectMatcher(info: ElementInfo, action: string): string;
31
+ /**
32
+ * Inspects a single element on a page using Playwright.
33
+ * Launches headless Chromium, navigates to URL, evaluates element.
34
+ *
35
+ * @param url - URL to navigate to
36
+ * @param cssSelector - CSS selector to locate element
37
+ * @param timeoutMs - Timeout for navigation (default 5000ms)
38
+ * @returns ElementInfo or null if element not found/error occurs
39
+ */
40
+ export declare function inspectElement(url: string, cssSelector: string, timeoutMs?: number): Promise<ElementInfo | null>;
41
+ /**
42
+ * Inspects multiple elements on a page using a single Playwright browser instance.
43
+ * More efficient than calling inspectElement multiple times.
44
+ *
45
+ * @param url - URL to navigate to
46
+ * @param selectors - Array of CSS selectors to locate elements
47
+ * @param timeoutMs - Timeout for navigation (default 5000ms)
48
+ * @returns Map of selector to ElementInfo (or null if not found)
49
+ */
50
+ export declare function inspectElements(url: string, selectors: string[], timeoutMs?: number): Promise<Map<string, ElementInfo | null>>;
51
+ /**
52
+ * Emits a warning for fragile queries (getByTestId fallback).
53
+ * Should be called when buildQuery returns method: 'getByTestId'.
54
+ *
55
+ * @param selector - The CSS selector that required fallback to testId
56
+ */
57
+ export declare function emitQry03Warning(selector: string): void;
58
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,IAAI,EAAE,MAAM,YAAY,CAAA;AAEpD,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,WAAW,EAEX,WAAW,EACZ,MAAM,uBAAuB,CAAA;AA4D9B,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA8BhF;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA6C7B;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CA+C3E;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAuBvE;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,SAAS,SAAO,GACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAyB7B;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EAAE,EACnB,SAAS,SAAO,GACf,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC,CAsC1C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAMvD"}
@@ -0,0 +1,291 @@
1
+ import { chromium } from 'playwright';
2
+ import pc from 'picocolors';
3
+ /**
4
+ * Maps HTML tag names to implied ARIA roles.
5
+ * Used by buildQuery to determine accessible query method.
6
+ */
7
+ const ROLE_MAP = {
8
+ button: 'button',
9
+ a: 'link',
10
+ input: 'textbox',
11
+ select: 'combobox',
12
+ textarea: 'textbox',
13
+ h1: 'heading',
14
+ h2: 'heading',
15
+ h3: 'heading',
16
+ h4: 'heading',
17
+ h5: 'heading',
18
+ h6: 'heading',
19
+ img: 'img',
20
+ };
21
+ /**
22
+ * Escapes single quotes in strings for use in generated query code.
23
+ */
24
+ function escapeSingleQuote(str) {
25
+ return str.replace(/'/g, "\\'");
26
+ }
27
+ /**
28
+ * Sanitizes a CSS selector to be used as a testId.
29
+ * Replaces non-alphanumeric characters with hyphens and trims leading/trailing hyphens.
30
+ */
31
+ function sanitizeSelectorForTestId(selector) {
32
+ return selector.replace(/[^a-zA-Z0-9-]/g, '-').replace(/^-+|-+$/g, '');
33
+ }
34
+ async function readElementInfo(page, selector) {
35
+ const locator = page.locator(selector).first();
36
+ const elementInfo = await locator.evaluate((el) => {
37
+ const htmlEl = el;
38
+ return {
39
+ tagName: el.tagName.toLowerCase(),
40
+ role: el.getAttribute('role') ?? null,
41
+ ariaLabel: el.getAttribute('aria-label') ?? null,
42
+ ariaLabelledBy: el.getAttribute('aria-labelledby') ?? null,
43
+ innerText: htmlEl.innerText ?? '',
44
+ value: htmlEl.value ?? undefined,
45
+ type: htmlEl.type ?? undefined,
46
+ placeholder: htmlEl.placeholder ?? null,
47
+ isPresent: true,
48
+ };
49
+ });
50
+ return elementInfo;
51
+ }
52
+ function sanitizeCaptureSegment(value) {
53
+ return value.replace(/[^a-zA-Z0-9-_]+/g, '-').replace(/^-+|-+$/g, '') || 'capture';
54
+ }
55
+ export async function extractDialogState(page) {
56
+ try {
57
+ const state = await page.evaluate(() => {
58
+ const dialog = document.querySelector('[role="dialog"], [role="alertdialog"]');
59
+ if (!dialog) {
60
+ return null;
61
+ }
62
+ const titleNode = dialog.querySelector('h1, h2, h3, [aria-labelledby]');
63
+ const descriptionNode = dialog.querySelector('[aria-describedby], p');
64
+ const actionNodes = Array.from(dialog.querySelectorAll('button, [role="button"]'));
65
+ return {
66
+ role: dialog.getAttribute('role') ?? null,
67
+ title: titleNode?.textContent?.trim() ?? null,
68
+ description: descriptionNode?.textContent?.trim() ?? null,
69
+ actions: actionNodes
70
+ .map((node) => node.innerText?.trim())
71
+ .filter((text) => Boolean(text)),
72
+ isOpen: true,
73
+ };
74
+ });
75
+ return state;
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ /**
82
+ * Captures a structured visual-state artifact for a page and optional selector.
83
+ */
84
+ export async function captureVisualState(url, options) {
85
+ const { reason, screenshotDir, selector, timeoutMs = 5000 } = options;
86
+ let browser = null;
87
+ try {
88
+ browser = await chromium.launch({ headless: true });
89
+ const page = await browser.newPage();
90
+ await page.goto(url, {
91
+ timeout: timeoutMs,
92
+ waitUntil: 'domcontentloaded',
93
+ });
94
+ const pageTitle = await page.title();
95
+ const dialog = await extractDialogState(page);
96
+ const element = selector ? await readElementInfo(page, selector) : null;
97
+ let screenshotPath;
98
+ if (screenshotDir) {
99
+ screenshotPath = `${screenshotDir}/${sanitizeCaptureSegment(pageTitle || reason)}.png`;
100
+ await page.screenshot({ path: screenshotPath, fullPage: true });
101
+ }
102
+ return {
103
+ capturedAt: new Date().toISOString(),
104
+ dialog,
105
+ element,
106
+ pageTitle,
107
+ reason,
108
+ screenshotPath,
109
+ selector,
110
+ url,
111
+ };
112
+ }
113
+ catch (error) {
114
+ console.warn(pc.yellow('[taro]') +
115
+ pc.dim(' VIS-01:') +
116
+ ` Failed to capture visual state for ${url}: ${error instanceof Error ? error.message : 'Unknown error'}`);
117
+ return null;
118
+ }
119
+ finally {
120
+ if (browser) {
121
+ await browser.close();
122
+ }
123
+ }
124
+ }
125
+ /**
126
+ * Builds the highest-priority RTL query for an element based on its accessibility properties.
127
+ * Priority: getByRole > getByLabelText > getByText > getByPlaceholderText > getByTestId
128
+ *
129
+ * @param info - Element information from DOM inspection
130
+ * @param selector - Original CSS selector
131
+ * @returns QueryResult with query string, quality rating, and method name
132
+ */
133
+ export function buildQuery(info, selector) {
134
+ const impliedRole = info.role ?? ROLE_MAP[info.tagName];
135
+ const accessibleName = info.ariaLabel ?? info.innerText;
136
+ // Priority 1: getByRole when both role and accessible name exist
137
+ if (impliedRole && accessibleName) {
138
+ return {
139
+ method: 'getByRole',
140
+ quality: 'excellent',
141
+ query: `screen.getByRole('${impliedRole}', { name: '${escapeSingleQuote(accessibleName)}' })`,
142
+ };
143
+ }
144
+ // Priority 2: getByLabelText when ariaLabel exists (no role match)
145
+ if (info.ariaLabel) {
146
+ return {
147
+ method: 'getByLabelText',
148
+ quality: 'excellent',
149
+ query: `screen.getByLabelText('${escapeSingleQuote(info.ariaLabel)}')`,
150
+ };
151
+ }
152
+ // Priority 3: getByText when innerText exists
153
+ if (info.innerText) {
154
+ return {
155
+ method: 'getByText',
156
+ quality: 'good',
157
+ query: `screen.getByText('${escapeSingleQuote(info.innerText)}')`,
158
+ };
159
+ }
160
+ // Priority 4: getByPlaceholderText when placeholder exists
161
+ if (info.placeholder) {
162
+ return {
163
+ method: 'getByPlaceholderText',
164
+ quality: 'acceptable',
165
+ query: `screen.getByPlaceholderText('${escapeSingleQuote(info.placeholder)}')`,
166
+ };
167
+ }
168
+ // Priority 5: Fallback to getByTestId (fragile)
169
+ const sanitized = sanitizeSelectorForTestId(selector);
170
+ return {
171
+ method: 'getByTestId',
172
+ quality: 'fragile',
173
+ query: `screen.getByTestId('${sanitized}')`,
174
+ };
175
+ }
176
+ /**
177
+ * Selects the most appropriate RTL matcher based on element type and action.
178
+ *
179
+ * @param info - Element information from DOM inspection
180
+ * @param action - The action being performed (fill, assert, etc.)
181
+ * @returns Matcher string (e.g., '.toHaveValue()', '.toBeChecked()')
182
+ */
183
+ export function selectMatcher(info, action) {
184
+ // checkbox → toBeChecked
185
+ if (info.type === 'checkbox') {
186
+ return '.toBeChecked()';
187
+ }
188
+ // fill with value → toHaveValue
189
+ if (info.value !== undefined && action === 'fill') {
190
+ return `.toHaveValue('${escapeSingleQuote(info.value)}')`;
191
+ }
192
+ // assert with innerText → toHaveTextContent
193
+ if (action === 'assert' && info.innerText) {
194
+ return `.toHaveTextContent('${escapeSingleQuote(info.innerText)}')`;
195
+ }
196
+ // dialog → toBeVisible
197
+ if (action === 'assert' && info.role === 'dialog') {
198
+ return '.toBeVisible()';
199
+ }
200
+ // Default → toBeInTheDocument
201
+ return '.toBeInTheDocument()';
202
+ }
203
+ /**
204
+ * Inspects a single element on a page using Playwright.
205
+ * Launches headless Chromium, navigates to URL, evaluates element.
206
+ *
207
+ * @param url - URL to navigate to
208
+ * @param cssSelector - CSS selector to locate element
209
+ * @param timeoutMs - Timeout for navigation (default 5000ms)
210
+ * @returns ElementInfo or null if element not found/error occurs
211
+ */
212
+ export async function inspectElement(url, cssSelector, timeoutMs = 5000) {
213
+ let browser = null;
214
+ try {
215
+ browser = await chromium.launch({ headless: true });
216
+ const page = await browser.newPage();
217
+ await page.goto(url, {
218
+ timeout: timeoutMs,
219
+ waitUntil: 'domcontentloaded',
220
+ });
221
+ return await readElementInfo(page, cssSelector);
222
+ }
223
+ catch (error) {
224
+ console.warn(pc.yellow('[taro]') +
225
+ pc.dim(' QRY-02:') +
226
+ ` Failed to inspect element ${cssSelector} on ${url}: ${error instanceof Error ? error.message : 'Unknown error'}`);
227
+ return null;
228
+ }
229
+ finally {
230
+ if (browser) {
231
+ await browser.close();
232
+ }
233
+ }
234
+ }
235
+ /**
236
+ * Inspects multiple elements on a page using a single Playwright browser instance.
237
+ * More efficient than calling inspectElement multiple times.
238
+ *
239
+ * @param url - URL to navigate to
240
+ * @param selectors - Array of CSS selectors to locate elements
241
+ * @param timeoutMs - Timeout for navigation (default 5000ms)
242
+ * @returns Map of selector to ElementInfo (or null if not found)
243
+ */
244
+ export async function inspectElements(url, selectors, timeoutMs = 5000) {
245
+ const result = new Map();
246
+ let browser = null;
247
+ try {
248
+ browser = await chromium.launch({ headless: true });
249
+ const page = await browser.newPage();
250
+ await page.goto(url, {
251
+ timeout: timeoutMs,
252
+ waitUntil: 'domcontentloaded',
253
+ });
254
+ for (const selector of selectors) {
255
+ try {
256
+ result.set(selector, await readElementInfo(page, selector));
257
+ }
258
+ catch {
259
+ // On individual selector failure, set to null and continue
260
+ result.set(selector, null);
261
+ }
262
+ }
263
+ }
264
+ catch (error) {
265
+ // On browser/page error, set all selectors to null
266
+ console.warn(pc.yellow('[taro]') +
267
+ pc.dim(' QRY-02:') +
268
+ ` Failed to inspect elements on ${url}: ${error instanceof Error ? error.message : 'Unknown error'}`);
269
+ for (const selector of selectors) {
270
+ result.set(selector, null);
271
+ }
272
+ }
273
+ finally {
274
+ if (browser) {
275
+ await browser.close();
276
+ }
277
+ }
278
+ return result;
279
+ }
280
+ /**
281
+ * Emits a warning for fragile queries (getByTestId fallback).
282
+ * Should be called when buildQuery returns method: 'getByTestId'.
283
+ *
284
+ * @param selector - The CSS selector that required fallback to testId
285
+ */
286
+ export function emitQry03Warning(selector) {
287
+ console.warn(pc.yellow('[taro]') +
288
+ pc.dim(' QRY-03:') +
289
+ ` No accessible query for ${pc.bold(selector)} — consider adding aria-label or data-testid to this element`);
290
+ }
291
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Codebase convention scanner
3
+ * Scans project for test file conventions and persists to .taro/conventions.json
4
+ */
5
+ import type { ConventionsSchema, ConventionFile } from '../types/conventions.js';
6
+ /**
7
+ * Recursively find all test files in a directory
8
+ * @param root - Root directory to scan
9
+ * @returns Array of absolute paths to test files
10
+ */
11
+ export declare function findTestFiles(root: string): Promise<string[]>;
12
+ export interface TestFileContent {
13
+ path: string;
14
+ content: string;
15
+ }
16
+ /**
17
+ * Load discovered test files with content for downstream analyzers.
18
+ */
19
+ export declare function readTestFiles(root: string): Promise<TestFileContent[]>;
20
+ /**
21
+ * Derive conventions from analyzed files
22
+ * @param files - Array of analyzed ConventionFile objects
23
+ * @param projectRoot - Root directory of the project
24
+ * @returns ConventionsSchema with derived conventions
25
+ */
26
+ export declare function deriveConventions(files: ConventionFile[], projectRoot: string): ConventionsSchema;
27
+ /**
28
+ * Read conventions from .taro/conventions.json
29
+ * @param projectRoot - Root directory of the project
30
+ * @returns ConventionsSchema or null if not found
31
+ */
32
+ export declare function readConventions(projectRoot: string): Promise<ConventionsSchema | null>;
33
+ /**
34
+ * Scan project for test conventions
35
+ * @param projectRoot - Root directory of the project
36
+ * @returns ConventionsSchema with detected conventions
37
+ */
38
+ export declare function scanConventions(projectRoot: string): Promise<ConventionsSchema>;
39
+ /**
40
+ * Persist conventions to .taro/conventions.json
41
+ */
42
+ export declare function persistConventions(projectRoot: string, conventions: ConventionsSchema): Promise<void>;
43
+ /**
44
+ * Merge new file conventions into the persisted conventions store.
45
+ */
46
+ export declare function mergeConventions(projectRoot: string, newPatterns: ConventionFile): Promise<void>;
47
+ /**
48
+ * Analyze a single test file without rescanning the whole project.
49
+ */
50
+ export declare function analyzeSingleTestFile(projectRoot: string, filePath: string): Promise<ConventionFile>;
51
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/core/scanner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAA4B,MAAM,yBAAyB,CAAA;AAc1G;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA2BnE;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAc5E;AAoED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EAAE,EACvB,WAAW,EAAE,MAAM,GAClB,iBAAiB,CAuCnB;AAgED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAWnC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAgD5B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,iBAAiB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,cAAc,GAC1B,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CAMzB"}