playwright-mimic 0.1.0 → 0.1.2

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 (118) hide show
  1. package/README.md +695 -446
  2. package/dist/agentic/agent.d.ts +106 -0
  3. package/dist/agentic/agent.d.ts.map +1 -0
  4. package/dist/agentic/agent.js +528 -0
  5. package/dist/agentic/agent.js.map +1 -0
  6. package/dist/agentic/index.d.ts +13 -0
  7. package/dist/agentic/index.d.ts.map +1 -0
  8. package/dist/agentic/index.js +12 -0
  9. package/dist/agentic/index.js.map +1 -0
  10. package/dist/agentic/planner.d.ts +41 -0
  11. package/dist/agentic/planner.d.ts.map +1 -0
  12. package/dist/agentic/planner.js +136 -0
  13. package/dist/agentic/planner.js.map +1 -0
  14. package/dist/agentic/react.d.ts +35 -0
  15. package/dist/agentic/react.d.ts.map +1 -0
  16. package/dist/agentic/react.js +170 -0
  17. package/dist/agentic/react.js.map +1 -0
  18. package/dist/agentic/recovery.d.ts +55 -0
  19. package/dist/agentic/recovery.d.ts.map +1 -0
  20. package/dist/agentic/recovery.js +200 -0
  21. package/dist/agentic/recovery.js.map +1 -0
  22. package/dist/agentic/reflection.d.ts +40 -0
  23. package/dist/agentic/reflection.d.ts.map +1 -0
  24. package/dist/agentic/reflection.js +142 -0
  25. package/dist/agentic/reflection.js.map +1 -0
  26. package/dist/agentic/types.d.ts +177 -0
  27. package/dist/agentic/types.d.ts.map +1 -0
  28. package/dist/agentic/types.js +8 -0
  29. package/dist/agentic/types.js.map +1 -0
  30. package/dist/agentic/wait.d.ts +50 -0
  31. package/dist/agentic/wait.d.ts.map +1 -0
  32. package/dist/agentic/wait.js +140 -0
  33. package/dist/agentic/wait.js.map +1 -0
  34. package/dist/agentic-mimic.d.ts +56 -0
  35. package/dist/agentic-mimic.d.ts.map +1 -0
  36. package/dist/agentic-mimic.js +98 -0
  37. package/dist/agentic-mimic.js.map +1 -0
  38. package/dist/index.d.ts +8 -8
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +9 -9
  41. package/dist/index.js.map +1 -1
  42. package/dist/mimic/actionType.d.ts +7 -0
  43. package/dist/mimic/actionType.d.ts.map +1 -0
  44. package/dist/mimic/actionType.js +44 -0
  45. package/dist/mimic/actionType.js.map +1 -0
  46. package/dist/mimic/annotations.d.ts +21 -0
  47. package/dist/mimic/annotations.d.ts.map +1 -0
  48. package/dist/mimic/annotations.js +36 -0
  49. package/dist/mimic/annotations.js.map +1 -0
  50. package/dist/mimic/cli.d.ts +15 -0
  51. package/dist/mimic/cli.d.ts.map +1 -0
  52. package/dist/mimic/cli.js +17 -0
  53. package/dist/mimic/cli.js.map +1 -0
  54. package/dist/mimic/click.d.ts +39 -0
  55. package/dist/mimic/click.d.ts.map +1 -0
  56. package/dist/mimic/click.js +348 -0
  57. package/dist/mimic/click.js.map +1 -0
  58. package/dist/mimic/forms.d.ts +52 -0
  59. package/dist/mimic/forms.d.ts.map +1 -0
  60. package/dist/mimic/forms.js +511 -0
  61. package/dist/mimic/forms.js.map +1 -0
  62. package/dist/mimic/markers.d.ts +133 -0
  63. package/dist/mimic/markers.d.ts.map +1 -0
  64. package/dist/mimic/markers.js +589 -0
  65. package/dist/mimic/markers.js.map +1 -0
  66. package/dist/mimic/navigation.d.ts +19 -0
  67. package/dist/mimic/navigation.d.ts.map +1 -0
  68. package/dist/mimic/navigation.js +136 -0
  69. package/dist/mimic/navigation.js.map +1 -0
  70. package/dist/mimic/playwrightCodeGenerator.d.ts +55 -0
  71. package/dist/mimic/playwrightCodeGenerator.d.ts.map +1 -0
  72. package/dist/mimic/playwrightCodeGenerator.js +270 -0
  73. package/dist/mimic/playwrightCodeGenerator.js.map +1 -0
  74. package/dist/mimic/replay.d.ts +21 -0
  75. package/dist/mimic/replay.d.ts.map +1 -0
  76. package/dist/mimic/replay.js +142 -0
  77. package/dist/mimic/replay.js.map +1 -0
  78. package/dist/mimic/schema/action.d.ts +315 -0
  79. package/dist/mimic/schema/action.d.ts.map +1 -0
  80. package/dist/mimic/schema/action.js +186 -0
  81. package/dist/mimic/schema/action.js.map +1 -0
  82. package/dist/mimic/selector.d.ts +143 -0
  83. package/dist/mimic/selector.d.ts.map +1 -0
  84. package/dist/mimic/selector.js +1515 -0
  85. package/dist/mimic/selector.js.map +1 -0
  86. package/dist/mimic/selectorDescriptor.d.ts +25 -0
  87. package/dist/mimic/selectorDescriptor.d.ts.map +1 -0
  88. package/dist/mimic/selectorDescriptor.js +32 -0
  89. package/dist/mimic/selectorDescriptor.js.map +1 -0
  90. package/dist/mimic/selectorSerialization.d.ts +18 -0
  91. package/dist/mimic/selectorSerialization.d.ts.map +1 -0
  92. package/dist/mimic/selectorSerialization.js +32 -0
  93. package/dist/mimic/selectorSerialization.js.map +1 -0
  94. package/dist/mimic/selectorTypes.d.ts +122 -0
  95. package/dist/mimic/selectorTypes.d.ts.map +1 -0
  96. package/dist/mimic/selectorTypes.js +2 -0
  97. package/dist/mimic/selectorTypes.js.map +1 -0
  98. package/dist/mimic/selectorUtils.d.ts +52 -0
  99. package/dist/mimic/selectorUtils.d.ts.map +1 -0
  100. package/dist/mimic/selectorUtils.js +251 -0
  101. package/dist/mimic/selectorUtils.js.map +1 -0
  102. package/dist/mimic/storage.d.ts +110 -0
  103. package/dist/mimic/storage.d.ts.map +1 -0
  104. package/dist/mimic/storage.js +409 -0
  105. package/dist/mimic/storage.js.map +1 -0
  106. package/dist/mimic/types.d.ts +85 -0
  107. package/dist/mimic/types.d.ts.map +1 -0
  108. package/dist/mimic/types.js +7 -0
  109. package/dist/mimic/types.js.map +1 -0
  110. package/dist/mimic.d.ts +29 -4
  111. package/dist/mimic.d.ts.map +1 -1
  112. package/dist/mimic.js +530 -32
  113. package/dist/mimic.js.map +1 -1
  114. package/dist/mimicry.d.ts +4 -4
  115. package/dist/mimicry.d.ts.map +1 -1
  116. package/dist/mimicry.js +22 -13
  117. package/dist/mimicry.js.map +1 -1
  118. package/package.json +30 -6
@@ -0,0 +1,136 @@
1
+ import { generateText, Output } from 'ai';
2
+ import { zNavigationAction, } from './schema/action.js';
3
+ import { countTokens } from '../utils/token-counter.js';
4
+ import { addAnnotation } from './annotations.js';
5
+ import { generateNavigationCode } from './playwrightCodeGenerator.js';
6
+ export const getNavigationAction = async (_page, brain, action, testContext) => {
7
+ // Build context description for the prompt
8
+ const contextDescription = testContext ? `
9
+ **Test Context:**
10
+ - Current URL: ${testContext.currentState.url}
11
+ - Current Page Title: ${testContext.currentState.pageTitle}
12
+ - Step ${testContext.currentStepIndex + 1} of ${testContext.totalSteps}
13
+ ${testContext.previousSteps.length > 0 ? `
14
+ **Previous Steps Executed:**
15
+ ${testContext.previousSteps.map((prevStep, idx) => `${idx + 1}. Step ${prevStep.stepIndex + 1}: "${prevStep.stepText}" (${prevStep.actionKind}${prevStep.url ? ` → ${prevStep.url}` : ''})`).join('\n')}
16
+ ` : ''}
17
+ ` : '';
18
+ const res = await generateText({
19
+ model: brain,
20
+ maxRetries: 3,
21
+ prompt: `You are an expert in converting Gherkin test steps into structured browser automation action objects using Playwright.
22
+
23
+ Your task is to process a single Gherkin step and determine whether it represents a **navigation** action. this can be any of the following:
24
+ - navigate to a page (this requires a url, if no url is provided, go for an option below)
25
+ - closePage: close the current page
26
+ - goBack: go back to the previous page, or navigate back in the browser history
27
+ - goForward: go forward to the next page, or navigate forward in the browser history
28
+ - refresh: refresh the current page, or reload the page
29
+
30
+ ${contextDescription}
31
+ **Input Gherkin step:** ${action}
32
+
33
+ **Instructions:**
34
+ 1. Determine the navigation type and extract the URL if applicable
35
+ 2. For navigate/openPage actions, determine if the step indicates opening in a new window/tab:
36
+ - If the step mentions "new window", "new tab", "open in new", "in a new page", or similar phrases, set newWindow: true
37
+ - Otherwise, set newWindow: false or omit it (defaults to false)
38
+ 3. Provide a clear, human-readable description of what navigation is happening
39
+ - For navigate/openPage: "Navigate to [page name or URL]" (e.g., "Navigate to login page", "Navigate to https://example.com")
40
+ - For navigate/openPage with newWindow: "Navigate to [page name or URL] in new window/tab" (e.g., "Navigate to login page in new window")
41
+ - Do not hallucinate the domain, if none are mentioned, just pass the uri (e.g., "/login")
42
+ - For goBack: "Go back to previous page in browser history" (the system will add the specific URL information)
43
+ - For goForward: "Go forward to next page in browser history" (the system will add the specific URL information)
44
+ - For refresh: "Refresh the current page" (the system will add the specific URL information)
45
+ - For closePage: "Close the current browser page/tab" (the system will add the specific URL information)
46
+
47
+ `,
48
+ output: Output.object({ schema: zNavigationAction, name: 'navigation' }),
49
+ });
50
+ await countTokens(res);
51
+ return res.output;
52
+ };
53
+ /**
54
+ * Execute a navigation action on the page with plain English annotation
55
+ *
56
+ * This function performs browser navigation actions (navigate, go back, refresh, etc.)
57
+ * and adds test annotations for better traceability and validation.
58
+ *
59
+ * @param page - Playwright Page object to perform navigation on
60
+ * @param navigationAction - Navigation action containing type, parameters, and description
61
+ * @param testInfo - Playwright TestInfo for adding annotations (optional)
62
+ * @param gherkinStep - The original Gherkin step for annotation type (optional)
63
+ * @returns Promise that resolves to the navigation action (for snapshot storage)
64
+ */
65
+ export const executeNavigationAction = async (page, navigationAction, testInfo, gherkinStep) => {
66
+ // Use LLM-generated description or build a default one
67
+ const actionDescription = navigationAction.description || 'navigation action';
68
+ // Generate Playwright code equivalent
69
+ const playwrightCode = generateNavigationCode(navigationAction.type, navigationAction.params.url ?? undefined, navigationAction.params.newWindow);
70
+ switch (navigationAction.type) {
71
+ case 'openPage':
72
+ case 'navigate':
73
+ // Check if we need to open in a new window/tab
74
+ if (navigationAction.params.newWindow) {
75
+ // Create a new page in the same browser context
76
+ const context = page.context();
77
+ const newPage = await context.newPage();
78
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} in new window/tab and waiting for page to load completely`, playwrightCode);
79
+ await newPage.goto(navigationAction.params.url, { waitUntil: 'networkidle' });
80
+ // Note: The new page is created and navigated, but the original page reference remains unchanged
81
+ // The new page is available in the browser context and can be accessed via context.pages()
82
+ }
83
+ else {
84
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} and waiting for page to load completely`, playwrightCode);
85
+ await page.goto(navigationAction.params.url, { waitUntil: 'networkidle' });
86
+ }
87
+ break;
88
+ case 'closePage':
89
+ // Only close page if explicitly requested - be very careful with this action
90
+ // Check if page is still open before closing
91
+ if (page.isClosed()) {
92
+ addAnnotation(testInfo, gherkinStep, `→ Page is already closed, cannot close again`, playwrightCode);
93
+ return navigationAction;
94
+ }
95
+ // Capture current URL for better traceability
96
+ const currentUrlBeforeClose = page.url();
97
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} (closing page at ${currentUrlBeforeClose})`, playwrightCode);
98
+ await page.close();
99
+ break;
100
+ case 'goBack':
101
+ // Capture current URL before going back for better traceability
102
+ const currentUrlBeforeBack = page.url();
103
+ await page.goBack();
104
+ try {
105
+ const urlAfterBack = page.url();
106
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} (from ${currentUrlBeforeBack} to ${urlAfterBack})`, playwrightCode);
107
+ }
108
+ catch {
109
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} (from ${currentUrlBeforeBack})`, playwrightCode);
110
+ }
111
+ break;
112
+ case 'goForward':
113
+ // Capture current URL before going forward for better traceability
114
+ const currentUrlBeforeForward = page.url();
115
+ await page.goForward();
116
+ try {
117
+ const urlAfterForward = page.url();
118
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} (from ${currentUrlBeforeForward} to ${urlAfterForward})`, playwrightCode);
119
+ }
120
+ catch {
121
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} (from ${currentUrlBeforeForward})`, playwrightCode);
122
+ }
123
+ break;
124
+ case 'refresh':
125
+ // Capture current URL for better traceability
126
+ const currentUrlBeforeRefresh = page.url();
127
+ addAnnotation(testInfo, gherkinStep, `→ ${actionDescription} to reload all content (refreshing ${currentUrlBeforeRefresh})`, playwrightCode);
128
+ await page.reload();
129
+ break;
130
+ default:
131
+ throw new Error(`Unknown navigation action type: ${navigationAction.type}`);
132
+ }
133
+ // Return the action for snapshot storage
134
+ return navigationAction;
135
+ };
136
+ //# sourceMappingURL=navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/mimic/navigation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Playwright Code Generator
3
+ *
4
+ * Converts SelectorDescriptor and action information into equivalent Playwright code strings
5
+ * for test annotations and documentation purposes.
6
+ */
7
+ import type { SelectorDescriptor } from './selectorTypes.js';
8
+ /**
9
+ * Convert a SelectorDescriptor to a Playwright code string
10
+ *
11
+ * Generates the equivalent Playwright locator code that would be used to select
12
+ * the element described by the SelectorDescriptor.
13
+ *
14
+ * @param descriptor - SelectorDescriptor to convert
15
+ * @param baseVar - Base variable name to use (default: 'page')
16
+ * @returns Playwright code string representing the locator
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const code = selectorToPlaywrightCode({
21
+ * type: 'role',
22
+ * role: 'button',
23
+ * name: 'Submit'
24
+ * });
25
+ * // Returns: "page.getByRole('button', { name: 'Submit' })"
26
+ * ```
27
+ */
28
+ export declare function selectorToPlaywrightCode(descriptor: SelectorDescriptor, baseVar?: string): string;
29
+ /**
30
+ * Generate Playwright code for a click action
31
+ *
32
+ * @param selectorCode - Playwright locator code string
33
+ * @param clickType - Type of click action ('left', 'right', 'double', 'middle', 'hover')
34
+ * @returns Playwright code string for the click action
35
+ */
36
+ export declare function generateClickCode(selectorCode: string, clickType: 'primary' | 'secondary' | 'tertiary' | 'double' | 'hover'): string;
37
+ /**
38
+ * Generate Playwright code for a form action
39
+ *
40
+ * @param selectorCode - Playwright locator code string
41
+ * @param actionType - Type of form action
42
+ * @param value - Value to use for the action (if applicable)
43
+ * @returns Playwright code string for the form action
44
+ */
45
+ export declare function generateFormCode(selectorCode: string, actionType: 'keypress' | 'type' | 'fill' | 'select' | 'uncheck' | 'check' | 'click' | 'setInputFiles' | 'clear', value?: string): string;
46
+ /**
47
+ * Generate Playwright code for a navigation action
48
+ *
49
+ * @param actionType - Type of navigation action
50
+ * @param url - URL for navigate/openPage actions (optional)
51
+ * @param newWindow - If true, opens URL in a new browser window/tab (optional)
52
+ * @returns Playwright code string for the navigation action
53
+ */
54
+ export declare function generateNavigationCode(actionType: 'openPage' | 'navigate' | 'closePage' | 'goBack' | 'goForward' | 'refresh', url?: string, newWindow?: boolean): string;
55
+ //# sourceMappingURL=playwrightCodeGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwrightCodeGenerator.d.ts","sourceRoot":"","sources":["../../src/mimic/playwrightCodeGenerator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,kBAAkB,EAC9B,OAAO,GAAE,MAAe,GACvB,MAAM,CA6JR;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GACnE,MAAM,CAeR;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,eAAe,GAAG,OAAO,EAC/G,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAwBR;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,EACtF,GAAG,CAAC,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,OAAO,GAClB,MAAM,CA4BR"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Playwright Code Generator
3
+ *
4
+ * Converts SelectorDescriptor and action information into equivalent Playwright code strings
5
+ * for test annotations and documentation purposes.
6
+ */
7
+ import { jsonToStringOrRegex } from './selectorSerialization.js';
8
+ /**
9
+ * Convert a SelectorDescriptor to a Playwright code string
10
+ *
11
+ * Generates the equivalent Playwright locator code that would be used to select
12
+ * the element described by the SelectorDescriptor.
13
+ *
14
+ * @param descriptor - SelectorDescriptor to convert
15
+ * @param baseVar - Base variable name to use (default: 'page')
16
+ * @returns Playwright code string representing the locator
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const code = selectorToPlaywrightCode({
21
+ * type: 'role',
22
+ * role: 'button',
23
+ * name: 'Submit'
24
+ * });
25
+ * // Returns: "page.getByRole('button', { name: 'Submit' })"
26
+ * ```
27
+ */
28
+ export function selectorToPlaywrightCode(descriptor, baseVar = 'page') {
29
+ let code = baseVar;
30
+ // Build base locator code based on selector type
31
+ switch (descriptor.type) {
32
+ case 'testid':
33
+ code += `.getByTestId(${JSON.stringify(descriptor.value)})`;
34
+ break;
35
+ case 'role':
36
+ if (descriptor.name !== undefined) {
37
+ const nameValue = jsonToStringOrRegex(descriptor.name);
38
+ const isRegex = nameValue instanceof RegExp;
39
+ if (isRegex) {
40
+ // For regex, show the pattern
41
+ const pattern = nameValue.source;
42
+ const flags = nameValue.flags;
43
+ code += `.getByRole(${JSON.stringify(descriptor.role)}, { name: /${pattern}/${flags} })`;
44
+ }
45
+ else {
46
+ // For string, include exact option if specified
47
+ const options = [`name: ${JSON.stringify(nameValue)}`];
48
+ if (descriptor.exact) {
49
+ options.push('exact: true');
50
+ }
51
+ code += `.getByRole(${JSON.stringify(descriptor.role)}, { ${options.join(', ')} })`;
52
+ }
53
+ }
54
+ else {
55
+ code += `.getByRole(${JSON.stringify(descriptor.role)})`;
56
+ }
57
+ // Add .nth() if specified (for radio groups, checkbox groups, etc.)
58
+ if (descriptor.nth !== undefined) {
59
+ code += `.nth(${descriptor.nth})`;
60
+ }
61
+ break;
62
+ case 'label':
63
+ {
64
+ const labelValue = jsonToStringOrRegex(descriptor.value);
65
+ const isRegex = labelValue instanceof RegExp;
66
+ if (isRegex) {
67
+ const pattern = labelValue.source;
68
+ const flags = labelValue.flags;
69
+ code += `.getByLabel(/${pattern}/${flags})`;
70
+ }
71
+ else {
72
+ const options = [];
73
+ if (descriptor.exact) {
74
+ options.push('exact: true');
75
+ }
76
+ const optionsStr = options.length > 0 ? `, { ${options.join(', ')} }` : '';
77
+ code += `.getByLabel(${JSON.stringify(labelValue)}${optionsStr})`;
78
+ }
79
+ // Add .nth() if specified
80
+ if (descriptor.nth !== undefined) {
81
+ code += `.nth(${descriptor.nth})`;
82
+ }
83
+ }
84
+ break;
85
+ case 'placeholder':
86
+ {
87
+ const placeholderValue = jsonToStringOrRegex(descriptor.value);
88
+ const isRegex = placeholderValue instanceof RegExp;
89
+ if (isRegex) {
90
+ const pattern = placeholderValue.source;
91
+ const flags = placeholderValue.flags;
92
+ code += `.getByPlaceholder(/${pattern}/${flags})`;
93
+ }
94
+ else {
95
+ const options = [];
96
+ if (descriptor.exact) {
97
+ options.push('exact: true');
98
+ }
99
+ const optionsStr = options.length > 0 ? `, { ${options.join(', ')} }` : '';
100
+ code += `.getByPlaceholder(${JSON.stringify(placeholderValue)}${optionsStr})`;
101
+ }
102
+ }
103
+ break;
104
+ case 'alt':
105
+ {
106
+ const altValue = jsonToStringOrRegex(descriptor.value);
107
+ const isRegex = altValue instanceof RegExp;
108
+ if (isRegex) {
109
+ const pattern = altValue.source;
110
+ const flags = altValue.flags;
111
+ code += `.getByAltText(/${pattern}/${flags})`;
112
+ }
113
+ else {
114
+ const options = [];
115
+ if (descriptor.exact) {
116
+ options.push('exact: true');
117
+ }
118
+ const optionsStr = options.length > 0 ? `, { ${options.join(', ')} }` : '';
119
+ code += `.getByAltText(${JSON.stringify(altValue)}${optionsStr})`;
120
+ }
121
+ }
122
+ break;
123
+ case 'title':
124
+ {
125
+ const titleValue = jsonToStringOrRegex(descriptor.value);
126
+ const isRegex = titleValue instanceof RegExp;
127
+ if (isRegex) {
128
+ const pattern = titleValue.source;
129
+ const flags = titleValue.flags;
130
+ code += `.getByTitle(/${pattern}/${flags})`;
131
+ }
132
+ else {
133
+ const options = [];
134
+ if (descriptor.exact) {
135
+ options.push('exact: true');
136
+ }
137
+ const optionsStr = options.length > 0 ? `, { ${options.join(', ')} }` : '';
138
+ code += `.getByTitle(${JSON.stringify(titleValue)}${optionsStr})`;
139
+ }
140
+ }
141
+ break;
142
+ case 'text':
143
+ {
144
+ const textValue = jsonToStringOrRegex(descriptor.value);
145
+ const isRegex = textValue instanceof RegExp;
146
+ if (isRegex) {
147
+ const pattern = textValue.source;
148
+ const flags = textValue.flags;
149
+ code += `.getByText(/${pattern}/${flags})`;
150
+ }
151
+ else {
152
+ const options = [];
153
+ if (descriptor.exact) {
154
+ options.push('exact: true');
155
+ }
156
+ const optionsStr = options.length > 0 ? `, { ${options.join(', ')} }` : '';
157
+ code += `.getByText(${JSON.stringify(textValue)}${optionsStr})`;
158
+ }
159
+ }
160
+ break;
161
+ case 'css':
162
+ code += `.locator(${JSON.stringify(descriptor.selector)})`;
163
+ break;
164
+ default:
165
+ const _exhaustive = descriptor;
166
+ void _exhaustive;
167
+ throw new Error(`Unknown selector type: ${descriptor.type}`);
168
+ }
169
+ // Handle nested child selectors recursively
170
+ if (descriptor.child) {
171
+ // For nested selectors, chain the child selector
172
+ code = selectorToPlaywrightCode(descriptor.child, code);
173
+ }
174
+ return code;
175
+ }
176
+ /**
177
+ * Generate Playwright code for a click action
178
+ *
179
+ * @param selectorCode - Playwright locator code string
180
+ * @param clickType - Type of click action ('left', 'right', 'double', 'middle', 'hover')
181
+ * @returns Playwright code string for the click action
182
+ */
183
+ export function generateClickCode(selectorCode, clickType) {
184
+ switch (clickType) {
185
+ case 'primary':
186
+ return `await ${selectorCode}.click();`;
187
+ case 'secondary':
188
+ return `await ${selectorCode}.click({ button: 'right' });`;
189
+ case 'double':
190
+ return `await ${selectorCode}.dblclick();`;
191
+ case 'tertiary':
192
+ return `await ${selectorCode}.click({ button: 'middle' });`;
193
+ case 'hover':
194
+ return `await ${selectorCode}.hover();`;
195
+ default:
196
+ throw new Error(`Unknown click type: ${clickType}`);
197
+ }
198
+ }
199
+ /**
200
+ * Generate Playwright code for a form action
201
+ *
202
+ * @param selectorCode - Playwright locator code string
203
+ * @param actionType - Type of form action
204
+ * @param value - Value to use for the action (if applicable)
205
+ * @returns Playwright code string for the form action
206
+ */
207
+ export function generateFormCode(selectorCode, actionType, value) {
208
+ switch (actionType) {
209
+ case 'fill':
210
+ return `await ${selectorCode}.fill(${JSON.stringify(value || '')});`;
211
+ case 'type':
212
+ // Type action uses page.keyboard, not the element selector
213
+ return `await page.keyboard.type(${JSON.stringify(value || '')});`;
214
+ case 'select':
215
+ return `await ${selectorCode}.selectOption(${JSON.stringify(value || '')});`;
216
+ case 'check':
217
+ return `await ${selectorCode}.check();`;
218
+ case 'uncheck':
219
+ return `await ${selectorCode}.uncheck();`;
220
+ case 'click':
221
+ return `await ${selectorCode}.click();`;
222
+ case 'clear':
223
+ return `await ${selectorCode}.clear();`;
224
+ case 'setInputFiles':
225
+ return `await ${selectorCode}.setInputFiles(${JSON.stringify(value || '')});`;
226
+ case 'keypress':
227
+ return `await page.keyboard.press(${JSON.stringify(value || '')});`;
228
+ default:
229
+ throw new Error(`Unknown form action type: ${actionType}`);
230
+ }
231
+ }
232
+ /**
233
+ * Generate Playwright code for a navigation action
234
+ *
235
+ * @param actionType - Type of navigation action
236
+ * @param url - URL for navigate/openPage actions (optional)
237
+ * @param newWindow - If true, opens URL in a new browser window/tab (optional)
238
+ * @returns Playwright code string for the navigation action
239
+ */
240
+ export function generateNavigationCode(actionType, url, newWindow) {
241
+ switch (actionType) {
242
+ case 'openPage':
243
+ case 'navigate':
244
+ if (newWindow) {
245
+ // Generate code for opening in a new window/tab
246
+ if (url) {
247
+ return `const newPage = await page.context().newPage();\nawait newPage.goto(${JSON.stringify(url)}, { waitUntil: 'networkidle' });`;
248
+ }
249
+ return `const newPage = await page.context().newPage();\nawait newPage.goto(url, { waitUntil: 'networkidle' });`;
250
+ }
251
+ else {
252
+ // Generate code for normal navigation
253
+ if (url) {
254
+ return `await page.goto(${JSON.stringify(url)}, { waitUntil: 'networkidle' });`;
255
+ }
256
+ return `await page.goto(url, { waitUntil: 'networkidle' });`;
257
+ }
258
+ case 'closePage':
259
+ return `await page.close();`;
260
+ case 'goBack':
261
+ return `await page.goBack();`;
262
+ case 'goForward':
263
+ return `await page.goForward();`;
264
+ case 'refresh':
265
+ return `await page.reload();`;
266
+ default:
267
+ throw new Error(`Unknown navigation action type: ${actionType}`);
268
+ }
269
+ }
270
+ //# sourceMappingURL=playwrightCodeGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwrightCodeGenerator.js","sourceRoot":"","sources":["../../src/mimic/playwrightCodeGenerator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Snapshot Replay Module
3
+ *
4
+ * Replays test steps from a snapshot without using LLM calls.
5
+ * This provides fast, deterministic test execution for previously successful tests.
6
+ */
7
+ import { Page, TestInfo } from '@playwright/test';
8
+ import type { Snapshot } from './types.js';
9
+ /**
10
+ * Replay a complete test from a snapshot
11
+ *
12
+ * Executes all steps in the snapshot without making LLM calls.
13
+ * This is much faster than normal execution since it skips AI analysis.
14
+ *
15
+ * @param page - Playwright Page object
16
+ * @param snapshot - Snapshot containing steps to replay
17
+ * @param testInfo - Playwright TestInfo for annotations (optional)
18
+ * @returns Promise that resolves when all steps are replayed
19
+ */
20
+ export declare function replayFromSnapshot(page: Page, snapshot: Snapshot, testInfo?: TestInfo): Promise<void>;
21
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/mimic/replay.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAQ,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,YAAY,CAAC;AAUzD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,QAAQ,CAAC,EAAE,QAAQ,GAClB,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Snapshot Replay Module
3
+ *
4
+ * Replays test steps from a snapshot without using LLM calls.
5
+ * This provides fast, deterministic test execution for previously successful tests.
6
+ */
7
+ import { test } from '@playwright/test';
8
+ import { executeNavigationAction } from './navigation.js';
9
+ import { executeClickAction } from './click.js';
10
+ import { executeFormAction } from './forms.js';
11
+ import { getMimic } from './markers.js';
12
+ import { getFromSelector } from './selectorUtils.js';
13
+ /**
14
+ * Replay a complete test from a snapshot
15
+ *
16
+ * Executes all steps in the snapshot without making LLM calls.
17
+ * This is much faster than normal execution since it skips AI analysis.
18
+ *
19
+ * @param page - Playwright Page object
20
+ * @param snapshot - Snapshot containing steps to replay
21
+ * @param testInfo - Playwright TestInfo for annotations (optional)
22
+ * @returns Promise that resolves when all steps are replayed
23
+ */
24
+ export async function replayFromSnapshot(page, snapshot, testInfo) {
25
+ // Get steps array for replay (support both new and old format)
26
+ // New format: use steps array (which is built from stepsByHash for backward compatibility)
27
+ // Old format: use steps array directly
28
+ const stepsToReplay = snapshot.steps || [];
29
+ if (stepsToReplay.length === 0) {
30
+ console.warn('⚠️ Snapshot has no steps to replay');
31
+ return;
32
+ }
33
+ // Replay each step in order
34
+ for (const step of stepsToReplay) {
35
+ await test.step(step.stepText, async () => {
36
+ switch (step.actionKind) {
37
+ case 'navigation':
38
+ await replayNavigationStep(page, step, testInfo);
39
+ break;
40
+ case 'click':
41
+ await replayClickStep(page, step, testInfo);
42
+ break;
43
+ case 'form update':
44
+ await replayFormStep(page, step, testInfo);
45
+ break;
46
+ default:
47
+ throw new Error(`Unknown action kind in snapshot: ${step.actionKind}`);
48
+ }
49
+ });
50
+ }
51
+ }
52
+ /**
53
+ * Replay a navigation step from snapshot
54
+ *
55
+ * @param page - Playwright Page object
56
+ * @param step - Snapshot step containing navigation action
57
+ * @param testInfo - Playwright TestInfo for annotations (optional)
58
+ * @returns Promise that resolves when navigation is complete
59
+ */
60
+ async function replayNavigationStep(page, step, testInfo) {
61
+ const actionDetails = step.actionDetails;
62
+ await executeNavigationAction(page, actionDetails, testInfo, step.stepText);
63
+ }
64
+ /**
65
+ * Replay a click step from snapshot
66
+ *
67
+ * Reconstructs the locator from stored target element information.
68
+ *
69
+ * @param page - Playwright Page object
70
+ * @param step - Snapshot step containing click action
71
+ * @param testInfo - Playwright TestInfo for annotations (optional)
72
+ * @returns Promise that resolves when click is complete
73
+ */
74
+ async function replayClickStep(page, step, testInfo) {
75
+ const actionDetails = step.actionDetails;
76
+ // Reconstruct the target element from snapshot using best selector
77
+ if (!step.targetElement || !step.targetElement.selector) {
78
+ throw new Error(`Snapshot step ${step.stepIndex} (click) is missing targetElement with selector`);
79
+ }
80
+ // Use the stored selector descriptor (primary) to reconstruct the locator
81
+ // Fall back to mimicId if selector fails
82
+ let element;
83
+ try {
84
+ element = getFromSelector(page, step.targetElement.selector);
85
+ // Verify the element exists
86
+ await element.waitFor({ timeout: 5000 });
87
+ }
88
+ catch (error) {
89
+ // Selector might be stale, fall back to marker ID
90
+ if (step.targetElement.mimicId !== undefined) {
91
+ console.warn(`Stored selector failed for step ${step.stepIndex}, using marker ID ${step.targetElement.mimicId}`);
92
+ element = getMimic(page, step.targetElement.mimicId);
93
+ }
94
+ else {
95
+ throw new Error(`Snapshot step ${step.stepIndex} (click) selector failed and no mimicId fallback available`);
96
+ }
97
+ }
98
+ // Find the selected candidate from the click action result
99
+ // The first candidate should be the one we used originally
100
+ const selectedCandidate = actionDetails.candidates[0];
101
+ if (!selectedCandidate) {
102
+ throw new Error(`Snapshot step ${step.stepIndex} (click) has no candidates in actionDetails`);
103
+ }
104
+ await executeClickAction(element, actionDetails, selectedCandidate, testInfo, step.stepText);
105
+ }
106
+ /**
107
+ * Replay a form step from snapshot
108
+ *
109
+ * Reconstructs the form element locator from stored target element information.
110
+ *
111
+ * @param page - Playwright Page object
112
+ * @param step - Snapshot step containing form action
113
+ * @param testInfo - Playwright TestInfo for annotations (optional)
114
+ * @returns Promise that resolves when form action is complete
115
+ */
116
+ async function replayFormStep(page, step, testInfo) {
117
+ const actionDetails = step.actionDetails;
118
+ // Reconstruct the target element from snapshot using best selector
119
+ if (!step.targetElement || !step.targetElement.selector) {
120
+ throw new Error(`Snapshot step ${step.stepIndex} (form) is missing targetElement with selector`);
121
+ }
122
+ // Use the stored selector descriptor (primary) to reconstruct the locator
123
+ // Fall back to mimicId if selector fails
124
+ let element;
125
+ try {
126
+ element = getFromSelector(page, step.targetElement.selector);
127
+ // Verify the element exists
128
+ await element.waitFor({ timeout: 5000 });
129
+ }
130
+ catch (error) {
131
+ // Selector might be stale, fall back to marker ID
132
+ if (step.targetElement.mimicId !== undefined) {
133
+ console.warn(`Stored selector failed for step ${step.stepIndex}, using marker ID ${step.targetElement.mimicId}`);
134
+ element = getMimic(page, step.targetElement.mimicId);
135
+ }
136
+ else {
137
+ throw new Error(`Snapshot step ${step.stepIndex} (form) selector failed and no mimicId fallback available`);
138
+ }
139
+ }
140
+ await executeFormAction(page, actionDetails, element, testInfo, step.stepText);
141
+ }
142
+ //# sourceMappingURL=replay.js.map