@fasttest-ai/qa-agent 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install.js +3 -0
- package/bin/qa-agent.js +7 -2
- package/dist/actions.d.ts +3 -0
- package/dist/actions.js +38 -4
- package/dist/actions.js.map +1 -1
- package/dist/browser.d.ts +30 -0
- package/dist/browser.js +120 -6
- package/dist/browser.js.map +1 -1
- package/dist/cli.d.ts +3 -3
- package/dist/cli.js +5 -5
- package/dist/cli.js.map +1 -1
- package/dist/cloud.d.ts +96 -38
- package/dist/cloud.js +96 -35
- package/dist/cloud.js.map +1 -1
- package/dist/config.d.ts +5 -4
- package/dist/config.js +20 -7
- package/dist/config.js.map +1 -1
- package/dist/healer.d.ts +5 -1
- package/dist/healer.js +106 -29
- package/dist/healer.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +697 -88
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +11 -0
- package/dist/install.js +225 -0
- package/dist/install.js.map +1 -0
- package/dist/runner.d.ts +2 -0
- package/dist/runner.js +245 -19
- package/dist/runner.js.map +1 -1
- package/dist/variables.d.ts +30 -0
- package/dist/variables.js +104 -0
- package/dist/variables.js.map +1 -0
- package/package.json +6 -3
package/dist/healer.js
CHANGED
|
@@ -28,7 +28,7 @@ const CONFIDENCE = {
|
|
|
28
28
|
* Attempt to heal a broken selector by trying 5 strategies in order.
|
|
29
29
|
* Returns the first working selector with its confidence score.
|
|
30
30
|
*/
|
|
31
|
-
export async function healSelector(page, cloud, originalSelector, failureType, errorMessage, pageUrl) {
|
|
31
|
+
export async function healSelector(page, cloud, originalSelector, failureType, errorMessage, pageUrl, context) {
|
|
32
32
|
// 1. Check Cloud for a stored pattern first (only if cloud is available)
|
|
33
33
|
if (cloud) {
|
|
34
34
|
try {
|
|
@@ -42,9 +42,10 @@ export async function healSelector(page, cloud, originalSelector, failureType, e
|
|
|
42
42
|
return { healed: false, error: classification.reason ?? "Classified as real bug" };
|
|
43
43
|
}
|
|
44
44
|
if (classification.pattern) {
|
|
45
|
-
// Validate the stored pattern still works
|
|
45
|
+
// Validate the stored pattern still works and targets the right element
|
|
46
46
|
const found = await testSelector(page, classification.pattern.healed_value);
|
|
47
|
-
|
|
47
|
+
const valid = found && await validateCandidate(page, classification.pattern.healed_value, context);
|
|
48
|
+
if (found && valid) {
|
|
48
49
|
return {
|
|
49
50
|
healed: true,
|
|
50
51
|
newSelector: classification.pattern.healed_value,
|
|
@@ -52,6 +53,10 @@ export async function healSelector(page, cloud, originalSelector, failureType, e
|
|
|
52
53
|
confidence: classification.pattern.confidence,
|
|
53
54
|
};
|
|
54
55
|
}
|
|
56
|
+
// Pattern failed — report to cloud for deprecation tracking
|
|
57
|
+
if (classification.pattern.id) {
|
|
58
|
+
reportPatternFailedQuietly(cloud, classification.pattern.id, pageUrl);
|
|
59
|
+
}
|
|
55
60
|
}
|
|
56
61
|
}
|
|
57
62
|
catch {
|
|
@@ -68,6 +73,10 @@ export async function healSelector(page, cloud, originalSelector, failureType, e
|
|
|
68
73
|
for (const strategy of strategies) {
|
|
69
74
|
const candidate = await strategy.fn();
|
|
70
75
|
if (candidate) {
|
|
76
|
+
// Validate the candidate targets the right type of element
|
|
77
|
+
const valid = await validateCandidate(page, candidate, context);
|
|
78
|
+
if (!valid)
|
|
79
|
+
continue; // Wrong element type — try next strategy
|
|
71
80
|
// Report the pattern to Cloud for future reuse (if connected)
|
|
72
81
|
if (cloud) {
|
|
73
82
|
await storePatternQuietly(cloud, failureType, originalSelector, candidate, strategy.name, CONFIDENCE[strategy.name] ?? 0.8, pageUrl);
|
|
@@ -89,13 +98,68 @@ export async function healSelector(page, cloud, originalSelector, failureType, e
|
|
|
89
98
|
// ---------------------------------------------------------------------------
|
|
90
99
|
async function testSelector(page, selector) {
|
|
91
100
|
try {
|
|
92
|
-
const
|
|
93
|
-
return
|
|
101
|
+
const count = await page.locator(selector).count();
|
|
102
|
+
return count === 1; // Reject ambiguous matches — must be exactly one element
|
|
94
103
|
}
|
|
95
104
|
catch {
|
|
96
105
|
return false;
|
|
97
106
|
}
|
|
98
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Validate that a candidate selector points to an element compatible
|
|
110
|
+
* with the step's action and description. Returns true if valid.
|
|
111
|
+
*/
|
|
112
|
+
async function validateCandidate(page, selector, context) {
|
|
113
|
+
if (!context)
|
|
114
|
+
return true;
|
|
115
|
+
try {
|
|
116
|
+
const info = await page.locator(selector).evaluate((el) => ({
|
|
117
|
+
tag: el.tagName.toLowerCase(),
|
|
118
|
+
role: el.getAttribute("role"),
|
|
119
|
+
type: el.type ?? null,
|
|
120
|
+
contentEditable: el.getAttribute("contenteditable"),
|
|
121
|
+
text: (el.textContent ?? "").trim().slice(0, 200),
|
|
122
|
+
ariaLabel: el.getAttribute("aria-label") ?? "",
|
|
123
|
+
}));
|
|
124
|
+
const action = context.action;
|
|
125
|
+
// Check action compatibility
|
|
126
|
+
if (action === "click" || action === "hover") {
|
|
127
|
+
const interactiveTags = ["button", "a", "input", "select", "summary", "details", "label", "option"];
|
|
128
|
+
const interactiveRoles = ["button", "link", "tab", "menuitem", "checkbox", "radio", "switch", "option"];
|
|
129
|
+
const isInteractive = interactiveTags.includes(info.tag) ||
|
|
130
|
+
(info.role != null && interactiveRoles.includes(info.role));
|
|
131
|
+
if (!isInteractive)
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if (action === "fill" || action === "type") {
|
|
135
|
+
const isFillable = info.tag === "input" ||
|
|
136
|
+
info.tag === "textarea" ||
|
|
137
|
+
info.contentEditable === "true" ||
|
|
138
|
+
info.contentEditable === "";
|
|
139
|
+
if (!isFillable)
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (action === "select") {
|
|
143
|
+
if (info.tag !== "select" && info.role !== "listbox" && info.role !== "combobox") {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Check description text similarity (if description contains quoted text)
|
|
148
|
+
if (context.description) {
|
|
149
|
+
const quotedMatch = context.description.match(/['"]([^'"]+)['"]/);
|
|
150
|
+
if (quotedMatch) {
|
|
151
|
+
const expectedText = quotedMatch[1].toLowerCase();
|
|
152
|
+
const elementText = (info.text + " " + info.ariaLabel).toLowerCase();
|
|
153
|
+
if (!elementText.includes(expectedText))
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return true; // If evaluation fails, don't block healing
|
|
161
|
+
}
|
|
162
|
+
}
|
|
99
163
|
/**
|
|
100
164
|
* Strategy 1: Look for a data-testid attribute near the original selector.
|
|
101
165
|
*/
|
|
@@ -107,7 +171,6 @@ async function tryDataTestId(page, original) {
|
|
|
107
171
|
return null;
|
|
108
172
|
const candidates = [
|
|
109
173
|
`[data-testid="${name}"]`,
|
|
110
|
-
`[data-testid*="${name}"]`,
|
|
111
174
|
`[data-test="${name}"]`,
|
|
112
175
|
`[data-test-id="${name}"]`,
|
|
113
176
|
];
|
|
@@ -131,8 +194,6 @@ async function tryAria(page, original) {
|
|
|
131
194
|
return null;
|
|
132
195
|
const candidates = [
|
|
133
196
|
`[aria-label="${name}"]`,
|
|
134
|
-
`[aria-label*="${name}"]`,
|
|
135
|
-
`[role][aria-label*="${name}"]`,
|
|
136
197
|
];
|
|
137
198
|
for (const sel of candidates) {
|
|
138
199
|
if (await testSelector(page, sel))
|
|
@@ -152,12 +213,14 @@ async function tryTextContent(page, original) {
|
|
|
152
213
|
const name = extractName(original);
|
|
153
214
|
if (!name)
|
|
154
215
|
return null;
|
|
155
|
-
//
|
|
216
|
+
// Use CSS attribute and ARIA selectors (Playwright 1.52+ compatible)
|
|
156
217
|
const candidates = [
|
|
157
|
-
`
|
|
158
|
-
|
|
159
|
-
`
|
|
160
|
-
`
|
|
218
|
+
`[aria-label="${name}"]`,
|
|
219
|
+
`[title="${name}"]`,
|
|
220
|
+
`[alt="${name}"]`,
|
|
221
|
+
`[placeholder="${name}"]`,
|
|
222
|
+
`role=button[name="${name}"]`,
|
|
223
|
+
`role=link[name="${name}"]`,
|
|
161
224
|
];
|
|
162
225
|
for (const sel of candidates) {
|
|
163
226
|
if (await testSelector(page, sel))
|
|
@@ -185,10 +248,6 @@ async function tryStructural(page, original) {
|
|
|
185
248
|
candidates.push(`${tag}[name="${name}"]`);
|
|
186
249
|
candidates.push(`${tag}[id*="${name}"]`);
|
|
187
250
|
candidates.push(`${tag}[class*="${name}"]`);
|
|
188
|
-
candidates.push(`form ${tag}[type="submit"]`);
|
|
189
|
-
}
|
|
190
|
-
else if (tag) {
|
|
191
|
-
candidates.push(`form >> ${tag}[type="submit"]`);
|
|
192
251
|
}
|
|
193
252
|
for (const sel of candidates) {
|
|
194
253
|
if (await testSelector(page, sel))
|
|
@@ -205,20 +264,28 @@ async function tryStructural(page, original) {
|
|
|
205
264
|
// ---------------------------------------------------------------------------
|
|
206
265
|
/**
|
|
207
266
|
* Extract a meaningful name from a CSS selector.
|
|
208
|
-
*
|
|
267
|
+
* Handles common patterns: attribute selectors, IDs, classes, name attrs.
|
|
209
268
|
*/
|
|
210
269
|
function extractName(selector) {
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
|
|
270
|
+
// 1. Try attribute selectors: [data-testid="value"], [name="value"], etc.
|
|
271
|
+
const attrMatch = selector.match(/\[(?:data-testid|data-test|data-test-id|id|name|aria-label)\s*[~|^$*]?=\s*["']([^"']+)["']\]/);
|
|
272
|
+
if (attrMatch)
|
|
273
|
+
return attrMatch[1];
|
|
274
|
+
// 2. Extract from #id
|
|
275
|
+
const idMatch = selector.match(/#([\w-]+)/);
|
|
276
|
+
if (idMatch)
|
|
277
|
+
return idMatch[1];
|
|
278
|
+
// 3. Extract from .class (use the last/most-specific class)
|
|
279
|
+
const classMatches = [...selector.matchAll(/\.([\w-]+)/g)];
|
|
280
|
+
if (classMatches.length > 0)
|
|
281
|
+
return classMatches[classMatches.length - 1][1];
|
|
282
|
+
// 4. Extract from [name="value"]
|
|
283
|
+
const nameMatch = selector.match(/\[name=["']([^"']+)["']\]/);
|
|
284
|
+
if (nameMatch)
|
|
285
|
+
return nameMatch[1];
|
|
286
|
+
// 5. Last resort: first word that looks like an identifier (3+ chars)
|
|
287
|
+
const wordMatch = selector.match(/[a-zA-Z][\w-]{2,}/);
|
|
288
|
+
return wordMatch?.[0] ?? null;
|
|
222
289
|
}
|
|
223
290
|
async function storePatternQuietly(cloud, failureType, originalValue, healedValue, strategy, confidence, pageUrl) {
|
|
224
291
|
try {
|
|
@@ -235,4 +302,14 @@ async function storePatternQuietly(cloud, failureType, originalValue, healedValu
|
|
|
235
302
|
// Non-fatal — pattern storage failure shouldn't block test execution
|
|
236
303
|
}
|
|
237
304
|
}
|
|
305
|
+
async function reportPatternFailedQuietly(cloud, patternId, pageUrl) {
|
|
306
|
+
try {
|
|
307
|
+
await cloud.post(`/qa/healing/patterns/${patternId}/failed`, {
|
|
308
|
+
page_url: pageUrl,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
// Non-fatal
|
|
313
|
+
}
|
|
314
|
+
}
|
|
238
315
|
//# sourceMappingURL=healer.js.map
|
package/dist/healer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"healer.js","sourceRoot":"","sources":["../src/healer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"healer.js","sourceRoot":"","sources":["../src/healer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAmBH,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAC9E,MAAM,UAAU,GAA2B;IACzC,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,EAAE,EAAE,IAAI;CACT,CAAC;AAEF,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAU,EACV,KAAyB,EACzB,gBAAwB,EACxB,WAAmB,EACnB,YAAoB,EACpB,OAAe,EACf,OAAwB;IAExB,yEAAyE;IACzE,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,cAAc,GAAG,MAAM,KAAK,CAAC,IAAI,CAWpC,sBAAsB,EAAE;gBACzB,YAAY,EAAE,WAAW;gBACzB,QAAQ,EAAE,gBAAgB;gBAC1B,QAAQ,EAAE,OAAO;gBACjB,aAAa,EAAE,YAAY;aAC5B,CAAC,CAAC;YAEH,IAAI,cAAc,CAAC,WAAW,EAAE,CAAC;gBAC/B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,MAAM,IAAI,wBAAwB,EAAE,CAAC;YACrF,CAAC;YAED,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;gBAC3B,wEAAwE;gBACxE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBAC5E,MAAM,KAAK,GAAG,KAAK,IAAI,MAAM,iBAAiB,CAAC,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;gBACnG,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;oBACnB,OAAO;wBACL,MAAM,EAAE,IAAI;wBACZ,WAAW,EAAE,cAAc,CAAC,OAAO,CAAC,YAAY;wBAChD,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,QAAQ;wBACzC,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,UAAU;qBAC9C,CAAC;gBACJ,CAAC;gBACD,4DAA4D;gBAC5D,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;oBAC9B,0BAA0B,CAAC,KAAM,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;QAC/C,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,MAAM,UAAU,GAGX;QACH,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE;QACxE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE;QAC3D,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE;QAClE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,gBAAgB,CAAC,EAAE;KACxE,CAAC;IAEF,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,SAAS,EAAE,CAAC;YACd,2DAA2D;YAC3D,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YAChE,IAAI,CAAC,KAAK;gBAAE,SAAS,CAAC,yCAAyC;YAE/D,8DAA8D;YAC9D,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,OAAO,CAAC,CAAC;YACvI,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,WAAW,EAAE,SAAS;gBACtB,QAAQ,EAAE,QAAQ,CAAC,IAAI;gBACvB,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;aACtC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,yEAAyE;IACzE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;AACxE,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,KAAK,UAAU,YAAY,CAAC,IAAU,EAAE,QAAgB;IACtD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QACnD,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,yDAAyD;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,iBAAiB,CAC9B,IAAU,EACV,QAAgB,EAChB,OAAwB;IAExB,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1D,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE;YAC7B,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC;YAC7B,IAAI,EAAG,EAAuB,CAAC,IAAI,IAAI,IAAI;YAC3C,eAAe,EAAE,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC;YACnD,IAAI,EAAE,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;YACjD,SAAS,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE;SAC/C,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAE9B,6BAA6B;QAC7B,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YAC7C,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YACpG,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACxG,MAAM,aAAa,GACjB,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;gBAClC,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9D,IAAI,CAAC,aAAa;gBAAE,OAAO,KAAK,CAAC;QACnC,CAAC;QAED,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3C,MAAM,UAAU,GACd,IAAI,CAAC,GAAG,KAAK,OAAO;gBACpB,IAAI,CAAC,GAAG,KAAK,UAAU;gBACvB,IAAI,CAAC,eAAe,KAAK,MAAM;gBAC/B,IAAI,CAAC,eAAe,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,UAAU;gBAAE,OAAO,KAAK,CAAC;QAChC,CAAC;QAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACjF,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAClE,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBAClD,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;gBACrE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC;oBAAE,OAAO,KAAK,CAAC;YACxD,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,2CAA2C;IAC1D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAAC,IAAU,EAAE,QAAgB;IACvD,IAAI,CAAC;QACH,uDAAuD;QACvD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,MAAM,UAAU,GAAG;YACjB,iBAAiB,IAAI,IAAI;YACzB,eAAe,IAAI,IAAI;YACvB,kBAAkB,IAAI,IAAI;SAC3B,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,OAAO,CAAC,IAAU,EAAE,QAAgB;IACjD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,MAAM,UAAU,GAAG;YACjB,gBAAgB,IAAI,IAAI;SACzB,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAAC,IAAU,EAAE,QAAgB;IACxD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,qEAAqE;QACrE,MAAM,UAAU,GAAG;YACjB,gBAAgB,IAAI,IAAI;YACxB,WAAW,IAAI,IAAI;YACnB,SAAS,IAAI,IAAI;YACjB,iBAAiB,IAAI,IAAI;YACzB,qBAAqB,IAAI,IAAI;YAC7B,mBAAmB,IAAI,IAAI;SAC5B,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,aAAa,CAAC,IAAU,EAAE,QAAgB;IACvD,IAAI,CAAC;QACH,gDAAgD;QAChD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEnC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAE/B,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YAChB,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,UAAU,IAAI,IAAI,CAAC,CAAC;YAC1C,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,SAAS,IAAI,IAAI,CAAC,CAAC;YACzC,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,YAAY,IAAI,IAAI,CAAC,CAAC;QAC9C,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC;QAChD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;GAGG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,0EAA0E;IAC1E,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAC9B,8FAA8F,CAC/F,CAAC;IACF,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IAEnC,sBAAsB;IACtB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;IAE/B,4DAA4D;IAC5D,MAAM,YAAY,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;IAC3D,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7E,iCAAiC;IACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC9D,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IAEnC,sEAAsE;IACtE,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACtD,OAAO,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,KAAkB,EAClB,WAAmB,EACnB,aAAqB,EACrB,WAAmB,EACnB,QAAgB,EAChB,UAAkB,EAClB,OAAe;IAEf,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,sBAAsB,EAAE;YACvC,YAAY,EAAE,WAAW;YACzB,cAAc,EAAE,aAAa;YAC7B,YAAY,EAAE,WAAW;YACzB,QAAQ;YACR,UAAU;YACV,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;IACvE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,0BAA0B,CACvC,KAAkB,EAClB,SAAiB,EACjB,OAAe;IAEf,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,wBAAwB,SAAS,SAAS,EAAE;YAC3D,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* FastTest Agent — MCP server (stdio transport).
|
|
4
4
|
*
|
|
5
5
|
* This is the ONLY MCP server in the architecture.
|
|
6
6
|
* Flow: Claude Code → MCP → Local Skill → HTTPS → Cloud API
|
|
7
7
|
*
|
|
8
8
|
* Exposes:
|
|
9
|
-
* -
|
|
9
|
+
* - 21 browser tools (Playwright, runs locally)
|
|
10
10
|
* - Local-first tools (test, explore, heal — host AI drives via structured prompts)
|
|
11
11
|
* - Cloud tools (save_suite, update_suite, run, status, cancel, etc. — require setup)
|
|
12
12
|
*/
|