@skyramp/mcp 0.4.2-rc.2 → 0.4.2-rc.3
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/build/tools/generate-tests/generateE2ERestTool.d.ts +0 -1
- package/build/tools/generate-tests/generateE2ERestTool.js +1 -9
- package/build/tools/generate-tests/generateUIRestTool.d.ts +0 -2
- package/build/tools/generate-tests/generateUIRestTool.js +1 -9
- package/build/types/TestTypes.d.ts +0 -7
- package/build/types/TestTypes.js +0 -20
- package/package.json +1 -1
- package/plugin/skills/enhance-assertions/reference/shared-rules.md +1 -1
- package/plugin/skills/enhance-assertions/reference/ui.md +1 -1
|
@@ -7,7 +7,6 @@ export declare class E2ETestService extends TestGenerationService {
|
|
|
7
7
|
protected buildGenerationOptions(params: BaseTestParams & {
|
|
8
8
|
responseData?: string;
|
|
9
9
|
playwrightInput?: string;
|
|
10
|
-
testName?: string;
|
|
11
10
|
}): any;
|
|
12
11
|
protected handleApiAnalysis(_params: BaseTestParams): Promise<CallToolResult | null>;
|
|
13
12
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { baseSchema, baseTraceSchema, TestType, codeRefactoringSchema,
|
|
2
|
+
import { baseSchema, baseTraceSchema, TestType, codeRefactoringSchema, } from "../../types/TestTypes.js";
|
|
3
3
|
import { TestGenerationService, } from "../../services/TestGenerationService.js";
|
|
4
4
|
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
5
5
|
import { toolError } from "../../utils/utils.js";
|
|
@@ -16,7 +16,6 @@ const e2eTestSchema = {
|
|
|
16
16
|
"from a Playwright zip that already produced one is rejected — one recording covers one scenario, and reusing " +
|
|
17
17
|
"it manufactures identical tests under names the recording never covered. Set true only when the same " +
|
|
18
18
|
"recording genuinely covers the new scenario end-to-end."),
|
|
19
|
-
testName: testNameField("testE2e"),
|
|
20
19
|
...codeRefactoringSchema.shape,
|
|
21
20
|
...baseSchema.shape,
|
|
22
21
|
};
|
|
@@ -29,11 +28,6 @@ export class E2ETestService extends TestGenerationService {
|
|
|
29
28
|
...super.buildBaseGenerationOptions(params),
|
|
30
29
|
responseData: params.responseData,
|
|
31
30
|
playwrightInput: params.playwrightInput,
|
|
32
|
-
// SKYR-4468: free-form title for the generated test, so the spec names the
|
|
33
|
-
// behaviour it verifies instead of the generic `testE2e`. The option is
|
|
34
|
-
// inert until the pinned @skyramp/skyramp release carries it — the client
|
|
35
|
-
// ignores options it does not know, so passing it early is safe.
|
|
36
|
-
testName: params.testName,
|
|
37
31
|
};
|
|
38
32
|
}
|
|
39
33
|
async handleApiAnalysis(_params) {
|
|
@@ -50,8 +44,6 @@ End-to-End tests validate complete user journeys by testing the entire applicati
|
|
|
50
44
|
TRACE & UI INTEGRATION:
|
|
51
45
|
E2E tests require both trace files (capturing backend API interactions) and Playwright recordings (capturing UI interactions captured using start_trace_collection tool) to generate comprehensive tests that validate the complete user experience.
|
|
52
46
|
|
|
53
|
-
**Test title:** Pass \`testName\` with the behaviour this recording verifies (e.g. "Add to cart from search results"), taken from the recommendation the recording came from. Omit it and the spec is titled \`testE2e\`, which claims nothing.
|
|
54
|
-
|
|
55
47
|
**CRITICAL - When using trace parameter:**
|
|
56
48
|
If \`trace\` parameter is provided (path to a trace file), DO NOT pass \`apiSchema\` or \`endpointURL\` parameters. The trace file already contains all necessary endpoint and schema information. Passing both will cause test generation to fail.`,
|
|
57
49
|
inputSchema: e2eTestSchema,
|
|
@@ -8,7 +8,6 @@ export declare class UITestService extends TestGenerationService {
|
|
|
8
8
|
protected buildGenerationOptions(params: BaseTestParams & {
|
|
9
9
|
playwrightInput?: string;
|
|
10
10
|
uniqueUIFormInputs?: string[];
|
|
11
|
-
testName?: string;
|
|
12
11
|
}): any;
|
|
13
12
|
protected handleApiAnalysis(_params: BaseTestParams): Promise<CallToolResult | null>;
|
|
14
13
|
generateTest(params: BaseTestParams & Record<string, any>): Promise<CallToolResult>;
|
|
@@ -20,7 +19,6 @@ export declare const uiTestSchema: {
|
|
|
20
19
|
include: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString, "many">>>;
|
|
21
20
|
exclude: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString, "many">>>;
|
|
22
21
|
uniqueUIFormInputs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
23
|
-
testName: z.ZodOptional<z.ZodString>;
|
|
24
22
|
output: z.ZodEffects<z.ZodOptional<z.ZodString>, string | undefined, string | undefined>;
|
|
25
23
|
outputDir: z.ZodString;
|
|
26
24
|
force: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { baseSchema, languageSchema, TestType, codeRefactoringSchema, baseTraceSchema,
|
|
1
|
+
import { baseSchema, languageSchema, TestType, codeRefactoringSchema, baseTraceSchema, } from "../../types/TestTypes.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
4
4
|
import { TestGenerationService, } from "../../services/TestGenerationService.js";
|
|
@@ -21,11 +21,6 @@ export class UITestService extends TestGenerationService {
|
|
|
21
21
|
// SKYR-4012: create-form inputs the agent flagged as unique-constrained,
|
|
22
22
|
// so Skyramp codegen types a per-run-unique value into them.
|
|
23
23
|
uniqueUIFormInputs: params.uniqueUIFormInputs,
|
|
24
|
-
// SKYR-4468: free-form title for the generated test, so the spec names the
|
|
25
|
-
// behaviour it verifies instead of the generic `testUi`. The option is
|
|
26
|
-
// inert until the pinned @skyramp/skyramp release carries it — the client
|
|
27
|
-
// ignores options it does not know, so passing it early is safe.
|
|
28
|
-
testName: params.testName,
|
|
29
24
|
};
|
|
30
25
|
}
|
|
31
26
|
async handleApiAnalysis(_params) {
|
|
@@ -91,7 +86,6 @@ export const uiTestSchema = {
|
|
|
91
86
|
.array(z.string().min(1))
|
|
92
87
|
.optional()
|
|
93
88
|
.describe("Create-form inputs whose value is UNIQUE-constrained (e.g. a name/slug that the backend rejects as a duplicate). Identify each by the accessible label or selector you typed into during recording (the same value passed to getByLabel/getByPlaceholder/getByRole, or a raw selector). Skyramp types a per-run-unique value into these inputs — and reuses it in later assertions — so the generated UI test can be re-run without hitting a duplicate/conflict error. Inspect the app's data model for unique constraints; omit when no create-form field is unique-constrained."),
|
|
94
|
-
testName: testNameField("testUi"),
|
|
95
89
|
output: baseSchema.shape.output,
|
|
96
90
|
outputDir: baseSchema.shape.outputDir,
|
|
97
91
|
force: baseSchema.shape.force,
|
|
@@ -129,8 +123,6 @@ This tells you exactly which frontend files changed so you record traces for the
|
|
|
129
123
|
|
|
130
124
|
**Idempotency (re-runnable create flows):** If the recorded flow creates a resource by typing into a UNIQUE-constrained field (a name/slug the backend rejects as a duplicate on a second run), pass those inputs in \`uniqueUIFormInputs\`. Skyramp then types a per-run-unique value into them (and reuses it in later assertions) so the generated test can be re-run without a duplicate/conflict failure.
|
|
131
125
|
|
|
132
|
-
**Test title:** Pass \`testName\` with the behaviour this recording verifies (e.g. "Add to cart from search results"), taken from the recommendation the recording came from. Omit it and the spec is titled \`testUi\`, which claims nothing.
|
|
133
|
-
|
|
134
126
|
**DOM Analyzer tools for blueprint-aware recording:** alongside the basic \`browser_*\` interaction tools, the Skyramp MCP exposes \`browser_blueprint\` (canonical PageBlueprint capture). This enables semantic target selection and delta-derived assertions: capture a blueprint before each meaningful action, perform the action, then capture again — the delta between the two grounds your assertions in observable state changes rather than author guesses about what "success" looks like.
|
|
135
127
|
|
|
136
128
|
**CRITICAL: Do NOT use skyramp_start_trace_collection/skyramp_stop_trace_collection for UI test recording — use browser_* tools + skyramp_export_zip instead.**`,
|
|
@@ -255,13 +255,6 @@ export declare const codeRefactoringSchema: z.ZodObject<{
|
|
|
255
255
|
codeReuse?: boolean | undefined;
|
|
256
256
|
modularizeCode?: boolean | undefined;
|
|
257
257
|
}>;
|
|
258
|
-
/** The `testName` field for a recording-driven generation tool.
|
|
259
|
-
*
|
|
260
|
-
* Single-sourced because the description is prompt text: it is the only thing
|
|
261
|
-
* steering the agent's choice of title, it gets re-tuned against eval results,
|
|
262
|
-
* and two copies would let the UI and E2E tools drift apart silently. Each
|
|
263
|
-
* tool passes the title its own generator falls back to (SKYR-4468). */
|
|
264
|
-
export declare const testNameField: (fallbackTitle: string) => z.ZodOptional<z.ZodString>;
|
|
265
258
|
/** Test types skyramp_enhance_assertions supports — single-sourced so the
|
|
266
259
|
* tool's schema enum and generation-time baseline seeding cannot drift
|
|
267
260
|
* (contract additionally requires provider mode at the seeding site). */
|
package/build/types/TestTypes.js
CHANGED
|
@@ -291,26 +291,6 @@ export const codeRefactoringSchema = z.object({
|
|
|
291
291
|
.default(false)
|
|
292
292
|
.describe("Whether to modularize the code"),
|
|
293
293
|
});
|
|
294
|
-
/** The `testName` field for a recording-driven generation tool.
|
|
295
|
-
*
|
|
296
|
-
* Single-sourced because the description is prompt text: it is the only thing
|
|
297
|
-
* steering the agent's choice of title, it gets re-tuned against eval results,
|
|
298
|
-
* and two copies would let the UI and E2E tools drift apart silently. Each
|
|
299
|
-
* tool passes the title its own generator falls back to (SKYR-4468). */
|
|
300
|
-
export const testNameField = (fallbackTitle) => z
|
|
301
|
-
.string()
|
|
302
|
-
// .trim() normalises incidental whitespace and, combined with .min(1),
|
|
303
|
-
// rejects a whitespace-only title, which would otherwise produce a
|
|
304
|
-
// meaningless test title and identifier (SKYR-4468).
|
|
305
|
-
.trim()
|
|
306
|
-
.min(1)
|
|
307
|
-
.optional()
|
|
308
|
-
.describe("Title for the generated test. Name the BEHAVIOUR this recording verifies, " +
|
|
309
|
-
"taken from the recommendation the recording came from — not the page it happens on. " +
|
|
310
|
-
'Example: "Add to cart from search results", not "Search page". ' +
|
|
311
|
-
"Skyramp emits it verbatim as the Playwright test title for TypeScript/JavaScript, " +
|
|
312
|
-
"and as a snake_case `def test_<name>` identifier for Python. " +
|
|
313
|
-
`Omit it and the test stays titled \`${fallbackTitle}\`, which claims nothing.`);
|
|
314
294
|
/** Test types skyramp_enhance_assertions supports — single-sourced so the
|
|
315
295
|
* tool's schema enum and generation-time baseline seeding cannot drift
|
|
316
296
|
* (contract additionally requires provider mode at the seeding site). */
|
package/package.json
CHANGED
|
@@ -26,7 +26,7 @@ Apply only to new test functions you are adding and existing test functions affe
|
|
|
26
26
|
|
|
27
27
|
Before editing `$2`, you must output a `<thinking>` block. It states the behaviour each test evaluates, then works through the rules for the responses that behaviour depends on, so no rule that applies is overlooked. The JSON array must match the `rule_checklist` template that accompanies the `$0` rules. Use the template's keys verbatim; each key is the slug shown in that rule's heading. Every key must appear — `[]` where the rule does not apply.
|
|
28
28
|
|
|
29
|
-
1. For each test function in scope, name the behaviour it evaluates in one line, taken from the recommendation it came from.
|
|
29
|
+
1. For each test function in scope, name the behaviour it evaluates in one line, taken from the recommendation it came from. Generated test functions are usually named `test_integration` or `testUi`, which claim nothing — use the name only when it is specific enough to add something, and never treat a generic one as evidence the test has no single behaviour. Then scan `$2` and the expected responses for the code change tested.
|
|
30
30
|
2. Classify each response first by its response status type and then assign the applicable assertion rules to the response.
|
|
31
31
|
- Success with body (2xx with a response body): all assertion rules below may apply — echo-back of request fields, computed response fields, array / items validation, and chained values across steps.
|
|
32
32
|
- Success with no body (200/202/204 with an empty body — e.g. logout/cancel/submit action endpoints): assert the status code only. Also apply chained-values rules if a follow-up step uses this response's ID.
|
|
@@ -126,7 +126,7 @@ if (await existingSecret.isVisible().catch(() => false)) {
|
|
|
126
126
|
|
|
127
127
|
Before editing `$2`, you must output a `<thinking>` block. It states the behaviour each test evaluates, then works through the rules for the items that behaviour depends on, so no rule that applies is overlooked. The JSON array should match the template below — every assertion category and every rule title under it must appear as a key, with `[]` where the rule does not apply.
|
|
128
128
|
|
|
129
|
-
1. For each test in scope, name the behaviour it evaluates in one line, taken from the recommendation it came from, and name the page where that behaviour shows.
|
|
129
|
+
1. For each test in scope, name the behaviour it evaluates in one line, taken from the recommendation it came from, and name the page where that behaviour shows. Generated specs are usually named `testUi`, which claims nothing — use the name only when it is specific enough to add something.
|
|
130
130
|
2. Selector inventory — list every selector already present in `$2` (`data-testid`, role + name, text, label, etc.). New assertions may use only selectors from this list. An assertion the recorder dropped because it failed during recording may use the selector of the element named in that recording's blueprint capture. Do not invent `data-testid` values, role names, or aria attributes. Also note captured network responses, repeated element patterns, exact rendered text/value/attribute from trace/source, and existing `toBeVisible()` assertions whose exact text is knowable.
|
|
131
131
|
3. Process — Replay → Identify → Fix or Add — walk through these three steps explicitly.
|
|
132
132
|
a. Replay the scenario mentally. At each state-changing action (form submit, item add/edit/delete), ask: "What is the EXPECTED outcome based on the action performed?"
|