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,409 @@
|
|
|
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 { createHash } from 'crypto';
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import { join, dirname, basename } from 'node:path';
|
|
10
|
+
/**
|
|
11
|
+
* Generate a hash from test text to create a unique identifier
|
|
12
|
+
*
|
|
13
|
+
* @param testText - The test text (mimic template string)
|
|
14
|
+
* @returns SHA-256 hash of the test text (first 16 characters for readability)
|
|
15
|
+
*/
|
|
16
|
+
export function hashTestText(testText) {
|
|
17
|
+
const hash = createHash('sha256');
|
|
18
|
+
hash.update(testText.trim());
|
|
19
|
+
return hash.digest('hex').substring(0, 16);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate a hash from step text to create a unique identifier
|
|
23
|
+
*
|
|
24
|
+
* @param stepText - The step text (Gherkin step)
|
|
25
|
+
* @returns SHA-256 hash of the step text (first 16 characters for readability)
|
|
26
|
+
*/
|
|
27
|
+
export function hashStepText(stepText) {
|
|
28
|
+
const hash = createHash('sha256');
|
|
29
|
+
hash.update(stepText.trim());
|
|
30
|
+
return hash.digest('hex').substring(0, 16);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extract test file name from full file path
|
|
34
|
+
*
|
|
35
|
+
* @param testFilePath - Full path to the test file
|
|
36
|
+
* @returns Test file name without extension (e.g., "buttons-variety" from "buttons-variety.spec.ts")
|
|
37
|
+
*/
|
|
38
|
+
export function getTestFileName(testFilePath) {
|
|
39
|
+
const fileName = basename(testFilePath);
|
|
40
|
+
// Remove extension (e.g., "agentic.spec.ts" -> "agentic.spec" -> "agentic")
|
|
41
|
+
const nameWithoutExt = fileName.replace(/\.(spec|test)\.(ts|js|tsx|jsx)$/, '');
|
|
42
|
+
return nameWithoutExt;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the mimic directory path for a test file
|
|
46
|
+
*
|
|
47
|
+
* @param testFilePath - Full path to the test file
|
|
48
|
+
* @returns Path to the __mimic__ directory
|
|
49
|
+
*/
|
|
50
|
+
export function getMimicDir(testFilePath) {
|
|
51
|
+
const testFileDir = dirname(testFilePath);
|
|
52
|
+
return join(testFileDir, '__mimic__');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the mimic file path for a test file
|
|
56
|
+
*
|
|
57
|
+
* @param testFilePath - Full path to the test file
|
|
58
|
+
* @returns Full path to the mimic JSON file (e.g., "__mimic__/agentic.mimic.json")
|
|
59
|
+
*/
|
|
60
|
+
export function getMimicFilePath(testFilePath) {
|
|
61
|
+
const mimicDir = getMimicDir(testFilePath);
|
|
62
|
+
const testFileName = getTestFileName(testFilePath);
|
|
63
|
+
return join(mimicDir, `${testFileName}.mimic.json`);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Ensure the __mimic__ directory exists
|
|
67
|
+
*
|
|
68
|
+
* @param testFilePath - Full path to the test file
|
|
69
|
+
* @returns Promise that resolves when directory is created or already exists
|
|
70
|
+
*/
|
|
71
|
+
async function ensureMimicDir(testFilePath) {
|
|
72
|
+
const mimicDir = getMimicDir(testFilePath);
|
|
73
|
+
try {
|
|
74
|
+
await fs.mkdir(mimicDir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Directory might already exist, which is fine
|
|
78
|
+
if (error instanceof Error && !error.message.includes('EEXIST')) {
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get the snapshot directory path for a test file (legacy support)
|
|
85
|
+
*
|
|
86
|
+
* @param testFilePath - Directory path of the test file
|
|
87
|
+
* @returns Path to the .mimic-snapshots directory
|
|
88
|
+
* @deprecated Use getMimicDir instead
|
|
89
|
+
*/
|
|
90
|
+
export function getSnapshotDir(testFilePath) {
|
|
91
|
+
return join(testFilePath, '.mimic-snapshots');
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get the snapshot file path for a specific test (legacy support)
|
|
95
|
+
*
|
|
96
|
+
* @param testFilePath - Directory path of the test file
|
|
97
|
+
* @param testHash - Hash identifier for the test
|
|
98
|
+
* @returns Full path to the snapshot JSON file
|
|
99
|
+
* @deprecated Use getMimicFilePath instead
|
|
100
|
+
*/
|
|
101
|
+
export function getSnapshotPath(testFilePath, testHash) {
|
|
102
|
+
const snapshotDir = getSnapshotDir(testFilePath);
|
|
103
|
+
return join(snapshotDir, `${testHash}.json`);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Read a snapshot from disk
|
|
107
|
+
*
|
|
108
|
+
* @param testFilePath - Full path to the test file
|
|
109
|
+
* @param testHash - Hash identifier for the test
|
|
110
|
+
* @returns Snapshot object if found, null otherwise
|
|
111
|
+
*/
|
|
112
|
+
export async function getSnapshot(testFilePath, testHash) {
|
|
113
|
+
if (!testFilePath) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const mimicFilePath = getMimicFilePath(testFilePath);
|
|
117
|
+
try {
|
|
118
|
+
const content = await fs.readFile(mimicFilePath, 'utf-8');
|
|
119
|
+
const mimicFile = JSON.parse(content);
|
|
120
|
+
// Find the test by testHash
|
|
121
|
+
const snapshot = mimicFile.tests?.find(test => test.testHash === testHash);
|
|
122
|
+
return snapshot || null;
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
// File doesn't exist or is invalid - return null
|
|
126
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
127
|
+
// Try legacy location for backward compatibility
|
|
128
|
+
return getSnapshotLegacy(testFilePath, testHash);
|
|
129
|
+
}
|
|
130
|
+
// For other errors (parse errors, etc.), log and return null
|
|
131
|
+
console.warn(`Failed to read snapshot at ${mimicFilePath}:`, error);
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Read a snapshot from legacy location (backward compatibility)
|
|
137
|
+
*
|
|
138
|
+
* @param testFilePath - Full path to the test file
|
|
139
|
+
* @param testHash - Hash identifier for the test
|
|
140
|
+
* @returns Snapshot object if found, null otherwise
|
|
141
|
+
*/
|
|
142
|
+
async function getSnapshotLegacy(testFilePath, testHash) {
|
|
143
|
+
const testFileDir = dirname(testFilePath);
|
|
144
|
+
const snapshotPath = getSnapshotPath(testFileDir, testHash);
|
|
145
|
+
try {
|
|
146
|
+
const content = await fs.readFile(snapshotPath, 'utf-8');
|
|
147
|
+
const snapshot = JSON.parse(content);
|
|
148
|
+
return snapshot;
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
// File doesn't exist or is invalid - return null
|
|
152
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Save a snapshot to disk
|
|
160
|
+
*
|
|
161
|
+
* Saves all tests from a test file into a single JSON file in __mimic__ directory.
|
|
162
|
+
* Updates existing test entry if testHash already exists, otherwise adds new test.
|
|
163
|
+
*
|
|
164
|
+
* @param testFilePath - Full path to the test file
|
|
165
|
+
* @param snapshot - Snapshot object to save
|
|
166
|
+
* @returns Promise that resolves when snapshot is saved
|
|
167
|
+
*/
|
|
168
|
+
export async function saveSnapshot(testFilePath, snapshot) {
|
|
169
|
+
if (!testFilePath) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
await ensureMimicDir(testFilePath);
|
|
173
|
+
const mimicFilePath = getMimicFilePath(testFilePath);
|
|
174
|
+
// Read existing file if it exists
|
|
175
|
+
let mimicFile = { tests: [] };
|
|
176
|
+
try {
|
|
177
|
+
const content = await fs.readFile(mimicFilePath, 'utf-8');
|
|
178
|
+
mimicFile = JSON.parse(content);
|
|
179
|
+
// Ensure tests array exists
|
|
180
|
+
if (!mimicFile.tests) {
|
|
181
|
+
mimicFile.tests = [];
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
// File doesn't exist - start with empty structure
|
|
186
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
187
|
+
mimicFile = { tests: [] };
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
// For other errors, log and start fresh
|
|
191
|
+
console.warn(`Failed to read existing mimic file at ${mimicFilePath}, starting fresh:`, error);
|
|
192
|
+
mimicFile = { tests: [] };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Update timestamps in flags
|
|
196
|
+
const now = new Date().toISOString();
|
|
197
|
+
if (!snapshot.flags) {
|
|
198
|
+
snapshot.flags = {
|
|
199
|
+
needsRetry: false,
|
|
200
|
+
hasErrors: false,
|
|
201
|
+
troubleshootingEnabled: false,
|
|
202
|
+
skipSnapshot: false,
|
|
203
|
+
forceRegenerate: false,
|
|
204
|
+
debugMode: false,
|
|
205
|
+
createdAt: now,
|
|
206
|
+
lastPassedAt: now,
|
|
207
|
+
lastFailedAt: null,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
snapshot.flags.lastPassedAt = now;
|
|
212
|
+
if (!snapshot.flags.createdAt) {
|
|
213
|
+
snapshot.flags.createdAt = now;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Find existing test by testHash and update, or add new
|
|
217
|
+
const existingIndex = mimicFile.tests.findIndex(test => test.testHash === snapshot.testHash);
|
|
218
|
+
if (existingIndex >= 0) {
|
|
219
|
+
// Merge with existing test: preserve existing steps that weren't regenerated
|
|
220
|
+
const existingTest = mimicFile.tests[existingIndex];
|
|
221
|
+
// Merge stepsByHash: new steps overwrite old ones, but keep steps that weren't regenerated
|
|
222
|
+
const mergedStepsByHash = {};
|
|
223
|
+
// Start with existing steps (support both formats)
|
|
224
|
+
if (existingTest && existingTest.stepsByHash) {
|
|
225
|
+
Object.assign(mergedStepsByHash, existingTest.stepsByHash);
|
|
226
|
+
}
|
|
227
|
+
else if (existingTest && existingTest.steps) {
|
|
228
|
+
// Convert old format to new format
|
|
229
|
+
for (const step of existingTest.steps) {
|
|
230
|
+
mergedStepsByHash[step.stepHash] = step;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// Add/overwrite with new steps from snapshot
|
|
234
|
+
if (snapshot.stepsByHash) {
|
|
235
|
+
Object.assign(mergedStepsByHash, snapshot.stepsByHash);
|
|
236
|
+
}
|
|
237
|
+
else if (snapshot.steps) {
|
|
238
|
+
// Convert new snapshot's steps array to stepsByHash if needed
|
|
239
|
+
for (const step of snapshot.steps) {
|
|
240
|
+
mergedStepsByHash[step.stepHash] = step;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Build merged steps array from mergedStepsByHash, sorted by stepIndex
|
|
244
|
+
const allMergedSteps = Object.values(mergedStepsByHash);
|
|
245
|
+
allMergedSteps.sort((a, b) => a.stepIndex - b.stepIndex);
|
|
246
|
+
// Update the test with merged data
|
|
247
|
+
mimicFile.tests[existingIndex] = {
|
|
248
|
+
...snapshot,
|
|
249
|
+
stepsByHash: mergedStepsByHash,
|
|
250
|
+
steps: allMergedSteps, // Maintain backward compatibility with steps array
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
// Add new test - ensure steps array exists even if only stepsByHash is provided
|
|
255
|
+
const finalSnapshot = {
|
|
256
|
+
...snapshot,
|
|
257
|
+
steps: snapshot.steps || (snapshot.stepsByHash ? Object.values(snapshot.stepsByHash).sort((a, b) => a.stepIndex - b.stepIndex) : []),
|
|
258
|
+
stepsByHash: snapshot.stepsByHash || (snapshot.steps ? (() => {
|
|
259
|
+
const hash = {};
|
|
260
|
+
for (const step of snapshot.steps) {
|
|
261
|
+
hash[step.stepHash] = step;
|
|
262
|
+
}
|
|
263
|
+
return hash;
|
|
264
|
+
})() : {}),
|
|
265
|
+
};
|
|
266
|
+
mimicFile.tests.push(finalSnapshot);
|
|
267
|
+
}
|
|
268
|
+
// Write back to file
|
|
269
|
+
await fs.writeFile(mimicFilePath, JSON.stringify(mimicFile, null, 2), 'utf-8');
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Record a test failure timestamp
|
|
273
|
+
*
|
|
274
|
+
* Updates the snapshot's lastFailedAt timestamp and flags if the snapshot exists.
|
|
275
|
+
*
|
|
276
|
+
* @param testFilePath - Full path to the test file
|
|
277
|
+
* @param testHash - Hash identifier for the test
|
|
278
|
+
* @param failedStepIndex - Index of the step that failed (optional)
|
|
279
|
+
* @param failedStepText - Text of the step that failed (optional)
|
|
280
|
+
* @param error - Error message (optional)
|
|
281
|
+
* @returns Promise that resolves when failure is recorded
|
|
282
|
+
*/
|
|
283
|
+
export async function recordFailure(testFilePath, testHash, failedStepIndex, failedStepText, error) {
|
|
284
|
+
if (!testFilePath) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const snapshot = await getSnapshot(testFilePath, testHash);
|
|
288
|
+
if (!snapshot) {
|
|
289
|
+
// Create a minimal snapshot just for failure tracking
|
|
290
|
+
const now = new Date().toISOString();
|
|
291
|
+
const failureSnapshot = {
|
|
292
|
+
testHash,
|
|
293
|
+
testText: '',
|
|
294
|
+
steps: [],
|
|
295
|
+
stepsByHash: {},
|
|
296
|
+
flags: {
|
|
297
|
+
needsRetry: true,
|
|
298
|
+
hasErrors: true,
|
|
299
|
+
troubleshootingEnabled: false,
|
|
300
|
+
skipSnapshot: false,
|
|
301
|
+
forceRegenerate: false,
|
|
302
|
+
debugMode: false,
|
|
303
|
+
createdAt: now,
|
|
304
|
+
lastPassedAt: null,
|
|
305
|
+
lastFailedAt: now,
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
await saveSnapshot(testFilePath, failureSnapshot);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
// Update existing snapshot with failure info
|
|
312
|
+
if (!snapshot.flags) {
|
|
313
|
+
const now = new Date().toISOString();
|
|
314
|
+
snapshot.flags = {
|
|
315
|
+
needsRetry: true,
|
|
316
|
+
hasErrors: true,
|
|
317
|
+
troubleshootingEnabled: false,
|
|
318
|
+
skipSnapshot: false,
|
|
319
|
+
forceRegenerate: false,
|
|
320
|
+
debugMode: false,
|
|
321
|
+
createdAt: now,
|
|
322
|
+
lastPassedAt: null,
|
|
323
|
+
lastFailedAt: now,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
snapshot.flags.lastFailedAt = new Date().toISOString();
|
|
328
|
+
snapshot.flags.needsRetry = true;
|
|
329
|
+
snapshot.flags.hasErrors = true;
|
|
330
|
+
}
|
|
331
|
+
// Store failure details if provided (store in flags for easier access)
|
|
332
|
+
if (failedStepIndex !== undefined || failedStepText || error) {
|
|
333
|
+
snapshot.flags.failureDetails = {
|
|
334
|
+
failedStepIndex,
|
|
335
|
+
failedStepText,
|
|
336
|
+
error,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
await saveSnapshot(testFilePath, snapshot);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Determine if a snapshot should be used for replay
|
|
343
|
+
*
|
|
344
|
+
* A snapshot should be used if:
|
|
345
|
+
* - It exists
|
|
346
|
+
* - lastPassedAt is more recent than lastFailedAt (or lastFailedAt is null)
|
|
347
|
+
* - Flags don't indicate it should be skipped
|
|
348
|
+
*
|
|
349
|
+
* Note: Even in troubleshoot mode, we use snapshots if they've passed.
|
|
350
|
+
* Regeneration will happen only if replay fails.
|
|
351
|
+
*
|
|
352
|
+
* @param testFilePath - Full path to the test file
|
|
353
|
+
* @param testHash - Hash identifier for the test
|
|
354
|
+
* @param troubleshootMode - Whether troubleshoot mode is enabled (unused, kept for compatibility)
|
|
355
|
+
* @param expectedStepCount - Expected number of steps (optional)
|
|
356
|
+
* @returns true if snapshot should be used, false otherwise
|
|
357
|
+
*/
|
|
358
|
+
export async function shouldUseSnapshot(testFilePath, testHash, _troubleshootMode = false, expectedStepCount) {
|
|
359
|
+
// Use snapshots even in troubleshoot mode if they've passed
|
|
360
|
+
// Regeneration will happen only if replay fails
|
|
361
|
+
if (!testFilePath) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
const snapshot = await getSnapshot(testFilePath, testHash);
|
|
365
|
+
if (!snapshot) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
// Check if snapshot should be skipped
|
|
369
|
+
if (snapshot.flags?.skipSnapshot) {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
// Check if force regenerate is enabled
|
|
373
|
+
if (snapshot.flags?.forceRegenerate) {
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
// Validate that snapshot has at least as many steps as expected input lines
|
|
377
|
+
if (expectedStepCount !== undefined) {
|
|
378
|
+
// Count unique steps in snapshot
|
|
379
|
+
// Support both new format (stepsByHash) and old format (steps array)
|
|
380
|
+
let snapshotStepCount;
|
|
381
|
+
if (snapshot.stepsByHash) {
|
|
382
|
+
snapshotStepCount = Object.keys(snapshot.stepsByHash).length;
|
|
383
|
+
}
|
|
384
|
+
else if (snapshot.steps) {
|
|
385
|
+
const uniqueStepIndices = new Set(snapshot.steps.map((step) => step.stepIndex));
|
|
386
|
+
snapshotStepCount = uniqueStepIndices.size;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
snapshotStepCount = 0;
|
|
390
|
+
}
|
|
391
|
+
if (snapshotStepCount < expectedStepCount) {
|
|
392
|
+
// Snapshot is incomplete - don't use it
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// If never passed, don't use snapshot
|
|
397
|
+
if (!snapshot.flags?.lastPassedAt) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
// If never failed, use snapshot
|
|
401
|
+
if (!snapshot.flags?.lastFailedAt) {
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
// Compare timestamps: use snapshot if pass is more recent than failure
|
|
405
|
+
const passTime = new Date(snapshot.flags.lastPassedAt).getTime();
|
|
406
|
+
const failTime = new Date(snapshot.flags.lastFailedAt).getTime();
|
|
407
|
+
return passTime > failTime;
|
|
408
|
+
}
|
|
409
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/mimic/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGpD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB;IAClD,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IACxC,4EAA4E;IAC5E,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,iCAAiC,EAAE,EAAE,CAAC,CAAC;IAC/E,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB;IAC9C,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,YAAoB;IACnD,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,YAAY,aAAa,CAAC,CAAC;AACtD,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,cAAc,CAAC,YAAoB;IAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,+CAA+C;QAC/C,IAAI,KAAK,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AASD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,YAAoB;IACjD,OAAO,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,QAAgB;IACpE,MAAM,WAAW,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;AAC/C,CAAC;AAGD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,YAAoB,EACpB,QAAgB;IAEhB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;QAEnD,4BAA4B;QAC5B,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAC3E,OAAO,QAAQ,IAAI,IAAI,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iDAAiD;QACjD,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAAa,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClF,iDAAiD;YACjD,OAAO,iBAAiB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACnD,CAAC;QACD,6DAA6D;QAC7D,OAAO,CAAC,IAAI,CAAC,8BAA8B,aAAa,GAAG,EAAE,KAAK,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,iBAAiB,CAC9B,YAAoB,EACpB,QAAgB;IAEhB,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAa,CAAC;QACjD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iDAAiD;QACjD,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAAa,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,YAAoB,EACpB,QAAkB;IAElB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IAED,MAAM,cAAc,CAAC,YAAY,CAAC,CAAC;IACnC,MAAM,aAAa,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAErD,kCAAkC;IAClC,IAAI,SAAS,GAAc,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC1D,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;QAC7C,4BAA4B;QAC5B,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YACrB,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,kDAAkD;QAClD,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAAa,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClF,SAAS,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,wCAAwC;YACxC,OAAO,CAAC,IAAI,CAAC,yCAAyC,aAAa,mBAAmB,EAAE,KAAK,CAAC,CAAC;YAC/F,SAAS,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpB,QAAQ,CAAC,KAAK,GAAG;YACf,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,KAAK;YAChB,sBAAsB,EAAE,KAAK;YAC7B,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,KAAK;YACtB,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,GAAG;YACd,YAAY,EAAE,GAAG;YACjB,YAAY,EAAE,IAAI;SACnB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YAC9B,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC;QACjC,CAAC;IACH,CAAC;IAED,wDAAwD;IACxD,MAAM,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC7F,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QACvB,6EAA6E;QAC7E,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAEpD,2FAA2F;QAC3F,MAAM,iBAAiB,GAAiC,EAAE,CAAC;QAE3D,mDAAmD;QACnD,IAAI,YAAY,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;QAC7D,CAAC;aAAM,IAAI,YAAY,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;YAC9C,mCAAmC;YACnC,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;gBACtC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC1B,8DAA8D;YAC9D,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAClC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,uEAAuE;QACvE,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACxD,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAEzD,mCAAmC;QACnC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG;YAC/B,GAAG,QAAQ;YACX,WAAW,EAAE,iBAAiB;YAC9B,KAAK,EAAE,cAAc,EAAE,mDAAmD;SAC3E,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,gFAAgF;QAChF,MAAM,aAAa,GAAa;YAC9B,GAAG,QAAQ;YACX,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACpI,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;gBAC3D,MAAM,IAAI,GAAiC,EAAE,CAAC;gBAC9C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;oBAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;gBAC7B,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACX,CAAC;QACF,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC;IAED,qBAAqB;IACrB,MAAM,EAAE,CAAC,SAAS,CAChB,aAAa,EACb,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAClC,OAAO,CACR,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,YAAoB,EACpB,QAAgB,EAChB,eAAwB,EACxB,cAAuB,EACvB,KAAc;IAEd,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,sDAAsD;QACtD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,eAAe,GAAa;YAChC,QAAQ;YACR,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,WAAW,EAAE,EAAE;YACf,KAAK,EAAE;gBACL,UAAU,EAAE,IAAI;gBAChB,SAAS,EAAE,IAAI;gBACf,sBAAsB,EAAE,KAAK;gBAC7B,YAAY,EAAE,KAAK;gBACnB,eAAe,EAAE,KAAK;gBACtB,SAAS,EAAE,KAAK;gBAChB,SAAS,EAAE,GAAG;gBACd,YAAY,EAAE,IAAI;gBAClB,YAAY,EAAE,GAAG;aAClB;SACF,CAAC;QACF,MAAM,YAAY,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,6CAA6C;IAC7C,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,QAAQ,CAAC,KAAK,GAAG;YACf,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,IAAI;YACf,sBAAsB,EAAE,KAAK;YAC7B,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,KAAK;YACtB,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,GAAG;YACd,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,GAAG;SAClB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACvD,QAAQ,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;QACjC,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IAClC,CAAC;IAED,uEAAuE;IACvE,IAAI,eAAe,KAAK,SAAS,IAAI,cAAc,IAAI,KAAK,EAAE,CAAC;QAC5D,QAAQ,CAAC,KAAa,CAAC,cAAc,GAAG;YACvC,eAAe;YACf,cAAc;YACd,KAAK;SACN,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,YAAoB,EACpB,QAAgB,EAChB,oBAA6B,KAAK,EAClC,iBAA0B;IAE1B,4DAA4D;IAC5D,gDAAgD;IAEhD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,sCAAsC;IACtC,IAAI,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uCAAuC;IACvC,IAAI,QAAQ,CAAC,KAAK,EAAE,eAAe,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,4EAA4E;IAC5E,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,iCAAiC;QACjC,qEAAqE;QACrE,IAAI,iBAAyB,CAAC;QAC9B,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACzB,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;QAC/D,CAAC;aAAM,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC1B,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAA2B,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YACvG,iBAAiB,GAAG,iBAAiB,CAAC,IAAI,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,iBAAiB,GAAG,CAAC,CAAC;QACxB,CAAC;QAED,IAAI,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;YAC1C,wCAAwC;YACxC,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,sCAAsC;IACtC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,gCAAgC;IAChC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uEAAuE;IACvE,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IACjE,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IAEjE,OAAO,QAAQ,GAAG,QAAQ,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot-related Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Types for storing and replaying test execution snapshots.
|
|
5
|
+
*/
|
|
6
|
+
import type { NavigationAction } from './schema/action.js';
|
|
7
|
+
import type { ClickActionResult } from './schema/action.js';
|
|
8
|
+
import type { FormActionResult } from './forms.js';
|
|
9
|
+
import type { SelectorDescriptor } from './selectorTypes.js';
|
|
10
|
+
/**
|
|
11
|
+
* Target element information using best selector with mimicId fallback
|
|
12
|
+
*/
|
|
13
|
+
export interface MarkerTargetElement {
|
|
14
|
+
/** The best selector descriptor for the element (primary) */
|
|
15
|
+
selector: SelectorDescriptor;
|
|
16
|
+
/** The mimic ID assigned to the element by the markers system (fallback) */
|
|
17
|
+
mimicId: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A single step in a test execution snapshot
|
|
21
|
+
*/
|
|
22
|
+
export interface SnapshotStep {
|
|
23
|
+
/** Hash of the step text for identification */
|
|
24
|
+
stepHash: string;
|
|
25
|
+
/** Index of the step in the test (0-based) */
|
|
26
|
+
stepIndex: number;
|
|
27
|
+
/** Original step text (Gherkin step) */
|
|
28
|
+
stepText: string;
|
|
29
|
+
/** Type of action (navigation, click, form update) */
|
|
30
|
+
actionKind: 'navigation' | 'click' | 'form update';
|
|
31
|
+
/** Full action details (varies by actionKind) */
|
|
32
|
+
actionDetails: NavigationAction | ClickActionResult | FormActionResult;
|
|
33
|
+
/** Target element information using marker ID (for click and form actions) */
|
|
34
|
+
targetElement?: MarkerTargetElement;
|
|
35
|
+
/** Timestamp when this step was executed */
|
|
36
|
+
executedAt: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Flags for test execution metadata and configuration
|
|
40
|
+
*/
|
|
41
|
+
export interface SnapshotFlags {
|
|
42
|
+
/** Metadata flags */
|
|
43
|
+
needsRetry: boolean;
|
|
44
|
+
hasErrors: boolean;
|
|
45
|
+
troubleshootingEnabled: boolean;
|
|
46
|
+
/** Configuration flags */
|
|
47
|
+
skipSnapshot: boolean;
|
|
48
|
+
forceRegenerate: boolean;
|
|
49
|
+
debugMode: boolean;
|
|
50
|
+
/** Timestamps */
|
|
51
|
+
createdAt: string;
|
|
52
|
+
lastPassedAt: string | null;
|
|
53
|
+
lastFailedAt: string | null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Complete snapshot of a test execution
|
|
57
|
+
*/
|
|
58
|
+
export interface Snapshot {
|
|
59
|
+
/** Hash identifier for this test */
|
|
60
|
+
testHash: string;
|
|
61
|
+
/** Original test text (mimic template string) */
|
|
62
|
+
testText: string;
|
|
63
|
+
/** Steps indexed by stepHash (command line text hash) for efficient lookup and selective regeneration */
|
|
64
|
+
stepsByHash: Record<string, SnapshotStep>;
|
|
65
|
+
/** Array of executed steps (for backward compatibility and ordered replay) */
|
|
66
|
+
steps: SnapshotStep[];
|
|
67
|
+
/** Flags for troubleshooting and configuration */
|
|
68
|
+
flags: SnapshotFlags;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Result of executing a single step (for snapshot creation)
|
|
72
|
+
*/
|
|
73
|
+
export interface StepExecutionResult {
|
|
74
|
+
/** Index of the step in the test (0-based) */
|
|
75
|
+
stepIndex: number;
|
|
76
|
+
/** Original step text (Gherkin step) */
|
|
77
|
+
stepText: string;
|
|
78
|
+
/** Type of action (navigation, click, form update) */
|
|
79
|
+
actionKind: 'navigation' | 'click' | 'form update';
|
|
80
|
+
/** Full action details (varies by actionKind) */
|
|
81
|
+
actionDetails: NavigationAction | ClickActionResult | FormActionResult;
|
|
82
|
+
/** Target element information using marker ID (for click and form actions) */
|
|
83
|
+
targetElement?: MarkerTargetElement;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mimic/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,UAAU,EAAE,YAAY,GAAG,OAAO,GAAG,aAAa,CAAC;IACnD,iDAAiD;IACjD,aAAa,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IACvE,8EAA8E;IAC9E,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,sBAAsB,EAAE,OAAO,CAAC;IAChC,0BAA0B;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,yGAAyG;IACzG,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1C,8EAA8E;IAC9E,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,kDAAkD;IAClD,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,UAAU,EAAE,YAAY,GAAG,OAAO,GAAG,aAAa,CAAC;IACnD,iDAAiD;IACjD,aAAa,EAAE,gBAAgB,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IACvE,8EAA8E;IAC9E,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mimic/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/dist/mimic.d.ts
CHANGED
|
@@ -4,23 +4,48 @@
|
|
|
4
4
|
import { Page, TestInfo } from '@playwright/test';
|
|
5
5
|
import type { LanguageModel } from 'ai';
|
|
6
6
|
export type Mimic = (steps: TemplateStringsArray, ...args: unknown[]) => Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Test context that tracks previous state and actions for better decision-making
|
|
9
|
+
*/
|
|
10
|
+
export interface TestContext {
|
|
11
|
+
/** Previous steps that have been executed */
|
|
12
|
+
previousSteps: Array<{
|
|
13
|
+
stepIndex: number;
|
|
14
|
+
stepText: string;
|
|
15
|
+
actionKind: string;
|
|
16
|
+
url?: string;
|
|
17
|
+
pageTitle?: string;
|
|
18
|
+
}>;
|
|
19
|
+
/** Current page state */
|
|
20
|
+
currentState: {
|
|
21
|
+
url: string;
|
|
22
|
+
pageTitle: string;
|
|
23
|
+
};
|
|
24
|
+
/** Total number of steps in the test */
|
|
25
|
+
totalSteps: number;
|
|
26
|
+
/** Current step index */
|
|
27
|
+
currentStepIndex: number;
|
|
28
|
+
}
|
|
7
29
|
/**
|
|
8
30
|
* Minimal flow function that takes a Playwright page and input string
|
|
9
31
|
*
|
|
10
32
|
* @param page - Playwright Page object
|
|
11
33
|
* @param input - Input string to process
|
|
34
|
+
* @param testFilePath - Directory path of the test file (for snapshot storage)
|
|
35
|
+
* @param troubleshootMode - Whether troubleshoot mode is enabled
|
|
12
36
|
* @returns Flow execution result with validated context
|
|
13
37
|
*/
|
|
14
|
-
export declare function mimic(input: string, { page, brains, testInfo }: {
|
|
38
|
+
export declare function mimic(input: string, { page, brains, testInfo, testFilePath, troubleshootMode }: {
|
|
15
39
|
page: Page;
|
|
16
40
|
brains: LanguageModel;
|
|
17
|
-
|
|
18
|
-
|
|
41
|
+
testInfo: TestInfo | undefined;
|
|
42
|
+
testFilePath?: string;
|
|
43
|
+
troubleshootMode?: boolean;
|
|
19
44
|
}): Promise<void>;
|
|
20
45
|
export declare const createMimic: (config: {
|
|
21
46
|
page: Page;
|
|
22
47
|
brains: LanguageModel;
|
|
23
|
-
eyes
|
|
48
|
+
eyes?: LanguageModel;
|
|
24
49
|
testInfo?: TestInfo;
|
|
25
50
|
}) => (prompt: TemplateStringsArray, ...args: unknown[]) => Promise<void>;
|
|
26
51
|
//# sourceMappingURL=mimic.d.ts.map
|
package/dist/mimic.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mimic.d.ts","sourceRoot":"","sources":["../src/mimic.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAQ,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"mimic.d.ts","sourceRoot":"","sources":["../src/mimic.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAQ,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAoBxC,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,aAAa,EAAE,KAAK,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,yBAAyB;IACzB,YAAY,EAAE;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAoHD;;;;;;;;GAQG;AACH,wBAAsB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,EAAE;IACrG,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,iBAoeA;AAeD,eAAO,MAAM,WAAW,GAAI,QAAQ;IAClC,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,MASe,QAAQ,oBAAoB,EAAE,GAAG,MAAM,OAAO,EAAE,kBAU/D,CAAA"}
|