@skyramp/mcp 0.3.5 → 0.3.6-rc.2.ac20
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/adapters/jestAdapter.js +3 -0
- package/build/adapters/mochaAdapter.js +2 -0
- package/build/adapters/playwrightAdapter.js +3 -0
- package/build/adapters/pytestAdapter.js +12 -0
- package/build/playwright/registerPlaywrightTools.js +92 -30
- package/build/playwright/traceRecordingPrompt.d.ts +6 -0
- package/build/playwright/traceRecordingPrompt.js +6 -2
- package/build/prompts/code-reuse.d.ts +1 -2
- package/build/prompts/code-reuse.js +182 -77
- package/build/prompts/modularization/integration-test-modularization.d.ts +2 -0
- package/build/prompts/modularization/integration-test-modularization.js +83 -41
- package/build/prompts/modularization/render.d.ts +18 -0
- package/build/prompts/modularization/render.js +12 -0
- package/build/prompts/modularization/ui-test-modularization.d.ts +3 -1
- package/build/prompts/modularization/ui-test-modularization.js +89 -47
- package/build/prompts/pom-aware-code-reuse.js +3 -1
- package/build/prompts/shared-helper-policy.d.ts +57 -0
- package/build/prompts/shared-helper-policy.js +135 -0
- package/build/prompts/test-recommendation/diffExecutionPlan.js +62 -56
- package/build/prompts/test-recommendation/fullRepoCatalog.js +19 -8
- package/build/prompts/test-recommendation/recommendationShared.d.ts +28 -6
- package/build/prompts/test-recommendation/recommendationShared.js +90 -16
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +22 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.d.ts +2 -2
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +3 -3
- package/build/prompts/testbot/testbot-prompts.js +81 -35
- package/build/recommendation/budgeters/shared.js +105 -27
- package/build/recommendation/discriminators.js +13 -2
- package/build/recommendation/planRanker.d.ts +6 -6
- package/build/recommendation/planRanker.js +6 -61
- package/build/services/AnalyticsService.d.ts +7 -0
- package/build/services/AnalyticsService.js +7 -1
- package/build/services/ModularizationService.js +1 -3
- package/build/services/TestDiscoveryService.d.ts +0 -2
- package/build/services/TestDiscoveryService.js +2 -37
- package/build/services/TestGenerationService.d.ts +16 -0
- package/build/services/TestGenerationService.js +86 -10
- package/build/services/containerEnv.js +13 -12
- package/build/tools/code-refactor/codeReuseTool.js +279 -93
- package/build/tools/code-refactor/enhance-state.d.ts +49 -0
- package/build/tools/code-refactor/enhance-state.js +109 -0
- package/build/tools/code-refactor/enhanceAssertionsTool.js +34 -1
- package/build/tools/code-refactor/modularizationTool.js +9 -2
- package/build/tools/code-refactor/reuse-outcome.d.ts +23 -1
- package/build/tools/code-refactor/reuse-outcome.js +14 -4
- package/build/tools/code-refactor/reuse-state.d.ts +127 -5
- package/build/tools/code-refactor/reuse-state.js +628 -16
- package/build/tools/code-refactor/utils-verify-gates.d.ts +26 -0
- package/build/tools/code-refactor/utils-verify-gates.js +100 -0
- package/build/tools/code-refactor/verify-gates.d.ts +2 -1
- package/build/tools/code-refactor/verify-gates.js +90 -25
- package/build/tools/executeSkyrampTestTool.d.ts +19 -0
- package/build/tools/executeSkyrampTestTool.js +158 -8
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.js +16 -0
- package/build/tools/generate-tests/generateUIRestTool.d.ts +1 -0
- package/build/tools/generate-tests/generateUIRestTool.js +22 -0
- package/build/tools/generate-tests/scenarioLint.d.ts +2 -0
- package/build/tools/generate-tests/scenarioLint.js +127 -19
- package/build/tools/generate-tests/trace-reuse-guard.d.ts +20 -0
- package/build/tools/generate-tests/trace-reuse-guard.js +93 -0
- package/build/tools/runExistingTestsTool.d.ts +34 -2
- package/build/tools/runExistingTestsTool.js +104 -4
- package/build/tools/submitReportTool.d.ts +38 -38
- package/build/tools/submitReportTool.js +537 -120
- package/build/tools/test-management/analyzeChangesTool.d.ts +24 -1
- package/build/tools/test-management/analyzeChangesTool.js +71 -10
- package/build/tools/test-management/analyzeTestHealthTool.js +7 -7
- package/build/tools/test-management/registerTestPlanTool.d.ts +203 -0
- package/build/tools/test-management/registerTestPlanTool.js +70 -12
- package/build/types/ExternalTestExecution.d.ts +67 -1
- package/build/types/Recommendation.d.ts +34 -5
- package/build/types/RepositoryAnalysis.d.ts +133 -114
- package/build/types/RepositoryAnalysis.js +1 -1
- package/build/types/ReuseOutcome.d.ts +102 -6
- package/build/types/ReuseOutcome.js +16 -2
- package/build/types/TestRecommendation.js +21 -3
- package/build/types/TestTypes.js +14 -8
- package/build/types/TestbotReport.d.ts +10 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.js +1 -1
- package/build/utils/AnalysisStateManager.d.ts +57 -1
- package/build/utils/AnalysisStateManager.js +54 -5
- package/build/utils/branchDiff.d.ts +10 -0
- package/build/utils/branchDiff.js +28 -0
- package/build/utils/changedRoutes.d.ts +29 -0
- package/build/utils/changedRoutes.js +87 -0
- package/build/utils/featureFlags.d.ts +21 -0
- package/build/utils/featureFlags.js +23 -0
- package/build/utils/frontendIntegration.js +34 -4
- package/build/utils/importerHop.d.ts +2 -8
- package/build/utils/importerHop.js +15 -53
- package/build/utils/pathMatching.d.ts +38 -0
- package/build/utils/pathMatching.js +71 -0
- package/build/utils/pathSignatures.d.ts +22 -0
- package/build/utils/pathSignatures.js +57 -0
- package/build/utils/planMatchKeys.d.ts +16 -3
- package/build/utils/planMatchKeys.js +26 -10
- package/build/utils/pluralization.d.ts +10 -0
- package/build/utils/pluralization.js +18 -0
- package/build/utils/pom-catalog-parse.d.ts +52 -0
- package/build/utils/pom-catalog-parse.js +141 -0
- package/build/utils/pom-scope/selector-extractor.d.ts +12 -0
- package/build/utils/pom-scope/selector-extractor.js +34 -8
- package/build/utils/pom-verify/verify.d.ts +6 -5
- package/build/utils/pom-verify/verify.js +8 -6
- package/build/utils/reportVerification.d.ts +64 -4
- package/build/utils/reportVerification.js +228 -3
- package/build/utils/reuseRouting.d.ts +3 -0
- package/build/utils/reuseRouting.js +50 -0
- package/build/utils/routeParsers.d.ts +2 -0
- package/build/utils/routeParsers.js +65 -8
- package/build/utils/scenarioDrafting.d.ts +1 -1
- package/build/utils/scenarioDrafting.js +57 -45
- package/build/utils/subjectEndpoints.d.ts +19 -0
- package/build/utils/subjectEndpoints.js +98 -0
- package/build/utils/testFileClassification.d.ts +11 -0
- package/build/utils/testFileClassification.js +47 -0
- package/build/utils/uiPageEnumerator.d.ts +45 -19
- package/build/utils/uiPageEnumerator.js +95 -51
- package/build/utils/utils-verify/allow.d.ts +16 -0
- package/build/utils/utils-verify/allow.js +68 -0
- package/build/utils/utils-verify/call-sites.d.ts +34 -0
- package/build/utils/utils-verify/call-sites.js +154 -0
- package/build/utils/utils-verify/index.d.ts +7 -0
- package/build/utils/utils-verify/index.js +7 -0
- package/build/utils/utils-verify/language-spec.d.ts +91 -0
- package/build/utils/utils-verify/language-spec.js +210 -0
- package/build/utils/utils-verify/locate.d.ts +39 -0
- package/build/utils/utils-verify/locate.js +199 -0
- package/build/utils/utils-verify/parse.d.ts +34 -0
- package/build/utils/utils-verify/parse.js +177 -0
- package/build/utils/utils-verify/stage.d.ts +24 -0
- package/build/utils/utils-verify/stage.js +107 -0
- package/build/utils/utils-verify/verify.d.ts +63 -0
- package/build/utils/utils-verify/verify.js +168 -0
- package/build/utils/utils.d.ts +3 -1
- package/build/utils/utils.js +3 -1
- package/build/workspace/workspace.d.ts +32 -32
- package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +9 -5
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +16 -0
- package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +2 -0
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +115 -14
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +13 -1
- package/node_modules/playwright/node_modules/playwright-core/.DS_Store +0 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/htmlReport/index.html +27 -253
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-DtudTj_v.js → codeMirrorModule-DJMC4zNo.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-BW82eAUI.js +196 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-FNMuBzX1.js → codeMirrorModule-CZfp96qZ.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-gpLo02E0.js +809 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.Bq1r1URj.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.VEfqi1qN.js +5 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
- package/node_modules/playwright/package.json +1 -1
- package/package.json +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-BpDwp16L.js +0 -422
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-Co9upU5h.js +0 -1035
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.DXNIQ_dx.js +0 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CIKB3XSv.js +0 -5
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { generateSkyrampHeader, SKYRAMP_UTILS_HEADER } from "../utils/utils.js";
|
|
2
|
-
import {
|
|
2
|
+
import { isUtilsReuseEnabled } from "../utils/featureFlags.js";
|
|
3
|
+
import { isModularizeFirstTarget, isPomAwareTarget, } from "../utils/reuseRouting.js";
|
|
3
4
|
import { getPomAwareCodeReusePrompt } from "./pom-aware-code-reuse.js";
|
|
5
|
+
import { NO_SHADOWING_RULE, selectHelperPolicy, } from "./shared-helper-policy.js";
|
|
4
6
|
const LANGUAGE_MAP = {
|
|
5
7
|
python: {
|
|
6
8
|
extension: "py",
|
|
@@ -19,23 +21,159 @@ const LANGUAGE_MAP = {
|
|
|
19
21
|
fileName: "skyrampUtils.ts",
|
|
20
22
|
},
|
|
21
23
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
function genericNearDupExample(testFile) {
|
|
25
|
+
return `### Worked example
|
|
26
|
+
|
|
27
|
+
\`flow-1.spec.ts\` has:
|
|
28
|
+
\`\`\`ts
|
|
29
|
+
export async function upload_translation_file(page, fileName) {
|
|
30
|
+
await page.waitForTimeout(1500);
|
|
31
|
+
const responsePromise1 = page.waitForResponse("**/api/files/upload**");
|
|
32
|
+
const fileUploadPromise0 = page.waitForEvent("filechooser");
|
|
33
|
+
await page.getByText("Choose a file").first().click();
|
|
34
|
+
const fileChooser0 = await fileUploadPromise0;
|
|
35
|
+
await fileChooser0.setFiles(fileName);
|
|
36
|
+
const response1 = await responsePromise1;
|
|
37
|
+
await page.waitForTimeout(1500);
|
|
27
38
|
}
|
|
28
|
-
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
\`${testFile}\` (current) has:
|
|
42
|
+
\`\`\`ts
|
|
43
|
+
export async function uploadFileToRFI(page, fileName, tabName) {
|
|
44
|
+
await page.waitForTimeout(1500);
|
|
45
|
+
const responsePromise1 = page.waitForResponse("**/api/files/upload**");
|
|
46
|
+
const fileUploadPromise0 = page.waitForEvent("filechooser");
|
|
47
|
+
await page.getByText("Choose a file").click();
|
|
48
|
+
const fileChooser0 = await fileUploadPromise0;
|
|
49
|
+
await fileChooser0.setFiles(fileName);
|
|
50
|
+
const response1 = await responsePromise1;
|
|
51
|
+
await page.waitForTimeout(1500);
|
|
52
|
+
}
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
These ARE near-duplicates. Same primitive sequence; the only material difference is the \`.first()\` qualifier on the locator. \`tabName\` is unused in the body — recorder noise, drop it. Correct merge:
|
|
56
|
+
|
|
57
|
+
\`\`\`ts
|
|
58
|
+
export async function uploadFileViaChooser(page, fileName) {
|
|
59
|
+
await page.waitForTimeout(1500);
|
|
60
|
+
const responsePromise = page.waitForResponse("**/api/files/upload**");
|
|
61
|
+
const fileUploadPromise = page.waitForEvent("filechooser");
|
|
62
|
+
await page.getByText("Choose a file").first().click();
|
|
63
|
+
const fileChooser = await fileUploadPromise;
|
|
64
|
+
await fileChooser.setFiles(fileName);
|
|
65
|
+
await responsePromise;
|
|
66
|
+
await page.waitForTimeout(1500);
|
|
67
|
+
}
|
|
68
|
+
\`\`\`
|
|
69
|
+
|
|
70
|
+
Both test files import and call \`uploadFileViaChooser(page, fileName)\`.`;
|
|
71
|
+
}
|
|
72
|
+
export function getCodeReusePrompt(testFile, language, framework, scopedPoms, testType) {
|
|
29
73
|
const lang = language.toLowerCase();
|
|
30
|
-
if (isPomAwareTarget(lang, framework)) {
|
|
74
|
+
if (isPomAwareTarget(lang, framework, testType)) {
|
|
31
75
|
return getPomAwareCodeReusePrompt(testFile, lang, scopedPoms);
|
|
32
76
|
}
|
|
33
|
-
const
|
|
34
|
-
const
|
|
77
|
+
const languageEntry = LANGUAGE_MAP[lang] ?? LANGUAGE_MAP.python;
|
|
78
|
+
const ext = languageEntry.extension;
|
|
79
|
+
const fileName = languageEntry.fileName;
|
|
35
80
|
const codegenMarker = `${ext === "py" ? "#" : "//"} Generated by Skyramp v`;
|
|
81
|
+
// Modularize-first flows (see isModularizeFirstTarget) reach reuse already
|
|
82
|
+
// modularized, so the trailing hand-off must not send the agent back into
|
|
83
|
+
// modularization a second time — it would re-extract the helpers this pass
|
|
84
|
+
// just consolidated.
|
|
85
|
+
const modularizeFirst = isModularizeFirstTarget(testType, lang);
|
|
86
|
+
const modularizationTail = modularizeFirst
|
|
87
|
+
? `**MANDATORY**: ${testType} tests are modularized BEFORE code reuse (see the PRECONDITION at the top). This reuse pass is the FINAL step for this file — do NOT call skyramp_modularization after it; a second modularization pass would re-extract the helpers this pass just consolidated.`
|
|
88
|
+
: `**MANDATORY**: After code reuse is complete, proceed to modularization by calling skyramp_modularization tool ONLY for UI, E2E, or INTEGRATION test types generated from traces.`;
|
|
89
|
+
// Modularize-first tests reach reuse freshly modularized: their helpers exist
|
|
90
|
+
// only in the current file, and STEP 5's other-files-only rule would strand
|
|
91
|
+
// them there forever — the FIRST test in a repo could never create the utils
|
|
92
|
+
// file. STEP 5b seeds the utils file from the current test's own helpers so
|
|
93
|
+
// this run's output carries it and later tests import instead of re-defining.
|
|
94
|
+
const seedsUtils = modularizeFirst;
|
|
95
|
+
// Naming, equivalence and assertion rules for helpers headed to the shared
|
|
96
|
+
// file are the helper policy's — selected once by test type, stated once.
|
|
97
|
+
const policy = selectHelperPolicy(testType);
|
|
98
|
+
// The generic worked example treats a locator qualifier (.first()) as a
|
|
99
|
+
// liftable difference; a shared-file browser helper must not, so seeded
|
|
100
|
+
// browser flows show an identical-selector merge instead.
|
|
101
|
+
const workedExample = seedsUtils
|
|
102
|
+
? policy.nearDupExample(testFile)
|
|
103
|
+
: genericNearDupExample(testFile);
|
|
104
|
+
const skipTarget = seedsUtils ? "STEP 5b" : "STEP 6";
|
|
105
|
+
const noSiblingsRule = seedsUtils
|
|
106
|
+
? `**IF NO OTHER SKYRAMP-GENERATED TEST FILES ARE FOUND, SKIP DIRECTLY TO STEP 5b — do not process STEP 4b or STEP 5.**`
|
|
107
|
+
: `**STOP HERE IF NO OTHER SKYRAMP-GENERATED TEST FILES FOUND**
|
|
108
|
+
**IF NO OTHER SKYRAMP-GENERATED TEST FILES ARE FOUND, SKIP TO STEP 6 - DO NOT CREATE ANY UTILS FILES.**`;
|
|
109
|
+
const seedStepBlock = seedsUtils
|
|
110
|
+
? `## STEP 5b: MOVE THIS TEST'S OWN HELPERS INTO \`${fileName}\`
|
|
111
|
+
|
|
112
|
+
skyramp_modularization already ran on ${testFile} and extracted its steps into named helper functions. Those helpers belong in the shared \`${fileName}\` so later tests import them instead of re-defining them.
|
|
113
|
+
|
|
114
|
+
For each helper function still defined locally in ${testFile} (i.e. not already merged by STEP 4b):
|
|
115
|
+
1. **CREATE** \`${fileName}\` if it does not exist, with the standard header:
|
|
116
|
+
\`\`\`${ext}
|
|
117
|
+
${generateSkyrampHeader(lang)}
|
|
118
|
+
\`\`\`
|
|
119
|
+
2. **CHECK ITS ASSERTIONS FIRST**: ${policy.assertionRule} Relocate a trailing excluded assertion to ${policy.relocationTarget} before the move.${policy.moveRule ? ` ${policy.moveRule}` : ""}
|
|
120
|
+
3. **MOVE** the helper into \`${fileName}\` — no renames, no signature changes, no changes beyond the trailing-assertion relocation above.
|
|
121
|
+
4. **IMPORT** it from \`${fileName}\` into ${testFile}; keep every call site unchanged.
|
|
122
|
+
5. If \`${fileName}\` already contains a helper for ${policy.sameStep} (or the same name): identical bodies → delete the local copy and import the utils version; differs only by ${policy.liftableLiterals} → apply the defaulted-parameter merge rule from STEP 4b (extend the utils helper with parameters defaulted to its current literals, import it, pass this test's values); differs structurally → leave the local helper in place and do not overwrite the utils version. ${policy.structuralNoise ? `${policy.structuralNoise}. ` : ""}${NO_SHADOWING_RULE}
|
|
123
|
+
|
|
124
|
+
This step MOVES helpers that skyramp_modularization already created — it does not author new ones. If ${testFile} defines no helper functions, skip this step and do not create an empty \`${fileName}\`.
|
|
125
|
+
`
|
|
126
|
+
: "";
|
|
127
|
+
const nearDupRules = seedsUtils ? policy.nearDupRules(fileName) : "";
|
|
128
|
+
const utilsMergeRule = seedsUtils
|
|
129
|
+
? `
|
|
130
|
+
**IF \`${fileName}\` ALREADY CONTAINS A HELPER FOR ${policy.sameStep}** that differs from what ${testFile} needs only by ${policy.liftableLiterals}: do NOT define a second helper — EXTEND the utils helper by lifting the differing literals to parameters whose defaults are the utils version's current literals (existing call sites stay valid unchanged), then import and call it with this test's values. ${policy.oneHelperRule(fileName)}${policy.structuralNoise ? ` ${policy.structuralNoise}.` : ""} ${NO_SHADOWING_RULE}
|
|
131
|
+
`
|
|
132
|
+
: "";
|
|
133
|
+
// SKYR-4219: an inline request block is a CALL SITE for an existing helper, not a
|
|
134
|
+
// helper to move. Without this, a direct-mode sibling (plain literals, no
|
|
135
|
+
// \`data_override\`/\`uniqueSuffix\`) never meets the scenario-mode helper for the
|
|
136
|
+
// same request, and a step still inline in the current test never meets the utils
|
|
137
|
+
// helper — reuse degrades to a no-op in any mixed directory. Explicit test-type
|
|
138
|
+
// gate, not \`seedsUtils\`: the rule is stated in API terms.
|
|
139
|
+
const inlineRequestRule = testType === "integration"
|
|
140
|
+
? `**INLINE REQUEST BLOCKS ARE CALL SITES, NOT HELPERS.** A request step written inline — one \`client.send_request(...)\` / \`client.sendRequest(...)\` call plus its status-code assertion, not wrapped in a function — is never something to move or author a helper from. But when a helper for the SAME method+path already exists, the block is that helper's near-duplicate (judge it by the API near-duplicate criteria in STEP 4b: same method+path and call structure; differences limited to body literals, \`data_override\` values, or expected status): REPLACE the block with a call to the helper, passing the block's own literals as arguments, and lift any literal the helper does not yet take to a parameter DEFAULTED to the helper's current value (existing call sites unchanged). KEEP the block's response variable — \`<same variable> = <helper>(...)\` — so the assertions that read it afterwards are unchanged. A value the block wraps in \`uniqueSuffix(...)\` or routes through \`data_override\` where the helper uses a plain literal (or vice versa) is a LITERAL difference, not a structural one — pass the expression as the argument. A block whose request differs structurally (extra step, different method or path) stays as it is.`
|
|
141
|
+
: "";
|
|
142
|
+
// Its own step, placed after 5b: the agent routinely satisfies ${testFile} in STEP 3
|
|
143
|
+
// and jumps straight to verification, never entering STEP 4 — so a sibling rule parked
|
|
144
|
+
// there is never read (measured: eval run u4219b). This is where the shared helper is
|
|
145
|
+
// guaranteed to exist and the agent is guaranteed to still be running.
|
|
146
|
+
const siblingCallSitesStep = testType === "integration"
|
|
147
|
+
? `## STEP 5c: REPLACE INLINE REQUEST BLOCKS IN OTHER SKYRAMP-GENERATED TESTS WITH CALLS TO \`${fileName}\`
|
|
148
|
+
|
|
149
|
+
**Run this step EVEN IF STEP 3 already satisfied ${testFile} and STEPS 4–5b did nothing.** ${inlineRequestRule}
|
|
150
|
+
|
|
151
|
+
1. Grep for the other Skyramp-generated test files exactly as in STEP 4 (codegen marker \`${codegenMarker}\`, excluding ${testFile} and \`${fileName}\`).
|
|
152
|
+
2. In each, find every inline request block whose method+path matches a helper now defined in \`${fileName}\`.
|
|
153
|
+
3. For each match: import the helper into that file and replace the block with the call, passing the block's literals (or expressions) as arguments; lift a literal the helper lacks to a defaulted parameter in \`${fileName}\`. Change NOTHING else in that file — its other steps, assertions and order stay verbatim.
|
|
154
|
+
4. A block with no matching helper, or one that differs structurally, stays as it is. Conservative bias: a wrong replacement breaks a passing test; a missed one leaves a duplicate.
|
|
155
|
+
|
|
156
|
+
`
|
|
157
|
+
: "";
|
|
158
|
+
const finalReminderScope = seedsUtils
|
|
159
|
+
? `**ONLY MOVE HELPERS THAT ALREADY EXIST IN TEST FILES — NEVER AUTHOR NEW ONES**`
|
|
160
|
+
: `**ONLY MOVE EXISTING HELPERS FROM OTHER TEST FILES**`;
|
|
161
|
+
const decisionTreeTail = seedsUtils
|
|
162
|
+
? `3. Found other test files with only repetitive patterns? → Step 5b (seed utils from this test's own helpers)
|
|
163
|
+
4. Found no other test files? → Step 5b
|
|
164
|
+
5. Other test files identical to current? → Step 5b
|
|
165
|
+
6. This test file defines no helpers either? → Step 6, NO utils file`
|
|
166
|
+
: `3. Found other test files with only repetitive patterns? → SKIP to Step 6, NO utils file
|
|
167
|
+
4. Found no other test files? → SKIP to Step 6, NO utils file
|
|
168
|
+
5. Other test files identical to current? → SKIP to Step 6, NO utils file`;
|
|
169
|
+
const precondition = modularizeFirst
|
|
170
|
+
? `
|
|
171
|
+
**PRECONDITION — check your own tool-call history, not the file**: this flow moves the helpers skyramp_modularization created into \`${fileName}\` (STEP 5b). If you have NOT called skyramp_modularization on ${testFile} in this run, STOP: call it now with \`testFile\` set to ${testFile}, \`testType: "${testType}"\`, and \`isTraceBased: true\`, apply its instructions, then call skyramp_reuse_code again with the same arguments as this call. If you HAVE called it and the file still defines no helper functions, that is a legitimate outcome — proceed; STEP 5b will simply have nothing to move.
|
|
172
|
+
`
|
|
173
|
+
: "";
|
|
36
174
|
return `# CODE REUSE - 6 CLEAR STEPS
|
|
37
175
|
**CRITICAL WARNING: VIOLATION OF THESE RULES WILL RESULT IN ERROR**
|
|
38
|
-
|
|
176
|
+
${precondition}
|
|
39
177
|
## DEFINITIONS (READ FIRST):
|
|
40
178
|
**What is a "Helper Function"?**
|
|
41
179
|
- A helper function is a STANDALONE, DISTINCT function that is ALREADY DEFINED in the code
|
|
@@ -65,10 +203,14 @@ Use the Grep tool to search for files containing "${SKYRAMP_UTILS_HEADER}":
|
|
|
65
203
|
Read the matching non-test files and check if any helpers can be reused in ${testFile}.
|
|
66
204
|
|
|
67
205
|
## STEP 3: USE EXISTING HELPERS FROM UTILS SOURCE FILES FOUND IN STEP 2
|
|
68
|
-
If helpers exist in util file that can be reused in ${testFile} without modifying them:
|
|
206
|
+
If helpers exist in util file that can be reused in ${testFile} without modifying them${inlineRequestRule ? " — or, for API request helpers, by EXTENDING them with defaulted parameters as the rules below allow" : ""}:
|
|
69
207
|
- Import them into ${testFile}
|
|
70
208
|
- Remove any duplicate code in ${testFile}
|
|
71
|
-
|
|
209
|
+
${inlineRequestRule
|
|
210
|
+
? `- ${inlineRequestRule} This applies to every request step still inline in ${testFile} that matches a utils helper.
|
|
211
|
+
`
|
|
212
|
+
: ""}- Test that ${testFile} still works without any errors and logical is same as original test file.
|
|
213
|
+
${utilsMergeRule}
|
|
72
214
|
|
|
73
215
|
## STEP 4: FIND LOCAL HELPERS IN OTHER SKYRAMP-GENERATED TEST FILES
|
|
74
216
|
|
|
@@ -85,8 +227,7 @@ The result will mix two kinds of files:
|
|
|
85
227
|
- **Utils file(s)** — already handled by STEP 2/STEP 3.
|
|
86
228
|
- **Other Skyramp-generated test files** — these are the targets of STEP 4 / 4b / 5. Identify them by the \`${codegenMarker}\` codegen marker on line 1 (NOT the bare utils header).
|
|
87
229
|
|
|
88
|
-
|
|
89
|
-
**IF NO OTHER SKYRAMP-GENERATED TEST FILES ARE FOUND, SKIP TO STEP 6 - DO NOT CREATE ANY UTILS FILES.**
|
|
230
|
+
${noSiblingsRule}
|
|
90
231
|
|
|
91
232
|
If other Skyramp-generated test files are found, read those files and look for ALREADY DEFINED helper functions with clear function signatures.
|
|
92
233
|
|
|
@@ -101,8 +242,12 @@ NOT A HELPER FUNCTION (do not extract):
|
|
|
101
242
|
- No function definition/signature
|
|
102
243
|
- Example: Multiple \`await page.getByTestId("xyz").click()\` directly in test
|
|
103
244
|
|
|
104
|
-
|
|
105
|
-
|
|
245
|
+
${inlineRequestRule
|
|
246
|
+
? `(Inline request blocks in OTHER test files are not helpers to move — STEP 5c replaces them with calls to the shared helpers.)
|
|
247
|
+
|
|
248
|
+
`
|
|
249
|
+
: ""}**IF OTHER TEST FILES ONLY CONTAIN REPETITIVE PATTERNS (NO ACTUAL HELPER FUNCTIONS), SKIP TO ${skipTarget}**
|
|
250
|
+
**IF OTHER SKYRAMP-GENERATED TEST FILES ARE BYTE-FOR-BYTE IDENTICAL TO ${testFile}, SKIP TO ${skipTarget}** (note: helpers being NEAR-duplicates does NOT count as identical — proceed to STEP 4b)
|
|
106
251
|
|
|
107
252
|
## STEP 4b: PARAMETERIZE NEAR-DUPLICATE HELPERS ACROSS SKYRAMP-GENERATED TEST FILES
|
|
108
253
|
|
|
@@ -117,53 +262,8 @@ Two helpers (one in ${testFile}, one in another Skyramp-generated test file foun
|
|
|
117
262
|
3. **The differing literals are trivially liftable to parameters** — no logic needs to be invented to derive them.
|
|
118
263
|
|
|
119
264
|
If any of the three is false → NOT near-duplicates. Leave them alone.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
\`flow-1.spec.ts\` has:
|
|
124
|
-
\`\`\`ts
|
|
125
|
-
export async function upload_translation_file(page, fileName) {
|
|
126
|
-
await page.waitForTimeout(1500);
|
|
127
|
-
const responsePromise1 = page.waitForResponse("**/api/files/upload**");
|
|
128
|
-
const fileUploadPromise0 = page.waitForEvent("filechooser");
|
|
129
|
-
await page.getByText("Choose a file").first().click();
|
|
130
|
-
const fileChooser0 = await fileUploadPromise0;
|
|
131
|
-
await fileChooser0.setFiles(fileName);
|
|
132
|
-
const response1 = await responsePromise1;
|
|
133
|
-
await page.waitForTimeout(1500);
|
|
134
|
-
}
|
|
135
|
-
\`\`\`
|
|
136
|
-
|
|
137
|
-
\`${testFile}\` (current) has:
|
|
138
|
-
\`\`\`ts
|
|
139
|
-
export async function uploadFileToRFI(page, fileName, tabName) {
|
|
140
|
-
await page.waitForTimeout(1500);
|
|
141
|
-
const responsePromise1 = page.waitForResponse("**/api/files/upload**");
|
|
142
|
-
const fileUploadPromise0 = page.waitForEvent("filechooser");
|
|
143
|
-
await page.getByText("Choose a file").click();
|
|
144
|
-
const fileChooser0 = await fileUploadPromise0;
|
|
145
|
-
await fileChooser0.setFiles(fileName);
|
|
146
|
-
const response1 = await responsePromise1;
|
|
147
|
-
await page.waitForTimeout(1500);
|
|
148
|
-
}
|
|
149
|
-
\`\`\`
|
|
150
|
-
|
|
151
|
-
These ARE near-duplicates. Same primitive sequence; the only material difference is the \`.first()\` qualifier on the locator. \`tabName\` is unused in the body — recorder noise, drop it. Correct merge:
|
|
152
|
-
|
|
153
|
-
\`\`\`ts
|
|
154
|
-
export async function uploadFileViaChooser(page, fileName) {
|
|
155
|
-
await page.waitForTimeout(1500);
|
|
156
|
-
const responsePromise = page.waitForResponse("**/api/files/upload**");
|
|
157
|
-
const fileUploadPromise = page.waitForEvent("filechooser");
|
|
158
|
-
await page.getByText("Choose a file").first().click();
|
|
159
|
-
const fileChooser = await fileUploadPromise;
|
|
160
|
-
await fileChooser.setFiles(fileName);
|
|
161
|
-
await responsePromise;
|
|
162
|
-
await page.waitForTimeout(1500);
|
|
163
|
-
}
|
|
164
|
-
\`\`\`
|
|
165
|
-
|
|
166
|
-
Both test files import and call \`uploadFileViaChooser(page, fileName)\`.
|
|
265
|
+
${nearDupRules}
|
|
266
|
+
${workedExample}
|
|
167
267
|
|
|
168
268
|
### Procedure
|
|
169
269
|
|
|
@@ -172,7 +272,7 @@ For each helper defined locally in ${testFile}:
|
|
|
172
272
|
1. **Scan** each OTHER Skyramp-generated test file from STEP 4 for a helper that matches the near-duplicate criteria above.
|
|
173
273
|
2. **If no match** → skip this helper, move on.
|
|
174
274
|
3. **If exactly one match** → parameterize and merge:
|
|
175
|
-
- **Name**: pick a name describing INTENT, not the originating test. E.g.
|
|
275
|
+
- **Name**: pick a name describing INTENT, not the originating test. ${seedsUtils ? policy.namingExample : "E.g. `uploadFileViaChooser`, not `upload_translation_file` or `uploadFileToRFI`."}
|
|
176
276
|
- **Parameters**: the literal values that differ across the two call sites. Drop any parameter that is unused in the body (recorder noise).
|
|
177
277
|
- **Body**: the common primitive sequence with the differing literals replaced by parameters.
|
|
178
278
|
- **Forbidden**: do NOT add if/else, ternaries, defaults, or any logic to bridge the differences. If a single body can't cover both call sites without new logic, they are NOT near-duplicates — leave them alone.
|
|
@@ -201,7 +301,7 @@ For each helper defined locally in ${testFile}:
|
|
|
201
301
|
- The helper functions are ALREADY IMPLEMENTED and working in those OTHER test files
|
|
202
302
|
- The helper in the OTHER test file is byte-for-byte usable in ${testFile} without any modification — if a helper would need parameterizing to fit both call sites, it is a near-duplicate and STEP 4b owns it; do NOT process those helpers here
|
|
203
303
|
|
|
204
|
-
**IF ANY CONDITION IS NOT MET, SKIP TO
|
|
304
|
+
**IF ANY CONDITION IS NOT MET, SKIP TO ${skipTarget}${seedsUtils ? "" : " - DO NOT CREATE ANY UTILS FILES"}.**
|
|
205
305
|
|
|
206
306
|
**Examples of when to SKIP STEP 5:**
|
|
207
307
|
- Other test files have identical repetitive code but no helper functions
|
|
@@ -212,10 +312,10 @@ For each helper defined locally in ${testFile}:
|
|
|
212
312
|
**CRITICAL:** For helpers found in STEP 4:
|
|
213
313
|
1. **CREATE** \`${fileName}\` file if it doesn't exist with the following header:
|
|
214
314
|
\`\`\`${ext}
|
|
215
|
-
${generateSkyrampHeader(
|
|
315
|
+
${generateSkyrampHeader(lang)}
|
|
216
316
|
\`\`\`
|
|
217
317
|
**CRITICAL: IF \`${fileName}\` is already big, create a new file with a different name and add the header to the new file.**
|
|
218
|
-
2. **COPY** those local helper functions from original test source files to \`${fileName}\` without modifying them
|
|
318
|
+
2. **COPY** those local helper functions from original test source files to \`${fileName}\` without modifying them${seedsUtils ? ` — with ONE exception, checked BEFORE the copy: ${policy.assertionRule} Relocate a trailing excluded assertion into the owning test's body first; the copy that lands in \`${fileName}\` carries none.${policy.moveRule ? ` ${policy.moveRule}` : ""}` : ""}
|
|
219
319
|
3. **DELETE** those local helper functions from test source files (REMOVE THEM COMPLETELY) WITHOUT ANY OTHER CHANGES.
|
|
220
320
|
4. **IMPORT** those local helper functions from \`${fileName}\` back into test source files WITHOUT MAKING ANY OTHER CHANGE.
|
|
221
321
|
5. **IMPORT** those local helper functions from \`${fileName}\` into ${testFile}
|
|
@@ -224,7 +324,7 @@ For each helper defined locally in ${testFile}:
|
|
|
224
324
|
**CRITICAL: DO NOT CREATE UNNECESSARY HELPER FUNCTIONS**
|
|
225
325
|
**DO NOT CREATE HELPERS BASED ON PATTERNS IN THE CURRENT FILE**
|
|
226
326
|
|
|
227
|
-
## STEP 6: VERIFY AND VALIDATE
|
|
327
|
+
${seedStepBlock}${siblingCallSitesStep}## STEP 6: VERIFY AND VALIDATE
|
|
228
328
|
1. **BEFORE** making any changes, read the original test file and identify ALL helper functions
|
|
229
329
|
2. **AFTER** copying helpers to utils, read the original file again to confirm helpers are GONE
|
|
230
330
|
3. **VERIFY** that helper functions are NO LONGER in original test files
|
|
@@ -234,15 +334,15 @@ For each helper defined locally in ${testFile}:
|
|
|
234
334
|
6. **VERIFY** that no unnecessary helper functions were created (functions that duplicate existing functionality)
|
|
235
335
|
7. **VERIFY** that all helper functions in utils are actually imported and used in the test files
|
|
236
336
|
8. **REMOVE** any helper functions that are not being used after refactoring
|
|
237
|
-
9. **NEVER** refactor, reorganize, or restructure existing source test files beyond moving helpers
|
|
337
|
+
9. **NEVER** refactor, reorganize, or restructure existing source test files beyond moving helpers${inlineRequestRule ? " — and, in this flow, replacing an inline request block with a call to the shared helper it duplicates (STEP 3 / STEP 5c)" : ""}
|
|
238
338
|
10. **RUN TESTS** to ensure functionality is preserved after refactoring
|
|
239
339
|
|
|
240
|
-
**FINAL REMINDER: DO NOT CREATE HELPER FUNCTIONS FROM SCRATCH**
|
|
241
|
-
|
|
340
|
+
**FINAL REMINDER: DO NOT CREATE HELPER FUNCTIONS FROM SCRATCH**
|
|
341
|
+
${finalReminderScope}
|
|
242
342
|
|
|
243
343
|
**IMPORTANT NOTES:**
|
|
244
344
|
- The process is designed to REUSE existing helper functions, not create new ones
|
|
245
|
-
- If no existing helpers are found, the test file should remain unchanged
|
|
345
|
+
- ${seedsUtils ? `If no existing helpers are found in utils or sibling tests, STEP 5b still moves this test's own helpers into \`${fileName}\` and imports them back — that is the expected first-run outcome, not a no-op` : "If no existing helpers are found, the test file should remain unchanged"}
|
|
246
346
|
- Code reuse is about moving existing, working helper functions between files
|
|
247
347
|
- Never create helper functions based on patterns you see in the current test file
|
|
248
348
|
- Helper functions must have explicit function signatures/definitions
|
|
@@ -251,11 +351,16 @@ For each helper defined locally in ${testFile}:
|
|
|
251
351
|
**DECISION TREE:**
|
|
252
352
|
1. Found existing utils file with helpers? → Import and use them (Step 3)
|
|
253
353
|
2. Found other test files with ACTUAL helper functions? → Move to utils (Step 5)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
354
|
+
${decisionTreeTail}
|
|
355
|
+
|
|
356
|
+
${modularizationTail}
|
|
257
357
|
|
|
258
|
-
|
|
358
|
+
${
|
|
359
|
+
// Gated with the debt it describes: with SkyrampUtils reuse off nothing refuses, and
|
|
360
|
+
// this text would send the agent to spend a call being told the feature is disabled.
|
|
361
|
+
isUtilsReuseEnabled()
|
|
362
|
+
? `**MANDATORY FINAL STEP — VERIFY**: once every edit above is written, call skyramp_reuse_code again with the SAME testFile, language, framework and testType and \`verify: true\`. It stages the shared utils file for the output commit and checks its invariants (for API helpers: one helper per method+path, status-code-only assertions, method+resource names; for browser helpers: actions and structural waits only, intent names). Resolve anything it reports and re-verify; finish only when it reports PASSED. It passes immediately when no utils file was written. skyramp_enhance_assertions and skyramp_execute_test refuse this test until that verify pass has run.\n`
|
|
363
|
+
: ""}
|
|
259
364
|
|
|
260
365
|
SUMMARIZE THE CODE REUSE PROCESS AND THE RESULTS.
|
|
261
366
|
`;
|
|
@@ -1 +1,3 @@
|
|
|
1
1
|
export declare function getModularizationPrompt(filePath: string): string;
|
|
2
|
+
/** Structured view of which steps render for the given inputs (for tests). */
|
|
3
|
+
export declare function previewModularizationPlan(filePath: string): import("../test-recommendation/promptPlan.js").PlanPreview;
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { isModularizeFirstTarget } from "../../utils/reuseRouting.js";
|
|
2
|
+
import { PromptPlan } from "../test-recommendation/promptPlan.js";
|
|
3
|
+
import { API_HELPERS, ASSERTION_BOUNDARY_RULE_EXTRACT, } from "../shared-helper-policy.js";
|
|
4
|
+
import { renderModularizationPrompt, } from "./render.js";
|
|
5
|
+
// On modularize-first flows (see isModularizeFirstTarget), downstream
|
|
6
|
+
// skyramp_reuse_code consolidates this file's helpers into the shared
|
|
7
|
+
// SkyrampUtils file — so EVERY request step must become a named helper, even
|
|
8
|
+
// when nothing repeats in-file (a linear CRUD scenario calls each endpoint once,
|
|
9
|
+
// so repetition-based extraction yields zero helpers and the utils file can
|
|
10
|
+
// never materialize).
|
|
11
|
+
const _plan = new PromptPlan()
|
|
12
|
+
.addPhase("main", "Integration Test Modularization", {
|
|
13
|
+
headerLevel: "hidden",
|
|
14
|
+
stepFormat: "hash",
|
|
15
|
+
})
|
|
16
|
+
.step("READ", "READ AND UNDERSTAND THE ORIGINAL TEST", (p) => `**CRITICAL: Before making ANY changes:**
|
|
17
|
+
1. Read ${p.filePath} completely
|
|
16
18
|
2. Identify all API endpoints and their parameters
|
|
17
19
|
3. Identify all test data (request bodies, expected responses)
|
|
18
20
|
4. Identify all assertions and expected values
|
|
19
21
|
5. Document the test flow
|
|
20
|
-
6. **DO NOT PROCEED** until you fully understand what the test does
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
**GOLDEN RULE: COPY-PASTE THE ORIGINAL CODE INTO HELPERS, JUST ADD PARAMETERS AND REPLACE HARDCODED VALUES WITH PARAMETERS**
|
|
22
|
+
6. **DO NOT PROCEED** until you fully understand what the test does`)
|
|
23
|
+
.step("IDENTIFY", (p) => (p.utilsReuse ? "IDENTIFY REQUEST STEPS" : "FIND REPETITIVE CODE"), (p) => p.utilsReuse
|
|
24
|
+
? `A request step = one API call plus the assertions that verify its response.
|
|
25
|
+
This project consolidates test helpers into a shared utils file, so EVERY request step becomes a named helper function — the step does NOT need to repeat.
|
|
26
|
+
List every request step in the test (e.g. create product, create order, update order, get order).`
|
|
27
|
+
: `Look for API calls that repeat 2+ times with IDENTICAL structure but different data.`)
|
|
28
|
+
.step("EXTRACT", "CREATE HELPER FUNCTIONS - EXTRACT ONLY, NO CHANGES", (p) => `**GOLDEN RULE: COPY-PASTE THE ORIGINAL CODE INTO HELPERS, JUST ADD PARAMETERS AND REPLACE HARDCODED VALUES WITH PARAMETERS**
|
|
28
29
|
|
|
29
30
|
**CRITICAL RULES:**
|
|
30
31
|
1. **EXACT CODE COPY** - Copy the API call code EXACTLY as-is from the original test
|
|
31
|
-
2. **ONLY ADD PARAMETERS** - The ONLY change allowed is converting hardcoded values to parameters
|
|
32
|
+
2. **ONLY ADD PARAMETERS** - The ONLY change allowed is converting hardcoded values to parameters${p.utilsReuse
|
|
33
|
+
? " — plus ONE placement exception: a response-body assertion that would land inside a helper is placed in the test body, applied to the response the helper returns (same check, same expected value, same relative order). That relocation is the only assertion move allowed; see HELPER SHAPE below"
|
|
34
|
+
: ""}
|
|
32
35
|
3. **NEVER GENERALIZE SELECTORS** - Keep all selectors/locators exactly as they are in the original code (do not refactor into dynamic template strings)
|
|
33
|
-
4. **NO LOGIC CHANGES** - Do not modify conditions, validations, or assertions
|
|
36
|
+
4. **NO LOGIC CHANGES** - Do not modify conditions, validations, or assertions${p.utilsReuse ? " (relocating a body assertion per rule 2 is a placement, not a change)" : ""}
|
|
34
37
|
5. **NO DATA CHANGES** - Do not change any request/response values or expected results
|
|
35
38
|
6. **PRESERVE PATH PARAMETERS** - API path parameters must be passed as function parameters
|
|
36
39
|
7. **PRESERVE ORDER** - Keep all operations in the exact same order
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
- Find the values that DIFFER between repetitions (e.g., user IDs, product names)
|
|
40
|
-
- Make ONLY those differing values into parameters
|
|
41
|
-
- Keep everything else EXACTLY the same
|
|
41
|
+
${p.utilsReuse ? sharedHelperShape(p) : repetitionParameterRules()}
|
|
42
42
|
|
|
43
43
|
**EXAMPLE OF CORRECT EXTRACTION:**
|
|
44
44
|
\`\`\`typescript
|
|
@@ -49,12 +49,18 @@ expect(response1.status).toBe(200);
|
|
|
49
49
|
const response2 = await fetch("/api/users/2");
|
|
50
50
|
expect(response2.status).toBe(200);
|
|
51
51
|
|
|
52
|
-
// Correct helper (EXACT copy + parameters):
|
|
53
|
-
|
|
52
|
+
// Correct helper (EXACT copy + parameters${p.utilsReuse ? "; the expected status is a defaulted parameter per HELPER SHAPE" : ""}):
|
|
53
|
+
${p.utilsReuse
|
|
54
|
+
? `async function getUser(userId: number, expectedStatus = 200) {
|
|
55
|
+
const response = await fetch(\`/api/users/\${userId}\`);
|
|
56
|
+
expect(response.status).toBe(expectedStatus);
|
|
57
|
+
return response;
|
|
58
|
+
}`
|
|
59
|
+
: `async function getUser(userId: number) {
|
|
54
60
|
const response = await fetch(\`/api/users/\${userId}\`);
|
|
55
61
|
expect(response.status).toBe(200);
|
|
56
62
|
return response;
|
|
57
|
-
}
|
|
63
|
+
}`}
|
|
58
64
|
\`\`\`
|
|
59
65
|
|
|
60
66
|
**WHAT NOT TO DO:**
|
|
@@ -64,14 +70,9 @@ Modifying expected status codes
|
|
|
64
70
|
Changing request/response validation
|
|
65
71
|
Reordering operations
|
|
66
72
|
"Improving" error handling
|
|
67
|
-
Adding new assertions
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
When calling the helpers, use the EXACT same values from the original test.
|
|
71
|
-
|
|
72
|
-
## STEP 5: FINAL VERIFICATION
|
|
73
|
-
|
|
74
|
-
**BEFORE WRITING ANY CODE, VERIFY:**
|
|
73
|
+
Adding new assertions`)
|
|
74
|
+
.step("USE", "USE HELPERS WITH EXACT SAME DATA", () => `When calling the helpers, use the EXACT same values from the original test.`)
|
|
75
|
+
.step("VERIFY", "FINAL VERIFICATION", () => `**BEFORE WRITING ANY CODE, VERIFY:**
|
|
75
76
|
- [ ] I have read and understood the original test completely
|
|
76
77
|
- [ ] I have identified all API calls and their parameters
|
|
77
78
|
- [ ] I have documented all expected responses and assertions
|
|
@@ -91,5 +92,46 @@ Run through the modularized test mentally:
|
|
|
91
92
|
2. Does it use the exact same request data?
|
|
92
93
|
3. Does it expect the exact same responses?
|
|
93
94
|
|
|
94
|
-
If ANY answer is "no", DO NOT submit - fix the modularization first
|
|
95
|
+
If ANY answer is "no", DO NOT submit - fix the modularization first.`)
|
|
96
|
+
.done();
|
|
97
|
+
// Shared-file helper shape: the helpers this step creates are consolidated into
|
|
98
|
+
// SkyrampUtils by the reuse pass, so each one must be nameable and callable by
|
|
99
|
+
// the next scenario — canonical names, scenario values as arguments, and no
|
|
100
|
+
// scenario-specific claims inside the helper.
|
|
101
|
+
function sharedHelperShape(p) {
|
|
102
|
+
return `**HELPER SHAPE (one helper per request step from Step ${_plan.labels.IDENTIFY}):**
|
|
103
|
+
- ${API_HELPERS.namingRule}
|
|
104
|
+
- **PARAMETERS**: pass in the client/session object, plus every value the step reads from a previous step's response (IDs used in paths or bodies), plus every body value this scenario varies or its assertions reference (names, prices, quantities, percentages). Values that never vary and that no assertion reads may stay hardcoded — do not invent parameters nothing passes differently.
|
|
105
|
+
- **SCENARIO VALUES GO THROUGH \`data_override\`, NOT THE BODY STRING**: apply each parameterized body value via the request's \`data_override\` map (that is what it is for) and leave the raw body string as generated. A scenario literal edited into the body string makes this helper unmergeable with the same step from another test.
|
|
106
|
+
- **RETURN** the response object so later steps can chain and assert from it.
|
|
107
|
+
- ${API_HELPERS.assertionRule} ${ASSERTION_BOUNDARY_RULE_EXTRACT}
|
|
108
|
+
- Helpers are module-level named functions in ${p.filePath}; the test body becomes a sequence of helper calls plus this scenario's assertions, in the original order.
|
|
109
|
+
- Keep everything else EXACTLY the same.`;
|
|
110
|
+
}
|
|
111
|
+
function repetitionParameterRules() {
|
|
112
|
+
return `**PARAMETER CONVERSION RULES:**
|
|
113
|
+
- Find the values that DIFFER between repetitions (e.g., user IDs, product names)
|
|
114
|
+
- Make ONLY those differing values into parameters
|
|
115
|
+
- Keep everything else EXACTLY the same`;
|
|
116
|
+
}
|
|
117
|
+
export function getModularizationPrompt(filePath) {
|
|
118
|
+
const utilsReuse = isModularizeFirstTarget("integration");
|
|
119
|
+
return renderModularizationPrompt({
|
|
120
|
+
title: "INTEGRATION TEST MODULARIZATION - SIMPLE AND SAFE",
|
|
121
|
+
forbidden: [
|
|
122
|
+
"DO NOT CREATE ANY INTERFACES, CLASSES, TYPES, OR NEW DATA STRUCTURES. USE INLINE TYPES ONLY.",
|
|
123
|
+
"DO NOT CREATE/UPDATE package.json or requirements.txt or pom.xml or build.gradle file",
|
|
124
|
+
`DO NOT CHANGE TEST LOGIC, DATA VALUES, ASSERTIONS, OR API CALLS${utilsReuse ? " (moving a response-body assertion out of a helper into the test body, verbatim, is a placement — not a change)" : ""}`,
|
|
125
|
+
"DO NOT MODIFY EXPECTED RESPONSES OR STATUS CODES",
|
|
126
|
+
],
|
|
127
|
+
plan: _plan,
|
|
128
|
+
params: { filePath, utilsReuse },
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/** Structured view of which steps render for the given inputs (for tests). */
|
|
132
|
+
export function previewModularizationPlan(filePath) {
|
|
133
|
+
return _plan.preview({
|
|
134
|
+
filePath,
|
|
135
|
+
utilsReuse: isModularizeFirstTarget("integration"),
|
|
136
|
+
});
|
|
95
137
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PromptPlan } from "../test-recommendation/promptPlan.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parameters both modularization plans render against.
|
|
4
|
+
* `utilsReuse` is true on modularize-first flows (see isModularizeFirstTarget):
|
|
5
|
+
* downstream skyramp_reuse_code consolidates this file's helpers into the shared
|
|
6
|
+
* SkyrampUtils file, which changes what a helper may be named and may assert.
|
|
7
|
+
*/
|
|
8
|
+
export interface ModularizationParams {
|
|
9
|
+
filePath: string;
|
|
10
|
+
utilsReuse: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** The scaffold shared by the UI and integration modularization prompts. */
|
|
13
|
+
export declare function renderModularizationPrompt(opts: {
|
|
14
|
+
title: string;
|
|
15
|
+
forbidden: string[];
|
|
16
|
+
plan: PromptPlan<ModularizationParams>;
|
|
17
|
+
params: ModularizationParams;
|
|
18
|
+
}): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** The scaffold shared by the UI and integration modularization prompts. */
|
|
2
|
+
export function renderModularizationPrompt(opts) {
|
|
3
|
+
return `# ${opts.title}
|
|
4
|
+
|
|
5
|
+
**CRITICAL: Use the 'write' tool to save the modularized code to: ${opts.params.filePath}**
|
|
6
|
+
**DO NOT use search_replace - use the 'write' tool to overwrite the entire file with the modularized version**
|
|
7
|
+
|
|
8
|
+
**ABSOLUTELY FORBIDDEN:**
|
|
9
|
+
${opts.forbidden.map((f) => `- ${f}`).join("\n")}
|
|
10
|
+
|
|
11
|
+
${opts.plan.render(opts.params)}`;
|
|
12
|
+
}
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
export declare function getModularizationPrompt(filePath: string): string;
|
|
1
|
+
export declare function getModularizationPrompt(filePath: string, testType: string, language?: string): string;
|
|
2
|
+
/** Structured view of which steps render for the given inputs (for tests). */
|
|
3
|
+
export declare function previewModularizationPlan(filePath: string, testType: string, language?: string): import("../test-recommendation/promptPlan.js").PlanPreview;
|