@skyramp/mcp 0.3.2-rc.pom-3 → 0.3.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/build/commands/commandLibrary.d.ts +1 -0
- package/build/commands/commandLibrary.js +19 -13
- package/build/commands/localDevTestChangesCommand.d.ts +15 -0
- package/build/commands/localDevTestChangesCommand.js +201 -0
- package/build/index.js +80 -6
- package/build/prompts/code-reuse.js +3 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
- package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
- package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
- package/build/prompts/local-dev/local-dev-plan.js +429 -0
- package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
- package/build/prompts/local-dev/local-dev-prompts.js +190 -0
- package/build/prompts/pom-aware-code-reuse.js +12 -0
- package/build/prompts/prompt-utils.d.ts +8 -0
- package/build/prompts/prompt-utils.js +33 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
- package/build/prompts/sut-setup/shared.js +16 -12
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
- package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
- package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
- package/build/prompts/testbot/testbot-prompts.js +32 -52
- package/build/recommendation/planRanker.d.ts +15 -2
- package/build/recommendation/planRanker.js +76 -5
- package/build/resources/testbotResource.js +2 -1
- package/build/services/AnalyticsService.d.ts +1 -1
- package/build/services/TestExecutionService.d.ts +2 -1
- package/build/services/TestExecutionService.js +8 -3
- package/build/services/TestGenerationService.d.ts +2 -2
- package/build/services/TestGenerationService.js +39 -21
- package/build/services/containerEnv.js +3 -1
- package/build/tool-phases.js +6 -0
- package/build/tools/code-refactor/codeReuseTool.js +43 -4
- package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
- package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
- package/build/tools/code-refactor/reuse-outcome.js +158 -0
- package/build/tools/code-refactor/reuse-state.d.ts +45 -0
- package/build/tools/code-refactor/reuse-state.js +140 -0
- package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
- package/build/tools/enrichTestWithMocksTool.js +726 -0
- package/build/tools/executeSkyrampTestTool.d.ts +11 -0
- package/build/tools/executeSkyrampTestTool.js +62 -21
- package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
- package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
- package/build/tools/generate-tests/generateContractRestTool.js +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
- package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
- package/build/tools/generate-tests/generateMockRestTool.js +391 -22
- package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
- package/build/tools/generate-tests/planGuard.js +2 -22
- package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
- package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
- package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
- package/build/tools/localDevWorkerComposeTool.js +264 -0
- package/build/tools/one-click/oneClickTool.d.ts +13 -0
- package/build/tools/one-click/oneClickTool.js +195 -24
- package/build/tools/preflightMockCheckTool.d.ts +2 -0
- package/build/tools/preflightMockCheckTool.js +96 -0
- package/build/tools/queryProxyMocksTool.d.ts +70 -0
- package/build/tools/queryProxyMocksTool.js +522 -0
- package/build/tools/runExistingTestsTool.d.ts +31 -0
- package/build/tools/runExistingTestsTool.js +214 -13
- package/build/tools/submitReportTool.js +38 -3
- package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
- package/build/tools/test-management/analyzeChangesTool.js +63 -40
- package/build/tools/test-management/registerTestPlanTool.js +55 -7
- package/build/tools/trace/startTraceCollectionTool.js +3 -3
- package/build/types/FrontendIntegration.d.ts +3 -0
- package/build/types/FrontendIntegration.js +3 -0
- package/build/types/OneClickCommands.d.ts +1 -1
- package/build/types/Recommendation.d.ts +20 -0
- package/build/types/Recommendation.js +32 -6
- package/build/types/RepositoryAnalysis.d.ts +131 -14
- package/build/types/RepositoryAnalysis.js +16 -2
- package/build/types/ReuseOutcome.d.ts +63 -0
- package/build/types/ReuseOutcome.js +33 -0
- package/build/types/TestExecution.d.ts +1 -0
- package/build/types/TestTypes.d.ts +25 -7
- package/build/types/TestTypes.js +22 -6
- package/build/types/TestbotReport.d.ts +7 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/index.js +1 -0
- package/build/utils/AnalysisStateManager.d.ts +26 -0
- package/build/utils/AnalysisStateManager.js +31 -1
- package/build/utils/analyze-openapi.js +18 -1
- package/build/utils/branchDiff.d.ts +17 -1
- package/build/utils/branchDiff.js +99 -14
- package/build/utils/featureFlags.d.ts +31 -0
- package/build/utils/featureFlags.js +37 -0
- package/build/utils/frontendIntegration.js +8 -1
- package/build/utils/grpcMockValidation.d.ts +1 -0
- package/build/utils/grpcMockValidation.js +49 -0
- package/build/utils/httpMethodValidation.d.ts +4 -0
- package/build/utils/httpMethodValidation.js +15 -0
- package/build/utils/logger.js +1 -1
- package/build/utils/mockCompatibility.d.ts +49 -0
- package/build/utils/mockCompatibility.js +82 -0
- package/build/utils/pom-scope/pom-files.js +7 -0
- package/build/utils/pom-verify/bindings.js +11 -1
- package/build/utils/pom-verify/re-exports.d.ts +10 -0
- package/build/utils/pom-verify/re-exports.js +61 -0
- package/build/utils/pom-verify/resolve.d.ts +4 -1
- package/build/utils/pom-verify/resolve.js +7 -4
- package/build/utils/pom-verify/verify.d.ts +5 -0
- package/build/utils/pom-verify/verify.js +25 -3
- package/build/utils/progress.js +10 -5
- package/build/utils/proxy-terminal.js +3 -3
- package/build/utils/routeParsers.d.ts +3 -9
- package/build/utils/routeParsers.js +79 -4
- package/build/utils/utils.js +2 -2
- package/build/utils/versions.d.ts +4 -3
- package/build/utils/versions.js +3 -1
- package/build/utils/workspaceAuth.d.ts +46 -0
- package/build/utils/workspaceAuth.js +156 -1
- package/build/workspace/testSuites.d.ts +2 -1
- package/build/workspace/testSuites.js +1 -1
- package/build/workspace/workspace.d.ts +108 -32
- package/build/workspace/workspace.js +32 -4
- package/package.json +5 -2
- package/build/adapters/jestAdapter.test.d.ts +0 -1
- package/build/adapters/jestAdapter.test.js +0 -93
- package/build/adapters/mochaAdapter.test.d.ts +0 -1
- package/build/adapters/mochaAdapter.test.js +0 -63
- package/build/adapters/playwrightAdapter.test.d.ts +0 -1
- package/build/adapters/playwrightAdapter.test.js +0 -169
- package/build/adapters/pytestAdapter.test.d.ts +0 -1
- package/build/adapters/pytestAdapter.test.js +0 -90
- package/build/prompts/code-reuse.test.d.ts +0 -1
- package/build/prompts/code-reuse.test.js +0 -62
- package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
- package/build/prompts/pom-aware-code-reuse.test.js +0 -11
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
- package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
- package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
- package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
- package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
- package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
- package/build/prompts/testbot/testbot-prompts.test.js +0 -451
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
- package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
- package/build/recommendation/discriminators.test.d.ts +0 -1
- package/build/recommendation/discriminators.test.js +0 -324
- package/build/recommendation/diversity.test.d.ts +0 -1
- package/build/recommendation/diversity.test.js +0 -77
- package/build/recommendation/planRanker.test.d.ts +0 -1
- package/build/recommendation/planRanker.test.js +0 -110
- package/build/resources/testbotResource.test.d.ts +0 -1
- package/build/resources/testbotResource.test.js +0 -44
- package/build/services/AnalyticsService.test.d.ts +0 -1
- package/build/services/AnalyticsService.test.js +0 -86
- package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.integration.test.js +0 -162
- package/build/services/ScenarioGenerationService.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.test.js +0 -414
- package/build/services/TestDiscoveryService.test.d.ts +0 -1
- package/build/services/TestDiscoveryService.test.js +0 -983
- package/build/services/TestExecutionService.test.d.ts +0 -1
- package/build/services/TestExecutionService.test.js +0 -1032
- package/build/services/TestGenerationService.test.d.ts +0 -1
- package/build/services/TestGenerationService.test.js +0 -578
- package/build/tool-phase-coverage.test.d.ts +0 -1
- package/build/tool-phase-coverage.test.js +0 -49
- package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
- package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
- package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
- package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
- package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
- package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
- package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
- package/build/tools/generate-tests/planGuard.test.js +0 -185
- package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
- package/build/tools/generate-tests/scenarioLint.test.js +0 -100
- package/build/tools/runExistingTestsTool.test.d.ts +0 -1
- package/build/tools/runExistingTestsTool.test.js +0 -379
- package/build/tools/submitReportTool.test.d.ts +0 -1
- package/build/tools/submitReportTool.test.js +0 -1428
- package/build/tools/test-management/actionsTool.test.d.ts +0 -1
- package/build/tools/test-management/actionsTool.test.js +0 -436
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
- package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
- package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
- package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
- package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
- package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
- package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
- package/build/tools/trace/resolveSessionPaths.test.js +0 -104
- package/build/tools/trace/sessionState.test.d.ts +0 -1
- package/build/tools/trace/sessionState.test.js +0 -17
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
- package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
- package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
- package/build/tools/workspace/serviceUpsert.test.js +0 -50
- package/build/utils/AnalysisStateManager.test.d.ts +0 -1
- package/build/utils/AnalysisStateManager.test.js +0 -134
- package/build/utils/dartRouteExtractor.test.d.ts +0 -1
- package/build/utils/dartRouteExtractor.test.js +0 -307
- package/build/utils/docker.test.d.ts +0 -1
- package/build/utils/docker.test.js +0 -114
- package/build/utils/featureFlags.test.d.ts +0 -1
- package/build/utils/featureFlags.test.js +0 -81
- package/build/utils/fileWalk.test.d.ts +0 -1
- package/build/utils/fileWalk.test.js +0 -252
- package/build/utils/frontendIntegration.test.d.ts +0 -1
- package/build/utils/frontendIntegration.test.js +0 -229
- package/build/utils/frontendSelectors.test.d.ts +0 -1
- package/build/utils/frontendSelectors.test.js +0 -118
- package/build/utils/gitStaging.test.d.ts +0 -1
- package/build/utils/gitStaging.test.js +0 -111
- package/build/utils/httpDefaults.test.d.ts +0 -1
- package/build/utils/httpDefaults.test.js +0 -21
- package/build/utils/importerHop.test.d.ts +0 -1
- package/build/utils/importerHop.test.js +0 -469
- package/build/utils/pathAffinityClassification.test.d.ts +0 -1
- package/build/utils/pathAffinityClassification.test.js +0 -208
- package/build/utils/planMatchKeys.test.d.ts +0 -1
- package/build/utils/planMatchKeys.test.js +0 -123
- package/build/utils/pom-scope/index.test.d.ts +0 -1
- package/build/utils/pom-scope/index.test.js +0 -278
- package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
- package/build/utils/pom-scope/pom-files.test.js +0 -29
- package/build/utils/pom-scope/scoring.test.d.ts +0 -1
- package/build/utils/pom-scope/scoring.test.js +0 -39
- package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
- package/build/utils/pom-scope/selector-extractor.test.js +0 -67
- package/build/utils/pom-verify/bindings.test.d.ts +0 -1
- package/build/utils/pom-verify/bindings.test.js +0 -164
- package/build/utils/pom-verify/calls.test.d.ts +0 -1
- package/build/utils/pom-verify/calls.test.js +0 -61
- package/build/utils/pom-verify/resolve.test.d.ts +0 -1
- package/build/utils/pom-verify/resolve.test.js +0 -114
- package/build/utils/pom-verify/verify.test.d.ts +0 -1
- package/build/utils/pom-verify/verify.test.js +0 -374
- package/build/utils/pr-comment-parser.test.d.ts +0 -1
- package/build/utils/pr-comment-parser.test.js +0 -428
- package/build/utils/progress.test.d.ts +0 -1
- package/build/utils/progress.test.js +0 -37
- package/build/utils/projectMetadata.test.d.ts +0 -1
- package/build/utils/projectMetadata.test.js +0 -172
- package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
- package/build/utils/pythonMountPrefixes.test.js +0 -113
- package/build/utils/repoScanner.test.d.ts +0 -1
- package/build/utils/repoScanner.test.js +0 -190
- package/build/utils/reportVerification.test.d.ts +0 -1
- package/build/utils/reportVerification.test.js +0 -185
- package/build/utils/routeParsers.test.d.ts +0 -1
- package/build/utils/routeParsers.test.js +0 -1011
- package/build/utils/scenarioDrafting.test.d.ts +0 -1
- package/build/utils/scenarioDrafting.test.js +0 -876
- package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
- package/build/utils/sourceRouteExtractor.test.js +0 -738
- package/build/utils/telemetry.test.d.ts +0 -1
- package/build/utils/telemetry.test.js +0 -70
- package/build/utils/trace-parser.test.d.ts +0 -6
- package/build/utils/trace-parser.test.js +0 -140
- package/build/utils/uiPageEnumerator.test.d.ts +0 -1
- package/build/utils/uiPageEnumerator.test.js +0 -824
- package/build/utils/utils.test.d.ts +0 -1
- package/build/utils/utils.test.js +0 -103
- package/build/utils/walkerCharacterization.test.d.ts +0 -1
- package/build/utils/walkerCharacterization.test.js +0 -233
- package/build/utils/workspaceAuth.test.d.ts +0 -1
- package/build/utils/workspaceAuth.test.js +0 -260
- package/build/workspace/testSuites.test.d.ts +0 -1
- package/build/workspace/testSuites.test.js +0 -23
- package/build/workspace/workspace.test.d.ts +0 -1
- package/build/workspace/workspace.test.js +0 -264
|
@@ -1,572 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
-
import { jest } from "@jest/globals";
|
|
3
|
-
import * as fs from "fs";
|
|
4
|
-
import * as os from "os";
|
|
5
|
-
import * as path from "path";
|
|
6
|
-
jest.unstable_mockModule("../../utils/logger.js", () => ({
|
|
7
|
-
logger: { info: jest.fn(), error: jest.fn(), warning: jest.fn(), debug: jest.fn() },
|
|
8
|
-
}));
|
|
9
|
-
jest.unstable_mockModule("../../services/AnalyticsService.js", () => ({
|
|
10
|
-
AnalyticsService: { pushMCPToolEvent: jest.fn().mockResolvedValue(undefined) },
|
|
11
|
-
}));
|
|
12
|
-
jest.unstable_mockModule("../../utils/gitStaging.js", () => ({
|
|
13
|
-
stageGeneratedPaths: jest.fn().mockResolvedValue(undefined),
|
|
14
|
-
}));
|
|
15
|
-
jest.unstable_mockModule("../../utils/pom-verify/index.js", () => ({
|
|
16
|
-
verifyReuse: jest.fn().mockResolvedValue({ ok: true, violations: [], unverifiable: [], checkedCalls: 3 }),
|
|
17
|
-
}));
|
|
18
|
-
const { registerCodeReuseTool } = await import("./codeReuseTool.js");
|
|
19
|
-
const { formatVerifyReport, formatZeroReuseGateFailure } = await import("./verify-gates.js");
|
|
20
|
-
const { stageGeneratedPaths } = await import("../../utils/gitStaging.js");
|
|
21
|
-
const { verifyReuse } = await import("../../utils/pom-verify/index.js");
|
|
22
|
-
// Minimal Skyramp runtime infra so zero-reuse-gate fixtures pass the (separate) infra gate and
|
|
23
|
-
// reach the logic under test.
|
|
24
|
-
const SKYRAMP_INFRA_PREFIX = `const { test, expect, newSkyrampPlaywrightPage } = require('@skyramp/skyramp');\nconst skyrampPage = newSkyrampPlaywrightPage(page, testInfo);\n`;
|
|
25
|
-
function captureToolHandler() {
|
|
26
|
-
let handler;
|
|
27
|
-
registerCodeReuseTool({ registerTool: (_n, _o, fn) => { handler = fn; } });
|
|
28
|
-
return handler;
|
|
29
|
-
}
|
|
30
|
-
describe("skyramp_reuse_code — verify mode", () => {
|
|
31
|
-
it("returns the verification report and skips prompt generation/staging when verify:true", async () => {
|
|
32
|
-
const handler = captureToolHandler();
|
|
33
|
-
const result = await handler({
|
|
34
|
-
testFile: "t.spec.ts",
|
|
35
|
-
language: "typescript",
|
|
36
|
-
framework: "playwright",
|
|
37
|
-
modularizeCode: false,
|
|
38
|
-
prompt: "",
|
|
39
|
-
verify: true,
|
|
40
|
-
});
|
|
41
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 3 calls checked.");
|
|
42
|
-
expect(verifyReuse).toHaveBeenCalledWith("t.spec.ts", "typescript");
|
|
43
|
-
expect(stageGeneratedPaths).not.toHaveBeenCalled();
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe("skyramp_reuse_code — verify mode zero-reuse compliance gate", () => {
|
|
47
|
-
it("fails verification when a zero-binding spec's selectors match a fixture POM file", async () => {
|
|
48
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
49
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-"));
|
|
50
|
-
try {
|
|
51
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
52
|
-
const pages = path.join(dir, "pages");
|
|
53
|
-
fs.mkdirSync(pages);
|
|
54
|
-
fs.writeFileSync(path.join(pages, "loginPage.js"), `export class LoginPage { constructor(page){ this.signIn = page.locator('[data-test="login-sign-in"]'); } }\n`);
|
|
55
|
-
const testsDir = path.join(dir, "tests");
|
|
56
|
-
fs.mkdirSync(testsDir);
|
|
57
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
58
|
-
fs.writeFileSync(testFile, `${SKYRAMP_INFRA_PREFIX}await page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
59
|
-
const handler = captureToolHandler();
|
|
60
|
-
const result = await handler({
|
|
61
|
-
testFile,
|
|
62
|
-
language: "javascript",
|
|
63
|
-
framework: "playwright",
|
|
64
|
-
modularizeCode: false,
|
|
65
|
-
prompt: "",
|
|
66
|
-
verify: true,
|
|
67
|
-
});
|
|
68
|
-
expect(result.content[0].text).toContain("VERIFICATION FAILED — this test contains no page-object reuse, but detection found reusable POM candidates for its selectors:");
|
|
69
|
-
expect(result.content[0].text).toContain("loginPage.js");
|
|
70
|
-
}
|
|
71
|
-
finally {
|
|
72
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
it("returns the normal PASSED response when a zero-binding spec's selectors only match discovery-fallback app source (no conventional POM dirs)", async () => {
|
|
76
|
-
// A POM-less repo whose in-repo frontend legitimately contains the spec's test-ids (built the
|
|
77
|
-
// markup, not a page-object layer) must not be gated — the selector-grep discovery fallback
|
|
78
|
-
// finding overlap here is not evidence that reuse was skipped.
|
|
79
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
80
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-nomatch-"));
|
|
81
|
-
try {
|
|
82
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
83
|
-
fs.mkdirSync(path.join(dir, "src", "components"), { recursive: true });
|
|
84
|
-
fs.writeFileSync(path.join(dir, "src", "components", "LoginForm.jsx"), `export function LoginForm() {\n return (<form>\n <input data-test="login-email" />\n <input data-test="login-password" />\n <button data-test="login-sign-in">Sign in</button>\n </form>);\n}\n`);
|
|
85
|
-
const testsDir = path.join(dir, "tests");
|
|
86
|
-
fs.mkdirSync(testsDir);
|
|
87
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
88
|
-
fs.writeFileSync(testFile, `${SKYRAMP_INFRA_PREFIX}await page.locator('[data-test="login-email"]').fill('a@b.c');\nawait page.locator('[data-test="login-password"]').fill('x');\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
89
|
-
const handler = captureToolHandler();
|
|
90
|
-
const result = await handler({
|
|
91
|
-
testFile,
|
|
92
|
-
language: "javascript",
|
|
93
|
-
framework: "playwright",
|
|
94
|
-
modularizeCode: false,
|
|
95
|
-
prompt: "",
|
|
96
|
-
verify: true,
|
|
97
|
-
});
|
|
98
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 0 calls checked.");
|
|
99
|
-
}
|
|
100
|
-
finally {
|
|
101
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
it("does not fire the gate when a deep-chain-only reuse leaves unverifiable entries (0 checked calls is not 0 reuse)", async () => {
|
|
105
|
-
// Reuse expressed entirely as a 2-hop chain (assetPage.section.method()) is non-strict, so
|
|
106
|
-
// verifyReuse reports it under `unverifiable`, not `checkedCalls`. Without the unverifiable
|
|
107
|
-
// guard this would look identical to a zero-reuse spec and falsely fire the gate.
|
|
108
|
-
verifyReuse.mockResolvedValueOnce({
|
|
109
|
-
ok: true,
|
|
110
|
-
violations: [],
|
|
111
|
-
unverifiable: ["assetPage.section.method"],
|
|
112
|
-
checkedCalls: 0,
|
|
113
|
-
});
|
|
114
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-deepchain-"));
|
|
115
|
-
try {
|
|
116
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
117
|
-
const pages = path.join(dir, "pages");
|
|
118
|
-
fs.mkdirSync(pages);
|
|
119
|
-
fs.writeFileSync(path.join(pages, "assetPage.js"), `export class AssetPage { constructor(page){ this.entryBtn = page.locator('[data-test="asset-entry"]'); } }\n`);
|
|
120
|
-
const testsDir = path.join(dir, "tests");
|
|
121
|
-
fs.mkdirSync(testsDir);
|
|
122
|
-
const testFile = path.join(testsDir, "refactored.spec.js");
|
|
123
|
-
fs.writeFileSync(testFile, `${SKYRAMP_INFRA_PREFIX}await assetPage.section.method();\nawait page.locator('[data-test="asset-entry"]').click();\n`);
|
|
124
|
-
const handler = captureToolHandler();
|
|
125
|
-
const result = await handler({
|
|
126
|
-
testFile,
|
|
127
|
-
language: "javascript",
|
|
128
|
-
framework: "playwright",
|
|
129
|
-
modularizeCode: false,
|
|
130
|
-
prompt: "",
|
|
131
|
-
verify: true,
|
|
132
|
-
});
|
|
133
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 0 calls checked.\nUnverifiable (informational): assetPage.section.method");
|
|
134
|
-
}
|
|
135
|
-
finally {
|
|
136
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
it("falls through to PASSED when every tier1 candidate is documented with a `// kept inline:` comment", async () => {
|
|
140
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
141
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-documented-"));
|
|
142
|
-
try {
|
|
143
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
144
|
-
const pages = path.join(dir, "pages");
|
|
145
|
-
fs.mkdirSync(pages);
|
|
146
|
-
fs.writeFileSync(path.join(pages, "loginPage.js"), `export class LoginPage { constructor(page){ this.signIn = page.locator('[data-test="login-sign-in"]'); } }\n`);
|
|
147
|
-
const testsDir = path.join(dir, "tests");
|
|
148
|
-
fs.mkdirSync(testsDir);
|
|
149
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
150
|
-
fs.writeFileSync(testFile, `${SKYRAMP_INFRA_PREFIX}// kept inline: loginPage.js — this flow doesn't own the sign-in frame\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
151
|
-
const handler = captureToolHandler();
|
|
152
|
-
const result = await handler({
|
|
153
|
-
testFile,
|
|
154
|
-
language: "javascript",
|
|
155
|
-
framework: "playwright",
|
|
156
|
-
modularizeCode: false,
|
|
157
|
-
prompt: "",
|
|
158
|
-
verify: true,
|
|
159
|
-
});
|
|
160
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 0 calls checked.");
|
|
161
|
-
}
|
|
162
|
-
finally {
|
|
163
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
it("accepts the exact comment format the demote flow instructs (demote → re-verify must not gate-fail)", async () => {
|
|
167
|
-
// formatVerifyReport tells a demoting agent to write `// kept inline: <POM file basename> — no
|
|
168
|
-
// matching POM method`. When the last strict call is demoted, the re-verify pass reaches this
|
|
169
|
-
// gate with checkedCalls === 0 — the demote comment itself must satisfy it, or the agent is
|
|
170
|
-
// told to re-document locators it already correctly documented.
|
|
171
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
172
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-demoted-"));
|
|
173
|
-
try {
|
|
174
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
175
|
-
const pages = path.join(dir, "pages");
|
|
176
|
-
fs.mkdirSync(pages);
|
|
177
|
-
fs.writeFileSync(path.join(pages, "loginPage.js"), `export class LoginPage { constructor(page){ this.signIn = page.locator('[data-test="login-sign-in"]'); } }\n`);
|
|
178
|
-
const testsDir = path.join(dir, "tests");
|
|
179
|
-
fs.mkdirSync(testsDir);
|
|
180
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
181
|
-
fs.writeFileSync(testFile, `${SKYRAMP_INFRA_PREFIX}await page.locator('[data-test="login-sign-in"]').click(); // kept inline: loginPage.js — no matching POM method\n`);
|
|
182
|
-
const handler = captureToolHandler();
|
|
183
|
-
const result = await handler({
|
|
184
|
-
testFile,
|
|
185
|
-
language: "javascript",
|
|
186
|
-
framework: "playwright",
|
|
187
|
-
modularizeCode: false,
|
|
188
|
-
prompt: "",
|
|
189
|
-
verify: true,
|
|
190
|
-
});
|
|
191
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 0 calls checked.");
|
|
192
|
-
}
|
|
193
|
-
finally {
|
|
194
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
it("does NOT accept a bare-basename kept-inline comment (a reason is required)", async () => {
|
|
198
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
199
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-bare-"));
|
|
200
|
-
try {
|
|
201
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
202
|
-
const pages = path.join(dir, "pages");
|
|
203
|
-
fs.mkdirSync(pages);
|
|
204
|
-
fs.writeFileSync(path.join(pages, "loginPage.js"), `export class LoginPage { constructor(page){ this.signIn = page.locator('[data-test="login-sign-in"]'); } }\n`);
|
|
205
|
-
const testsDir = path.join(dir, "tests");
|
|
206
|
-
fs.mkdirSync(testsDir);
|
|
207
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
208
|
-
fs.writeFileSync(testFile,
|
|
209
|
-
// bare basename, no dash-separated reason — the lazy bypass the format check rejects
|
|
210
|
-
`${SKYRAMP_INFRA_PREFIX}// kept inline: loginPage.js\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
211
|
-
const handler = captureToolHandler();
|
|
212
|
-
const result = await handler({
|
|
213
|
-
testFile,
|
|
214
|
-
language: "javascript",
|
|
215
|
-
framework: "playwright",
|
|
216
|
-
modularizeCode: false,
|
|
217
|
-
prompt: "",
|
|
218
|
-
verify: true,
|
|
219
|
-
});
|
|
220
|
-
expect(result.content[0].text).toContain("VERIFICATION FAILED — this test contains no page-object reuse");
|
|
221
|
-
}
|
|
222
|
-
finally {
|
|
223
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
it("does NOT accept a kept-inline marker embedded in a string literal (only a real comment counts)", async () => {
|
|
227
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
228
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-string-"));
|
|
229
|
-
try {
|
|
230
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
231
|
-
const pages = path.join(dir, "pages");
|
|
232
|
-
fs.mkdirSync(pages);
|
|
233
|
-
fs.writeFileSync(path.join(pages, "loginPage.js"), `export class LoginPage { constructor(page){ this.signIn = page.locator('[data-test="login-sign-in"]'); } }\n`);
|
|
234
|
-
const testsDir = path.join(dir, "tests");
|
|
235
|
-
fs.mkdirSync(testsDir);
|
|
236
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
237
|
-
fs.writeFileSync(testFile,
|
|
238
|
-
// full marker format, but inside quoted text — must not satisfy the gate
|
|
239
|
-
`${SKYRAMP_INFRA_PREFIX}console.log("// kept inline: loginPage.js — not a real comment");\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
240
|
-
const handler = captureToolHandler();
|
|
241
|
-
const result = await handler({
|
|
242
|
-
testFile,
|
|
243
|
-
language: "javascript",
|
|
244
|
-
framework: "playwright",
|
|
245
|
-
modularizeCode: false,
|
|
246
|
-
prompt: "",
|
|
247
|
-
verify: true,
|
|
248
|
-
});
|
|
249
|
-
expect(result.content[0].text).toContain("VERIFICATION FAILED — this test contains no page-object reuse");
|
|
250
|
-
}
|
|
251
|
-
finally {
|
|
252
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
it("surfaces the parse-error remediation, not the gate text, when the spec has broken syntax", async () => {
|
|
256
|
-
verifyReuse.mockResolvedValueOnce({
|
|
257
|
-
ok: false,
|
|
258
|
-
violations: [],
|
|
259
|
-
unverifiable: [],
|
|
260
|
-
checkedCalls: 0,
|
|
261
|
-
parseError: "SyntaxError: Unexpected end of input",
|
|
262
|
-
});
|
|
263
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-parseerror-"));
|
|
264
|
-
try {
|
|
265
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
266
|
-
const pages = path.join(dir, "pages");
|
|
267
|
-
fs.mkdirSync(pages);
|
|
268
|
-
fs.writeFileSync(path.join(pages, "loginPage.js"), `export class LoginPage { constructor(page){ this.signIn = page.locator('[data-test="login-sign-in"]'); } }\n`);
|
|
269
|
-
const testsDir = path.join(dir, "tests");
|
|
270
|
-
fs.mkdirSync(testsDir);
|
|
271
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
272
|
-
fs.writeFileSync(testFile, `await page.locator('[data-test="login-sign-in"]').click(\n`); // unbalanced paren
|
|
273
|
-
const handler = captureToolHandler();
|
|
274
|
-
const result = await handler({
|
|
275
|
-
testFile,
|
|
276
|
-
language: "javascript",
|
|
277
|
-
framework: "playwright",
|
|
278
|
-
modularizeCode: false,
|
|
279
|
-
prompt: "",
|
|
280
|
-
verify: true,
|
|
281
|
-
});
|
|
282
|
-
expect(result.content[0].text).toContain("Parse error (fix the syntax and re-verify): SyntaxError: Unexpected end of input");
|
|
283
|
-
expect(result.content[0].text).not.toContain("VERIFICATION FAILED — this test contains no page-object reuse");
|
|
284
|
-
}
|
|
285
|
-
finally {
|
|
286
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
it("never fires the gate for a non-Playwright framework, even with matching POM candidates", async () => {
|
|
290
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
291
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-gate-nonplaywright-"));
|
|
292
|
-
try {
|
|
293
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
294
|
-
const pages = path.join(dir, "pages");
|
|
295
|
-
fs.mkdirSync(pages);
|
|
296
|
-
fs.writeFileSync(path.join(pages, "loginPage.js"), `export class LoginPage { constructor(page){ this.signIn = page.locator('[data-test="login-sign-in"]'); } }\n`);
|
|
297
|
-
const testsDir = path.join(dir, "tests");
|
|
298
|
-
fs.mkdirSync(testsDir);
|
|
299
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
300
|
-
fs.writeFileSync(testFile, `await page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
301
|
-
const handler = captureToolHandler();
|
|
302
|
-
const result = await handler({
|
|
303
|
-
testFile,
|
|
304
|
-
language: "javascript",
|
|
305
|
-
framework: "cypress",
|
|
306
|
-
modularizeCode: false,
|
|
307
|
-
prompt: "",
|
|
308
|
-
verify: true,
|
|
309
|
-
});
|
|
310
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 0 calls checked.");
|
|
311
|
-
}
|
|
312
|
-
finally {
|
|
313
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
it("falls through to PASSED when POM scoping fails (e.g. testFile in a nonexistent directory)", async () => {
|
|
317
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 0 });
|
|
318
|
-
const testFile = path.join(os.tmpdir(), "code-reuse-gate-does-not-exist", "generated.spec.js");
|
|
319
|
-
const handler = captureToolHandler();
|
|
320
|
-
const result = await handler({
|
|
321
|
-
testFile,
|
|
322
|
-
language: "javascript",
|
|
323
|
-
framework: "playwright",
|
|
324
|
-
modularizeCode: false,
|
|
325
|
-
prompt: "",
|
|
326
|
-
verify: true,
|
|
327
|
-
});
|
|
328
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 0 calls checked.");
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
describe("skyramp_reuse_code — verify mode infra gate", () => {
|
|
332
|
-
it("fails verification when the Skyramp runtime import is missing entirely (repo fixtures used instead)", async () => {
|
|
333
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 2 });
|
|
334
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-noimport-"));
|
|
335
|
-
try {
|
|
336
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
337
|
-
const testsDir = path.join(dir, "tests");
|
|
338
|
-
fs.mkdirSync(testsDir);
|
|
339
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
340
|
-
fs.writeFileSync(testFile, `const { test, expect } = require('../fixtures/enhanced-baseFixtures');\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
341
|
-
const handler = captureToolHandler();
|
|
342
|
-
const result = await handler({
|
|
343
|
-
testFile,
|
|
344
|
-
language: "javascript",
|
|
345
|
-
framework: "playwright",
|
|
346
|
-
modularizeCode: false,
|
|
347
|
-
prompt: "",
|
|
348
|
-
verify: true,
|
|
349
|
-
});
|
|
350
|
-
expect(result.content[0].text).toContain("VERIFICATION FAILED — the Skyramp runtime infrastructure is missing");
|
|
351
|
-
}
|
|
352
|
-
finally {
|
|
353
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
354
|
-
}
|
|
355
|
-
});
|
|
356
|
-
it("fails verification when @skyramp/skyramp is imported but newSkyrampPlaywrightPage( is never called", async () => {
|
|
357
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 2 });
|
|
358
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-nowrapper-"));
|
|
359
|
-
try {
|
|
360
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
361
|
-
const testsDir = path.join(dir, "tests");
|
|
362
|
-
fs.mkdirSync(testsDir);
|
|
363
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
364
|
-
fs.writeFileSync(testFile, `const { test, expect } = require('@skyramp/skyramp');\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
365
|
-
const handler = captureToolHandler();
|
|
366
|
-
const result = await handler({
|
|
367
|
-
testFile,
|
|
368
|
-
language: "javascript",
|
|
369
|
-
framework: "playwright",
|
|
370
|
-
modularizeCode: false,
|
|
371
|
-
prompt: "",
|
|
372
|
-
verify: true,
|
|
373
|
-
});
|
|
374
|
-
expect(result.content[0].text).toContain("VERIFICATION FAILED — the Skyramp runtime infrastructure is missing");
|
|
375
|
-
}
|
|
376
|
-
finally {
|
|
377
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
it("fails verification when the runtime import and wrapper call are only present commented out", async () => {
|
|
381
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 2 });
|
|
382
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-commented-"));
|
|
383
|
-
try {
|
|
384
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
385
|
-
const testsDir = path.join(dir, "tests");
|
|
386
|
-
fs.mkdirSync(testsDir);
|
|
387
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
388
|
-
fs.writeFileSync(testFile, `// const { test, expect, newSkyrampPlaywrightPage } = require('@skyramp/skyramp');\n// const skyrampPage = newSkyrampPlaywrightPage(page, testInfo);\nconst { test, expect } = require('../fixtures/enhanced-baseFixtures');\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
389
|
-
const handler = captureToolHandler();
|
|
390
|
-
const result = await handler({
|
|
391
|
-
testFile,
|
|
392
|
-
language: "javascript",
|
|
393
|
-
framework: "playwright",
|
|
394
|
-
modularizeCode: false,
|
|
395
|
-
prompt: "",
|
|
396
|
-
verify: true,
|
|
397
|
-
});
|
|
398
|
-
expect(result.content[0].text).toContain("VERIFICATION FAILED — the Skyramp runtime infrastructure is missing");
|
|
399
|
-
}
|
|
400
|
-
finally {
|
|
401
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
it("fails verification when the wrapper call appears only inside a string literal", async () => {
|
|
405
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 2 });
|
|
406
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-string-"));
|
|
407
|
-
try {
|
|
408
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
409
|
-
const testsDir = path.join(dir, "tests");
|
|
410
|
-
fs.mkdirSync(testsDir);
|
|
411
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
412
|
-
fs.writeFileSync(testFile,
|
|
413
|
-
// real import, but the wrapper is never actually called — only mentioned in prose
|
|
414
|
-
`const { test, expect } = require('@skyramp/skyramp');\nconsole.log("newSkyrampPlaywrightPage( is not needed here");\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
415
|
-
const handler = captureToolHandler();
|
|
416
|
-
const result = await handler({
|
|
417
|
-
testFile,
|
|
418
|
-
language: "javascript",
|
|
419
|
-
framework: "playwright",
|
|
420
|
-
modularizeCode: false,
|
|
421
|
-
prompt: "",
|
|
422
|
-
verify: true,
|
|
423
|
-
});
|
|
424
|
-
expect(result.content[0].text).toContain("VERIFICATION FAILED — the Skyramp runtime infrastructure is missing");
|
|
425
|
-
}
|
|
426
|
-
finally {
|
|
427
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
|
-
it("appends the mapping-violation report when the infra gate fires on a spec that also has violations", async () => {
|
|
431
|
-
verifyReuse.mockResolvedValueOnce({
|
|
432
|
-
ok: false,
|
|
433
|
-
violations: [{ binding: "pm", member: "fakeMethod", searched: ["pages/loginPage.js"], availableMembers: ["login"] }],
|
|
434
|
-
unverifiable: [],
|
|
435
|
-
checkedCalls: 1,
|
|
436
|
-
});
|
|
437
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-violations-"));
|
|
438
|
-
try {
|
|
439
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
440
|
-
const testsDir = path.join(dir, "tests");
|
|
441
|
-
fs.mkdirSync(testsDir);
|
|
442
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
443
|
-
fs.writeFileSync(testFile, `const { test, expect } = require('../fixtures/enhanced-baseFixtures');\nawait pm.fakeMethod();\n`);
|
|
444
|
-
const handler = captureToolHandler();
|
|
445
|
-
const result = await handler({
|
|
446
|
-
testFile,
|
|
447
|
-
language: "javascript",
|
|
448
|
-
framework: "playwright",
|
|
449
|
-
modularizeCode: false,
|
|
450
|
-
prompt: "",
|
|
451
|
-
verify: true,
|
|
452
|
-
});
|
|
453
|
-
const text = result.content[0].text;
|
|
454
|
-
expect(text).toContain("VERIFICATION FAILED — the Skyramp runtime infrastructure is missing");
|
|
455
|
-
expect(text).toContain("pm.fakeMethod — not found in pages/loginPage.js. Available members: login");
|
|
456
|
-
}
|
|
457
|
-
finally {
|
|
458
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
459
|
-
}
|
|
460
|
-
});
|
|
461
|
-
it("does not fire the infra gate when both the import and the wrapper call are present", async () => {
|
|
462
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 2 });
|
|
463
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-present-"));
|
|
464
|
-
try {
|
|
465
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
466
|
-
const testsDir = path.join(dir, "tests");
|
|
467
|
-
fs.mkdirSync(testsDir);
|
|
468
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
469
|
-
fs.writeFileSync(testFile, `${SKYRAMP_INFRA_PREFIX}await page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
470
|
-
const handler = captureToolHandler();
|
|
471
|
-
const result = await handler({
|
|
472
|
-
testFile,
|
|
473
|
-
language: "javascript",
|
|
474
|
-
framework: "playwright",
|
|
475
|
-
modularizeCode: false,
|
|
476
|
-
prompt: "",
|
|
477
|
-
verify: true,
|
|
478
|
-
});
|
|
479
|
-
expect(result.content[0].text).not.toContain("VERIFICATION FAILED — the Skyramp runtime infrastructure is missing");
|
|
480
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 2 calls checked.");
|
|
481
|
-
}
|
|
482
|
-
finally {
|
|
483
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
it("never fires the infra gate for a non-Playwright framework", async () => {
|
|
487
|
-
verifyReuse.mockResolvedValueOnce({ ok: true, violations: [], unverifiable: [], checkedCalls: 2 });
|
|
488
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-nonplaywright-"));
|
|
489
|
-
try {
|
|
490
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
491
|
-
const testsDir = path.join(dir, "tests");
|
|
492
|
-
fs.mkdirSync(testsDir);
|
|
493
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
494
|
-
fs.writeFileSync(testFile, `const { test, expect } = require('../fixtures/enhanced-baseFixtures');\nawait page.locator('[data-test="login-sign-in"]').click();\n`);
|
|
495
|
-
const handler = captureToolHandler();
|
|
496
|
-
const result = await handler({
|
|
497
|
-
testFile,
|
|
498
|
-
language: "javascript",
|
|
499
|
-
framework: "cypress",
|
|
500
|
-
modularizeCode: false,
|
|
501
|
-
prompt: "",
|
|
502
|
-
verify: true,
|
|
503
|
-
});
|
|
504
|
-
expect(result.content[0].text).toBe("VERIFICATION PASSED — 2 calls checked.");
|
|
505
|
-
}
|
|
506
|
-
finally {
|
|
507
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
it("surfaces the parse-error remediation, not the infra text, when the spec has broken syntax and is missing the imports", async () => {
|
|
511
|
-
verifyReuse.mockResolvedValueOnce({
|
|
512
|
-
ok: false,
|
|
513
|
-
violations: [],
|
|
514
|
-
unverifiable: [],
|
|
515
|
-
checkedCalls: 0,
|
|
516
|
-
parseError: "SyntaxError: Unexpected end of input",
|
|
517
|
-
});
|
|
518
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "code-reuse-infra-parseerror-"));
|
|
519
|
-
try {
|
|
520
|
-
fs.writeFileSync(path.join(dir, "package.json"), "{}");
|
|
521
|
-
const testsDir = path.join(dir, "tests");
|
|
522
|
-
fs.mkdirSync(testsDir);
|
|
523
|
-
const testFile = path.join(testsDir, "generated.spec.js");
|
|
524
|
-
fs.writeFileSync(testFile, `await page.locator('[data-test="login-sign-in"]').click(\n`); // unbalanced paren, no skyramp imports
|
|
525
|
-
const handler = captureToolHandler();
|
|
526
|
-
const result = await handler({
|
|
527
|
-
testFile,
|
|
528
|
-
language: "javascript",
|
|
529
|
-
framework: "playwright",
|
|
530
|
-
modularizeCode: false,
|
|
531
|
-
prompt: "",
|
|
532
|
-
verify: true,
|
|
533
|
-
});
|
|
534
|
-
expect(result.content[0].text).toContain("Parse error (fix the syntax and re-verify): SyntaxError: Unexpected end of input");
|
|
535
|
-
expect(result.content[0].text).not.toContain("VERIFICATION FAILED — the Skyramp runtime infrastructure is missing");
|
|
536
|
-
}
|
|
537
|
-
finally {
|
|
538
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
539
|
-
}
|
|
540
|
-
});
|
|
541
|
-
});
|
|
542
|
-
describe("formatVerifyReport", () => {
|
|
543
|
-
it("reports a violation block with the fix-rule paragraph, not the passed message", () => {
|
|
544
|
-
const text = formatVerifyReport({
|
|
545
|
-
ok: false,
|
|
546
|
-
violations: [{ binding: "pm", member: "fakeMethod", searched: ["a.ts", "b.ts"], availableMembers: ["realMethod"] }],
|
|
547
|
-
unverifiable: [],
|
|
548
|
-
checkedCalls: 1,
|
|
549
|
-
});
|
|
550
|
-
expect(text).toContain("VERIFICATION FAILED");
|
|
551
|
-
expect(text).toContain("pm.fakeMethod — not found in a.ts (+1-hop). Available members: realMethod");
|
|
552
|
-
expect(text).toContain("Do not finish until it reports PASSED.");
|
|
553
|
-
});
|
|
554
|
-
});
|
|
555
|
-
describe("formatZeroReuseGateFailure", () => {
|
|
556
|
-
it("lists each tier1 candidate with its matched tokens", () => {
|
|
557
|
-
const text = formatZeroReuseGateFailure([
|
|
558
|
-
{ file: "pages/loginPage.js", score: 1, rareHits: 1, matchedTokens: ["login-sign-in", "login-submit"] },
|
|
559
|
-
]);
|
|
560
|
-
expect(text).toContain("VERIFICATION FAILED — this test contains no page-object reuse, but detection found reusable POM candidates for its selectors:");
|
|
561
|
-
expect(text).toContain("- pages/loginPage.js (matched: login-sign-in, login-submit)");
|
|
562
|
-
expect(text).toContain("A raw locator that matches a POM property verbatim is evidence TO substitute, never a reason to stay inline.");
|
|
563
|
-
expect(text).toContain("Only finish with raw locators if you add a comment for each file above — `// kept inline: <file basename> — <reason it cannot cover this test>` — then re-run this verification, which will accept the documented files.");
|
|
564
|
-
});
|
|
565
|
-
it("labels an import-expanded candidate (no own token hits) instead of printing an empty matched list", () => {
|
|
566
|
-
const text = formatZeroReuseGateFailure([
|
|
567
|
-
{ file: "pages/basePage.js", score: 1, rareHits: 0, matchedTokens: [] },
|
|
568
|
-
]);
|
|
569
|
-
expect(text).toContain("- pages/basePage.js (imported by a matched page-object file)");
|
|
570
|
-
expect(text).not.toContain("(matched: )");
|
|
571
|
-
});
|
|
572
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|