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.
- package/README.md +695 -446
- package/dist/agentic/agent.d.ts +106 -0
- package/dist/agentic/agent.d.ts.map +1 -0
- package/dist/agentic/agent.js +528 -0
- package/dist/agentic/agent.js.map +1 -0
- package/dist/agentic/index.d.ts +13 -0
- package/dist/agentic/index.d.ts.map +1 -0
- package/dist/agentic/index.js +12 -0
- package/dist/agentic/index.js.map +1 -0
- package/dist/agentic/planner.d.ts +41 -0
- package/dist/agentic/planner.d.ts.map +1 -0
- package/dist/agentic/planner.js +136 -0
- package/dist/agentic/planner.js.map +1 -0
- package/dist/agentic/react.d.ts +35 -0
- package/dist/agentic/react.d.ts.map +1 -0
- package/dist/agentic/react.js +170 -0
- package/dist/agentic/react.js.map +1 -0
- package/dist/agentic/recovery.d.ts +55 -0
- package/dist/agentic/recovery.d.ts.map +1 -0
- package/dist/agentic/recovery.js +200 -0
- package/dist/agentic/recovery.js.map +1 -0
- package/dist/agentic/reflection.d.ts +40 -0
- package/dist/agentic/reflection.d.ts.map +1 -0
- package/dist/agentic/reflection.js +142 -0
- package/dist/agentic/reflection.js.map +1 -0
- package/dist/agentic/types.d.ts +177 -0
- package/dist/agentic/types.d.ts.map +1 -0
- package/dist/agentic/types.js +8 -0
- package/dist/agentic/types.js.map +1 -0
- package/dist/agentic/wait.d.ts +50 -0
- package/dist/agentic/wait.d.ts.map +1 -0
- package/dist/agentic/wait.js +140 -0
- package/dist/agentic/wait.js.map +1 -0
- package/dist/agentic-mimic.d.ts +56 -0
- package/dist/agentic-mimic.d.ts.map +1 -0
- package/dist/agentic-mimic.js +98 -0
- package/dist/agentic-mimic.js.map +1 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/mimic/actionType.d.ts +7 -0
- package/dist/mimic/actionType.d.ts.map +1 -0
- package/dist/mimic/actionType.js +44 -0
- package/dist/mimic/actionType.js.map +1 -0
- package/dist/mimic/annotations.d.ts +21 -0
- package/dist/mimic/annotations.d.ts.map +1 -0
- package/dist/mimic/annotations.js +36 -0
- package/dist/mimic/annotations.js.map +1 -0
- package/dist/mimic/cli.d.ts +15 -0
- package/dist/mimic/cli.d.ts.map +1 -0
- package/dist/mimic/cli.js +17 -0
- package/dist/mimic/cli.js.map +1 -0
- package/dist/mimic/click.d.ts +39 -0
- package/dist/mimic/click.d.ts.map +1 -0
- package/dist/mimic/click.js +348 -0
- package/dist/mimic/click.js.map +1 -0
- package/dist/mimic/forms.d.ts +52 -0
- package/dist/mimic/forms.d.ts.map +1 -0
- package/dist/mimic/forms.js +511 -0
- package/dist/mimic/forms.js.map +1 -0
- package/dist/mimic/markers.d.ts +133 -0
- package/dist/mimic/markers.d.ts.map +1 -0
- package/dist/mimic/markers.js +589 -0
- package/dist/mimic/markers.js.map +1 -0
- package/dist/mimic/navigation.d.ts +19 -0
- package/dist/mimic/navigation.d.ts.map +1 -0
- package/dist/mimic/navigation.js +136 -0
- package/dist/mimic/navigation.js.map +1 -0
- package/dist/mimic/playwrightCodeGenerator.d.ts +55 -0
- package/dist/mimic/playwrightCodeGenerator.d.ts.map +1 -0
- package/dist/mimic/playwrightCodeGenerator.js +270 -0
- package/dist/mimic/playwrightCodeGenerator.js.map +1 -0
- package/dist/mimic/replay.d.ts +21 -0
- package/dist/mimic/replay.d.ts.map +1 -0
- package/dist/mimic/replay.js +142 -0
- package/dist/mimic/replay.js.map +1 -0
- package/dist/mimic/schema/action.d.ts +315 -0
- package/dist/mimic/schema/action.d.ts.map +1 -0
- package/dist/mimic/schema/action.js +186 -0
- package/dist/mimic/schema/action.js.map +1 -0
- package/dist/mimic/selector.d.ts +143 -0
- package/dist/mimic/selector.d.ts.map +1 -0
- package/dist/mimic/selector.js +1515 -0
- package/dist/mimic/selector.js.map +1 -0
- package/dist/mimic/selectorDescriptor.d.ts +25 -0
- package/dist/mimic/selectorDescriptor.d.ts.map +1 -0
- package/dist/mimic/selectorDescriptor.js +32 -0
- package/dist/mimic/selectorDescriptor.js.map +1 -0
- package/dist/mimic/selectorSerialization.d.ts +18 -0
- package/dist/mimic/selectorSerialization.d.ts.map +1 -0
- package/dist/mimic/selectorSerialization.js +32 -0
- package/dist/mimic/selectorSerialization.js.map +1 -0
- package/dist/mimic/selectorTypes.d.ts +122 -0
- package/dist/mimic/selectorTypes.d.ts.map +1 -0
- package/dist/mimic/selectorTypes.js +2 -0
- package/dist/mimic/selectorTypes.js.map +1 -0
- package/dist/mimic/selectorUtils.d.ts +52 -0
- package/dist/mimic/selectorUtils.d.ts.map +1 -0
- package/dist/mimic/selectorUtils.js +251 -0
- package/dist/mimic/selectorUtils.js.map +1 -0
- package/dist/mimic/storage.d.ts +110 -0
- package/dist/mimic/storage.d.ts.map +1 -0
- package/dist/mimic/storage.js +409 -0
- package/dist/mimic/storage.js.map +1 -0
- package/dist/mimic/types.d.ts +85 -0
- package/dist/mimic/types.d.ts.map +1 -0
- package/dist/mimic/types.js +7 -0
- package/dist/mimic/types.js.map +1 -0
- package/dist/mimic.d.ts +29 -4
- package/dist/mimic.d.ts.map +1 -1
- package/dist/mimic.js +530 -32
- package/dist/mimic.js.map +1 -1
- package/dist/mimicry.d.ts +4 -4
- package/dist/mimicry.d.ts.map +1 -1
- package/dist/mimicry.js +22 -13
- package/dist/mimicry.js.map +1 -1
- package/package.json +30 -6
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { jsonToStringOrRegex } from './selectorSerialization.js';
|
|
2
|
+
import { getMimic } from './markers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reconstruct a Playwright Locator from a stored SelectorDescriptor
|
|
5
|
+
*
|
|
6
|
+
* This function recursively builds a locator from a selector descriptor,
|
|
7
|
+
* handling nested selectors by chaining locator method calls.
|
|
8
|
+
*
|
|
9
|
+
* The descriptor uses JSON-serializable formats (StringOrRegexJson), which are
|
|
10
|
+
* converted to runtime formats (StringOrRegex) as needed when calling Playwright APIs.
|
|
11
|
+
*
|
|
12
|
+
* @param page - Playwright Page object (or parent Locator for nested selectors)
|
|
13
|
+
* @param descriptor - SelectorDescriptor (from JSON)
|
|
14
|
+
* @param depth - Current recursion depth (internal use, defaults to 0)
|
|
15
|
+
* @returns Playwright Locator reconstructed from the descriptor
|
|
16
|
+
*/
|
|
17
|
+
export function getFromSelector(page, descriptor, depth = 0) {
|
|
18
|
+
// Prevent infinite recursion by limiting depth to 10 levels
|
|
19
|
+
const MAX_DEPTH = 10;
|
|
20
|
+
if (depth >= MAX_DEPTH) {
|
|
21
|
+
throw new Error(`Maximum selector nesting depth (${MAX_DEPTH}) exceeded. This may indicate a circular reference in the selector descriptor.`);
|
|
22
|
+
}
|
|
23
|
+
let baseLocator;
|
|
24
|
+
// Build base locator based on selector type
|
|
25
|
+
// Both Page and Locator have the same locator methods, so we can call them directly
|
|
26
|
+
switch (descriptor.type) {
|
|
27
|
+
case 'testid':
|
|
28
|
+
baseLocator = page.getByTestId(descriptor.value);
|
|
29
|
+
break;
|
|
30
|
+
case 'role':
|
|
31
|
+
if (descriptor.name !== undefined) {
|
|
32
|
+
// Convert JSON format to runtime format for Playwright API
|
|
33
|
+
const nameValue = jsonToStringOrRegex(descriptor.name);
|
|
34
|
+
const isRegex = nameValue instanceof RegExp;
|
|
35
|
+
const roleOptions = isRegex
|
|
36
|
+
? { name: nameValue }
|
|
37
|
+
: { name: nameValue, exact: descriptor.exact ?? false };
|
|
38
|
+
baseLocator = page.getByRole(descriptor.role, roleOptions);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
baseLocator = page.getByRole(descriptor.role);
|
|
42
|
+
}
|
|
43
|
+
// Apply nth() if specified (for radio groups, checkbox groups, etc.)
|
|
44
|
+
if (descriptor.nth !== undefined) {
|
|
45
|
+
baseLocator = baseLocator.nth(descriptor.nth);
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
case 'label':
|
|
49
|
+
{
|
|
50
|
+
// Convert JSON format to runtime format
|
|
51
|
+
const labelValue = jsonToStringOrRegex(descriptor.value);
|
|
52
|
+
const isRegex = labelValue instanceof RegExp;
|
|
53
|
+
const labelOptions = isRegex
|
|
54
|
+
? {}
|
|
55
|
+
: { exact: descriptor.exact ?? false };
|
|
56
|
+
baseLocator = page.getByLabel(labelValue, labelOptions);
|
|
57
|
+
// Apply nth() if specified
|
|
58
|
+
if (descriptor.nth !== undefined) {
|
|
59
|
+
baseLocator = baseLocator.nth(descriptor.nth);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 'placeholder':
|
|
64
|
+
{
|
|
65
|
+
// Convert JSON format to runtime format
|
|
66
|
+
const placeholderValue = jsonToStringOrRegex(descriptor.value);
|
|
67
|
+
const isRegex = placeholderValue instanceof RegExp;
|
|
68
|
+
const placeholderOptions = isRegex
|
|
69
|
+
? {}
|
|
70
|
+
: { exact: descriptor.exact ?? false };
|
|
71
|
+
baseLocator = page.getByPlaceholder(placeholderValue, placeholderOptions);
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
case 'alt':
|
|
75
|
+
{
|
|
76
|
+
// Convert JSON format to runtime format
|
|
77
|
+
const altValue = jsonToStringOrRegex(descriptor.value);
|
|
78
|
+
const isRegex = altValue instanceof RegExp;
|
|
79
|
+
const altOptions = isRegex
|
|
80
|
+
? {}
|
|
81
|
+
: { exact: descriptor.exact ?? false };
|
|
82
|
+
baseLocator = page.getByAltText(altValue, altOptions);
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
85
|
+
case 'title':
|
|
86
|
+
{
|
|
87
|
+
// Convert JSON format to runtime format
|
|
88
|
+
const titleValue = jsonToStringOrRegex(descriptor.value);
|
|
89
|
+
const isRegex = titleValue instanceof RegExp;
|
|
90
|
+
const titleOptions = isRegex
|
|
91
|
+
? {}
|
|
92
|
+
: { exact: descriptor.exact ?? false };
|
|
93
|
+
baseLocator = page.getByTitle(titleValue, titleOptions);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case 'text':
|
|
97
|
+
{
|
|
98
|
+
// Convert JSON format to runtime format
|
|
99
|
+
const textValue = jsonToStringOrRegex(descriptor.value);
|
|
100
|
+
const isRegex = textValue instanceof RegExp;
|
|
101
|
+
const textOptions = isRegex
|
|
102
|
+
? {}
|
|
103
|
+
: { exact: descriptor.exact ?? false };
|
|
104
|
+
baseLocator = page.getByText(textValue, textOptions);
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
case 'css':
|
|
108
|
+
baseLocator = page.locator(descriptor.selector);
|
|
109
|
+
break;
|
|
110
|
+
default:
|
|
111
|
+
// TypeScript exhaustiveness check - if we reach here, a case is missing
|
|
112
|
+
const _exhaustive = descriptor;
|
|
113
|
+
void _exhaustive; // Suppress unused variable warning
|
|
114
|
+
throw new Error(`Unknown selector type: ${descriptor.type}`);
|
|
115
|
+
}
|
|
116
|
+
// If there's a nested child selector, recursively build it from the base locator
|
|
117
|
+
if (descriptor.child) {
|
|
118
|
+
return getFromSelector(baseLocator, descriptor.child, depth + 1);
|
|
119
|
+
}
|
|
120
|
+
return baseLocator;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the mimic ID from a locator
|
|
124
|
+
*
|
|
125
|
+
* Retrieves the data-mimic-id attribute value from the element
|
|
126
|
+
* that the locator points to. This ID is assigned by the markers system.
|
|
127
|
+
*
|
|
128
|
+
* @param locator - Playwright Locator to get the mimic ID from
|
|
129
|
+
* @returns Promise resolving to the mimic ID number, or null if not found
|
|
130
|
+
*/
|
|
131
|
+
export async function getMimicIdFromLocator(locator) {
|
|
132
|
+
try {
|
|
133
|
+
// Evaluate directly on the locator to get the mimic ID attribute
|
|
134
|
+
const mimicId = await locator.evaluate((el) => {
|
|
135
|
+
const idAttr = el.getAttribute('data-mimic-id');
|
|
136
|
+
return idAttr ? Number(idAttr) : null;
|
|
137
|
+
});
|
|
138
|
+
return mimicId;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
// If element not found or error occurs, return null
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Verify that a selector uniquely identifies the target element
|
|
147
|
+
*
|
|
148
|
+
* This function checks if a locator built from a SelectorDescriptor matches
|
|
149
|
+
* exactly one element, and optionally verifies it matches the target element
|
|
150
|
+
* using the markers system (mimic ID).
|
|
151
|
+
*
|
|
152
|
+
* The function saves the nested Locator type returned by getFromSelector,
|
|
153
|
+
* which can be used for further operations on the matched element.
|
|
154
|
+
*
|
|
155
|
+
* @param page - Playwright Page object
|
|
156
|
+
* @param descriptor - SelectorDescriptor to verify
|
|
157
|
+
* @param targetMimicId - Optional mimic ID to verify the match is correct
|
|
158
|
+
* @param timeout - Optional timeout in milliseconds for locator operations (default: 30000 = 30 seconds)
|
|
159
|
+
* @returns Promise resolving to an object with:
|
|
160
|
+
* - unique: true if selector is unique (and matches target if provided)
|
|
161
|
+
* - locator: The Locator returned by getFromSelector (nested type preserved)
|
|
162
|
+
*/
|
|
163
|
+
export async function verifySelectorUniqueness(page, descriptor, targetMimicId, timeout) {
|
|
164
|
+
// Default to 30 seconds for selector operations
|
|
165
|
+
const operationTimeout = timeout ?? 30000;
|
|
166
|
+
try {
|
|
167
|
+
// Get the locator from the selector descriptor (preserves nested type)
|
|
168
|
+
const locator = getFromSelector(page, descriptor);
|
|
169
|
+
// count() doesn't support timeout, but it's typically fast
|
|
170
|
+
// The main timeout-sensitive operations are elementHandle() calls below
|
|
171
|
+
const count = await locator.count();
|
|
172
|
+
// Must match exactly one element
|
|
173
|
+
if (count !== 1) {
|
|
174
|
+
// If multiple matches and we have a target mimic ID, find the index
|
|
175
|
+
let index;
|
|
176
|
+
if (count > 1 && targetMimicId !== null && targetMimicId !== undefined) {
|
|
177
|
+
// Find which index matches the target element
|
|
178
|
+
for (let i = 0; i < count; i++) {
|
|
179
|
+
const nthLocator = locator.nth(i);
|
|
180
|
+
const mimicId = await getMimicIdFromLocator(nthLocator);
|
|
181
|
+
if (mimicId === targetMimicId) {
|
|
182
|
+
index = i;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Only include index if it's defined
|
|
188
|
+
const result = {
|
|
189
|
+
unique: false,
|
|
190
|
+
locator,
|
|
191
|
+
count,
|
|
192
|
+
};
|
|
193
|
+
if (index !== undefined) {
|
|
194
|
+
result.index = index;
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
// If target mimic ID provided, verify it's the same element
|
|
199
|
+
if (targetMimicId !== null && targetMimicId !== undefined) {
|
|
200
|
+
// Get the mimic ID from the matched locator
|
|
201
|
+
const matchedMimicId = await getMimicIdFromLocator(locator);
|
|
202
|
+
// If no mimic ID found on matched element, verification fails
|
|
203
|
+
if (matchedMimicId === null) {
|
|
204
|
+
return { unique: false, locator };
|
|
205
|
+
}
|
|
206
|
+
// Verify the mimic IDs match
|
|
207
|
+
if (matchedMimicId !== targetMimicId) {
|
|
208
|
+
return { unique: false, locator };
|
|
209
|
+
}
|
|
210
|
+
// Additional verification: ensure the locator from getMimic matches
|
|
211
|
+
// This double-checks that the selector correctly identifies the element
|
|
212
|
+
const markerLocator = getMimic(page, targetMimicId);
|
|
213
|
+
// count() doesn't support timeout, but it's typically fast
|
|
214
|
+
const markerCount = await markerLocator.count();
|
|
215
|
+
if (markerCount !== 1) {
|
|
216
|
+
return { unique: false, locator };
|
|
217
|
+
}
|
|
218
|
+
// Verify both locators point to the same element by comparing their positions
|
|
219
|
+
const locatorElement = await locator.elementHandle({ timeout: operationTimeout });
|
|
220
|
+
const markerElement = await markerLocator.elementHandle({ timeout: operationTimeout });
|
|
221
|
+
if (!locatorElement || !markerElement) {
|
|
222
|
+
return { unique: false, locator };
|
|
223
|
+
}
|
|
224
|
+
// Compare elements by their mimic IDs (most reliable)
|
|
225
|
+
const locatorMimicId = await page.evaluate((el) => {
|
|
226
|
+
return el.getAttribute('data-mimic-id');
|
|
227
|
+
}, locatorElement);
|
|
228
|
+
const markerMimicId = await page.evaluate((el) => {
|
|
229
|
+
return el.getAttribute('data-mimic-id');
|
|
230
|
+
}, markerElement);
|
|
231
|
+
if (locatorMimicId !== markerMimicId || locatorMimicId !== String(targetMimicId)) {
|
|
232
|
+
return { unique: false, locator };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { unique: true, locator, count: 1 };
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
// If selector is invalid or throws, it's not unique
|
|
239
|
+
// Still return the locator for potential use
|
|
240
|
+
try {
|
|
241
|
+
const locator = getFromSelector(page, descriptor);
|
|
242
|
+
return { unique: false, locator, count: 0 };
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// If we can't even create the locator, return a dummy one
|
|
246
|
+
// This shouldn't happen in practice, but TypeScript requires a return
|
|
247
|
+
return { unique: false, locator: page.locator('body'), count: 0 };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=selectorUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectorUtils.js","sourceRoot":"","sources":["../../src/mimic/selectorUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot Storage Module
|
|
3
|
+
*
|
|
4
|
+
* Handles reading, writing, and managing test execution snapshots.
|
|
5
|
+
* Snapshots store successful test executions as JSON files for fast replay.
|
|
6
|
+
*/
|
|
7
|
+
import type { Snapshot } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Generate a hash from test text to create a unique identifier
|
|
10
|
+
*
|
|
11
|
+
* @param testText - The test text (mimic template string)
|
|
12
|
+
* @returns SHA-256 hash of the test text (first 16 characters for readability)
|
|
13
|
+
*/
|
|
14
|
+
export declare function hashTestText(testText: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Generate a hash from step text to create a unique identifier
|
|
17
|
+
*
|
|
18
|
+
* @param stepText - The step text (Gherkin step)
|
|
19
|
+
* @returns SHA-256 hash of the step text (first 16 characters for readability)
|
|
20
|
+
*/
|
|
21
|
+
export declare function hashStepText(stepText: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Extract test file name from full file path
|
|
24
|
+
*
|
|
25
|
+
* @param testFilePath - Full path to the test file
|
|
26
|
+
* @returns Test file name without extension (e.g., "buttons-variety" from "buttons-variety.spec.ts")
|
|
27
|
+
*/
|
|
28
|
+
export declare function getTestFileName(testFilePath: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Get the mimic directory path for a test file
|
|
31
|
+
*
|
|
32
|
+
* @param testFilePath - Full path to the test file
|
|
33
|
+
* @returns Path to the __mimic__ directory
|
|
34
|
+
*/
|
|
35
|
+
export declare function getMimicDir(testFilePath: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Get the mimic file path for a test file
|
|
38
|
+
*
|
|
39
|
+
* @param testFilePath - Full path to the test file
|
|
40
|
+
* @returns Full path to the mimic JSON file (e.g., "__mimic__/agentic.mimic.json")
|
|
41
|
+
*/
|
|
42
|
+
export declare function getMimicFilePath(testFilePath: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Get the snapshot directory path for a test file (legacy support)
|
|
45
|
+
*
|
|
46
|
+
* @param testFilePath - Directory path of the test file
|
|
47
|
+
* @returns Path to the .mimic-snapshots directory
|
|
48
|
+
* @deprecated Use getMimicDir instead
|
|
49
|
+
*/
|
|
50
|
+
export declare function getSnapshotDir(testFilePath: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Get the snapshot file path for a specific test (legacy support)
|
|
53
|
+
*
|
|
54
|
+
* @param testFilePath - Directory path of the test file
|
|
55
|
+
* @param testHash - Hash identifier for the test
|
|
56
|
+
* @returns Full path to the snapshot JSON file
|
|
57
|
+
* @deprecated Use getMimicFilePath instead
|
|
58
|
+
*/
|
|
59
|
+
export declare function getSnapshotPath(testFilePath: string, testHash: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Read a snapshot from disk
|
|
62
|
+
*
|
|
63
|
+
* @param testFilePath - Full path to the test file
|
|
64
|
+
* @param testHash - Hash identifier for the test
|
|
65
|
+
* @returns Snapshot object if found, null otherwise
|
|
66
|
+
*/
|
|
67
|
+
export declare function getSnapshot(testFilePath: string, testHash: string): Promise<Snapshot | null>;
|
|
68
|
+
/**
|
|
69
|
+
* Save a snapshot to disk
|
|
70
|
+
*
|
|
71
|
+
* Saves all tests from a test file into a single JSON file in __mimic__ directory.
|
|
72
|
+
* Updates existing test entry if testHash already exists, otherwise adds new test.
|
|
73
|
+
*
|
|
74
|
+
* @param testFilePath - Full path to the test file
|
|
75
|
+
* @param snapshot - Snapshot object to save
|
|
76
|
+
* @returns Promise that resolves when snapshot is saved
|
|
77
|
+
*/
|
|
78
|
+
export declare function saveSnapshot(testFilePath: string, snapshot: Snapshot): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Record a test failure timestamp
|
|
81
|
+
*
|
|
82
|
+
* Updates the snapshot's lastFailedAt timestamp and flags if the snapshot exists.
|
|
83
|
+
*
|
|
84
|
+
* @param testFilePath - Full path to the test file
|
|
85
|
+
* @param testHash - Hash identifier for the test
|
|
86
|
+
* @param failedStepIndex - Index of the step that failed (optional)
|
|
87
|
+
* @param failedStepText - Text of the step that failed (optional)
|
|
88
|
+
* @param error - Error message (optional)
|
|
89
|
+
* @returns Promise that resolves when failure is recorded
|
|
90
|
+
*/
|
|
91
|
+
export declare function recordFailure(testFilePath: string, testHash: string, failedStepIndex?: number, failedStepText?: string, error?: string): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Determine if a snapshot should be used for replay
|
|
94
|
+
*
|
|
95
|
+
* A snapshot should be used if:
|
|
96
|
+
* - It exists
|
|
97
|
+
* - lastPassedAt is more recent than lastFailedAt (or lastFailedAt is null)
|
|
98
|
+
* - Flags don't indicate it should be skipped
|
|
99
|
+
*
|
|
100
|
+
* Note: Even in troubleshoot mode, we use snapshots if they've passed.
|
|
101
|
+
* Regeneration will happen only if replay fails.
|
|
102
|
+
*
|
|
103
|
+
* @param testFilePath - Full path to the test file
|
|
104
|
+
* @param testHash - Hash identifier for the test
|
|
105
|
+
* @param troubleshootMode - Whether troubleshoot mode is enabled (unused, kept for compatibility)
|
|
106
|
+
* @param expectedStepCount - Expected number of steps (optional)
|
|
107
|
+
* @returns true if snapshot should be used, false otherwise
|
|
108
|
+
*/
|
|
109
|
+
export declare function shouldUseSnapshot(testFilePath: string, testHash: string, _troubleshootMode?: boolean, expectedStepCount?: number): Promise<boolean>;
|
|
110
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/mimic/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,YAAY,CAAC;AAEzD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI7D;AA2BD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG9E;AAGD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAwB1B;AA6BD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CA8Gf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,eAAe,CAAC,EAAE,MAAM,EACxB,cAAc,CAAC,EAAE,MAAM,EACvB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe,EAClC,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,CAAC,OAAO,CAAC,CA0DlB"}
|