@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 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
// @ts-ignore
|
|
2
|
-
import { validateParams, generateSkyrampHeader, testFileMatches } from "./utils.js";
|
|
3
|
-
describe("testFileMatches", () => {
|
|
4
|
-
it("matches identical absolute paths", () => {
|
|
5
|
-
expect(testFileMatches("/repo/tests/orders_test.py", "/repo/tests/orders_test.py")).toBe(true);
|
|
6
|
-
});
|
|
7
|
-
it("does not match two different absolute paths, even with the same basename", () => {
|
|
8
|
-
expect(testFileMatches("/repo/frontend/tests/utils_test.py", "/repo/backend/tests/utils_test.py")).toBe(false);
|
|
9
|
-
});
|
|
10
|
-
it("matches a relative candidate against a real path-segment boundary", () => {
|
|
11
|
-
expect(testFileMatches("/repo/backend/tests/orders_test.py", "tests/orders_test.py")).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
it("does not match a relative candidate that is only a substring, not a path-segment boundary", () => {
|
|
14
|
-
// "ers_test.py" is a suffix of the basename but not preceded by a path separator.
|
|
15
|
-
expect(testFileMatches("/repo/backend/tests/orders_test.py", "ers_test.py")).toBe(false);
|
|
16
|
-
});
|
|
17
|
-
it("falls back to basename equality only when the candidate has no path info at all", () => {
|
|
18
|
-
expect(testFileMatches("/repo/backend/tests/orders_test.py", "orders_test.py")).toBe(true);
|
|
19
|
-
});
|
|
20
|
-
it("bare-basename fallback is ambiguous across two files that share a basename (documented limitation)", () => {
|
|
21
|
-
expect(testFileMatches("/repo/frontend/tests/utils_test.py", "utils_test.py")).toBe(true);
|
|
22
|
-
expect(testFileMatches("/repo/backend/tests/utils_test.py", "utils_test.py")).toBe(true);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
describe("validateParams", () => {
|
|
26
|
-
it("should return null for valid comma-separated key=value pairs", () => {
|
|
27
|
-
const result = validateParams("foo=bar,baz=qux", "testField");
|
|
28
|
-
expect(result).toBeNull();
|
|
29
|
-
});
|
|
30
|
-
it("should return null for empty string", () => {
|
|
31
|
-
const result = validateParams("", "testField");
|
|
32
|
-
expect(result).toBeNull();
|
|
33
|
-
});
|
|
34
|
-
it("should return error for JSON-like input", () => {
|
|
35
|
-
const result = validateParams('{"foo":"bar"}', "testField");
|
|
36
|
-
expect(result?.isError).toBe(true);
|
|
37
|
-
const firstContent = result?.content?.[0];
|
|
38
|
-
expect(firstContent?.type).toBe("text");
|
|
39
|
-
if (firstContent?.type === "text") {
|
|
40
|
-
expect(firstContent.text).toMatch(/key=value/);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
it("should return error for missing value", () => {
|
|
44
|
-
const result = validateParams("foo=", "testField");
|
|
45
|
-
expect(result?.isError).toBe(true);
|
|
46
|
-
const firstContent = result?.content?.[0];
|
|
47
|
-
expect(firstContent?.type).toBe("text");
|
|
48
|
-
if (firstContent?.type === "text") {
|
|
49
|
-
expect(firstContent.text).toMatch(/key=value/);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
it("should return error for missing key", () => {
|
|
53
|
-
const result = validateParams("=bar", "testField");
|
|
54
|
-
expect(result?.isError).toBe(true);
|
|
55
|
-
const firstContent = result?.content?.[0];
|
|
56
|
-
expect(firstContent?.type).toBe("text");
|
|
57
|
-
if (firstContent?.type === "text") {
|
|
58
|
-
expect(firstContent.text).toMatch(/key=value/);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
it("should return error for missing key and value", () => {
|
|
62
|
-
const result = validateParams("=", "testField");
|
|
63
|
-
expect(result?.isError).toBe(true);
|
|
64
|
-
const firstContent = result?.content?.[0];
|
|
65
|
-
expect(firstContent?.type).toBe("text");
|
|
66
|
-
if (firstContent?.type === "text") {
|
|
67
|
-
expect(firstContent.text).toMatch(/key=value/);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
describe("generateSkyrampHeader", () => {
|
|
72
|
-
it("should generate correct header for Python", () => {
|
|
73
|
-
const header = generateSkyrampHeader("python");
|
|
74
|
-
expect(header).toMatch(/^# Generated by Skyramp on/);
|
|
75
|
-
expect(header).toContain("\n\n");
|
|
76
|
-
});
|
|
77
|
-
it("should generate correct header for JavaScript", () => {
|
|
78
|
-
const header = generateSkyrampHeader("javascript");
|
|
79
|
-
expect(header).toMatch(/^\/\/ Generated by Skyramp on/);
|
|
80
|
-
expect(header).toContain("\n\n");
|
|
81
|
-
});
|
|
82
|
-
it("should generate correct header for TypeScript", () => {
|
|
83
|
-
const header = generateSkyrampHeader("typescript");
|
|
84
|
-
expect(header).toMatch(/^\/\/ Generated by Skyramp on/);
|
|
85
|
-
expect(header).toContain("\n\n");
|
|
86
|
-
});
|
|
87
|
-
it("should generate correct header for Java", () => {
|
|
88
|
-
const header = generateSkyrampHeader("java");
|
|
89
|
-
expect(header).toMatch(/^\/\/ Generated by Skyramp on/);
|
|
90
|
-
expect(header).toContain("\n\n");
|
|
91
|
-
});
|
|
92
|
-
it("should generate correct header for unknown language", () => {
|
|
93
|
-
const header = generateSkyrampHeader("unknown");
|
|
94
|
-
expect(header).toMatch(/^# Generated by Skyramp on/);
|
|
95
|
-
expect(header).toContain("\n\n");
|
|
96
|
-
});
|
|
97
|
-
it("should include timestamp in header", () => {
|
|
98
|
-
const header = generateSkyrampHeader("python");
|
|
99
|
-
// Check that the header contains a timestamp in the expected format
|
|
100
|
-
expect(header).toMatch(/on \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}/);
|
|
101
|
-
expect(header).toMatch(/Generated by Skyramp/);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
// Characterization tests for the SIX callers that were migrated onto the shared
|
|
2
|
-
// walkDir/collectFiles primitives. These pin each caller's directory-walking
|
|
3
|
-
// behavior (skip-dirs, dotfile skipping, depth caps, count caps, match
|
|
4
|
-
// predicates, first-match, path normalization, best-effort) through real
|
|
5
|
-
// filesystem fixtures, so the pre-refactor hand-rolled walkers and the
|
|
6
|
-
// post-refactor walkDir-based ones are proven to behave identically.
|
|
7
|
-
//
|
|
8
|
-
// They deliberately exercise the PUBLIC entry points (plus the two
|
|
9
|
-
// TestExecutionService helpers, exported for this purpose) rather than the
|
|
10
|
-
// primitives — the primitives have their own unit tests in fileWalk.test.ts;
|
|
11
|
-
// here we verify each caller wires the primitive up the same way it walked
|
|
12
|
-
// before.
|
|
13
|
-
import { jest } from "@jest/globals";
|
|
14
|
-
import * as fs from "fs";
|
|
15
|
-
import * as os from "os";
|
|
16
|
-
import * as path from "path";
|
|
17
|
-
// TestExecutionService imports dockerode at module load; stub it so importing
|
|
18
|
-
// the module needs no Docker daemon. Everything else uses the REAL fs.
|
|
19
|
-
jest.unstable_mockModule("dockerode", () => ({
|
|
20
|
-
default: jest
|
|
21
|
-
.fn()
|
|
22
|
-
.mockImplementation(() => ({ run: jest.fn(), listImages: jest.fn() })),
|
|
23
|
-
}));
|
|
24
|
-
const { extractDartRoutes } = await import("./dartRouteExtractor.js");
|
|
25
|
-
const { extractSourceRoutes } = await import("./sourceRouteExtractor.js");
|
|
26
|
-
const { discoverTraceFiles, discoverPlaywrightZips } = await import("./trace-parser.js");
|
|
27
|
-
const { checkFrontendFileIntegration } = await import("./frontendIntegration.js");
|
|
28
|
-
const { collectVideoPath, findExcludedPaths } = await import("../services/TestExecutionService.js");
|
|
29
|
-
/** Materialize a file tree under a fresh temp dir; values are file contents. */
|
|
30
|
-
function makeTree(files) {
|
|
31
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), "walker-char-"));
|
|
32
|
-
for (const [rel, content] of Object.entries(files)) {
|
|
33
|
-
const abs = path.join(root, rel);
|
|
34
|
-
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
35
|
-
fs.writeFileSync(abs, content);
|
|
36
|
-
}
|
|
37
|
-
return root;
|
|
38
|
-
}
|
|
39
|
-
function relSorted(root, abs) {
|
|
40
|
-
return abs
|
|
41
|
-
.map((p) => path.relative(root, p).replace(/\\/g, "/"))
|
|
42
|
-
.sort();
|
|
43
|
-
}
|
|
44
|
-
// ── dartRouteExtractor.findDartFiles ────────────────────────────────────────
|
|
45
|
-
describe("extractDartRoutes — findDartFiles traversal", () => {
|
|
46
|
-
const GO_ROUTE = (p) => `GoRoute(path: '${p}', builder: (c, s) => Screen());`;
|
|
47
|
-
it("discovers .dart files in normal nested directories", () => {
|
|
48
|
-
const root = makeTree({
|
|
49
|
-
"lib/router.dart": GO_ROUTE("/home"),
|
|
50
|
-
"lib/feature/routes.dart": GO_ROUTE("/feature"),
|
|
51
|
-
});
|
|
52
|
-
expect(extractDartRoutes(root).map((r) => r.path).sort()).toEqual([
|
|
53
|
-
"/feature",
|
|
54
|
-
"/home",
|
|
55
|
-
]);
|
|
56
|
-
});
|
|
57
|
-
it("skips dotfile directories not listed in SKIP_DIRS (startsWith '.')", () => {
|
|
58
|
-
// `.cache` is NOT in dart SKIP_DIRS — only the generic dotfile-dir rule
|
|
59
|
-
// (entry.name.startsWith(".")) keeps it out of the walk.
|
|
60
|
-
const root = makeTree({
|
|
61
|
-
"lib/router.dart": GO_ROUTE("/home"),
|
|
62
|
-
".cache/hidden.dart": GO_ROUTE("/secret"),
|
|
63
|
-
});
|
|
64
|
-
expect(extractDartRoutes(root).map((r) => r.path)).toEqual(["/home"]);
|
|
65
|
-
});
|
|
66
|
-
it("skips SKIP_DIRS entries (build, ios)", () => {
|
|
67
|
-
const root = makeTree({
|
|
68
|
-
"lib/router.dart": GO_ROUTE("/home"),
|
|
69
|
-
"build/generated.dart": GO_ROUTE("/built"),
|
|
70
|
-
"ios/Runner.dart": GO_ROUTE("/ios"),
|
|
71
|
-
});
|
|
72
|
-
expect(extractDartRoutes(root).map((r) => r.path)).toEqual(["/home"]);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
// ── sourceRouteExtractor.findRouterFiles ─────────────────────────────────────
|
|
76
|
-
describe("extractSourceRoutes — findRouterFiles traversal", () => {
|
|
77
|
-
const APP = (p) => `
|
|
78
|
-
import { Routes, Route } from 'react-router-dom';
|
|
79
|
-
export default function App() {
|
|
80
|
-
return (<Routes><Route path="${p}" element={<X />} /></Routes>);
|
|
81
|
-
}
|
|
82
|
-
`;
|
|
83
|
-
it("skips router files inside node_modules and dotfile directories", () => {
|
|
84
|
-
const root = makeTree({
|
|
85
|
-
"src/App.tsx": APP("/ok"),
|
|
86
|
-
"node_modules/pkg/App.tsx": APP("/dep"),
|
|
87
|
-
".backup/App.tsx": APP("/bak"),
|
|
88
|
-
});
|
|
89
|
-
expect(extractSourceRoutes(root).map((r) => r.path)).toEqual(["/ok"]);
|
|
90
|
-
});
|
|
91
|
-
const DEFINE_MODULE = `
|
|
92
|
-
import { defineModule } from '@directus/extensions';
|
|
93
|
-
import Coll from './routes/collection.vue';
|
|
94
|
-
export default defineModule({
|
|
95
|
-
id: 'notes',
|
|
96
|
-
routes: [{ name: 'notes', path: '', component: Coll }],
|
|
97
|
-
});
|
|
98
|
-
`;
|
|
99
|
-
it("treats an index.* file as a router candidate ONLY under a modules/ segment", () => {
|
|
100
|
-
const underModules = makeTree({
|
|
101
|
-
"src/modules/notes/index.ts": DEFINE_MODULE,
|
|
102
|
-
});
|
|
103
|
-
expect(extractSourceRoutes(underModules).map((r) => r.path)).toEqual([
|
|
104
|
-
"/notes",
|
|
105
|
-
]);
|
|
106
|
-
// Same defineModule file, but not under a `modules/` segment: findRouterFiles
|
|
107
|
-
// must not pick `index.ts` as a candidate, so no routes are extracted.
|
|
108
|
-
const notUnderModules = makeTree({
|
|
109
|
-
"src/features/notes/index.ts": DEFINE_MODULE,
|
|
110
|
-
});
|
|
111
|
-
expect(extractSourceRoutes(notUnderModules)).toEqual([]);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
// ── trace-parser.scanDir (via discoverTraceFiles / discoverPlaywrightZips) ───
|
|
115
|
-
describe("discoverTraceFiles / discoverPlaywrightZips — scanDir traversal", () => {
|
|
116
|
-
it("skips SKIP_DIRS while scanning an artifact directory", () => {
|
|
117
|
-
const root = makeTree({
|
|
118
|
-
"tests/trace.json": "{}",
|
|
119
|
-
"tests/node_modules/dep/trace.json": "{}",
|
|
120
|
-
});
|
|
121
|
-
expect(relSorted(root, discoverTraceFiles(root))).toEqual([
|
|
122
|
-
"tests/trace.json",
|
|
123
|
-
]);
|
|
124
|
-
});
|
|
125
|
-
it("finds trace files nested several levels deep inside an artifact dir", () => {
|
|
126
|
-
const root = makeTree({
|
|
127
|
-
".skyramp/a/b/c/playwright_trace.json": "{}",
|
|
128
|
-
});
|
|
129
|
-
expect(relSorted(root, discoverTraceFiles(root))).toEqual([
|
|
130
|
-
".skyramp/a/b/c/playwright_trace.json",
|
|
131
|
-
]);
|
|
132
|
-
});
|
|
133
|
-
it("does not descend into non-artifact dirs beyond the root (depth scoping)", () => {
|
|
134
|
-
const root = makeTree({
|
|
135
|
-
"src/components/trace.json": "{}", // src is not an artifact dir → depth 0 only
|
|
136
|
-
});
|
|
137
|
-
expect(discoverTraceFiles(root)).toEqual([]);
|
|
138
|
-
});
|
|
139
|
-
it("discovers playwright zips only within artifact dirs", () => {
|
|
140
|
-
const root = makeTree({
|
|
141
|
-
"e2e/run_trace.zip": "zip",
|
|
142
|
-
"frontend/public/traces/demo.playwright.zip": "zip",
|
|
143
|
-
});
|
|
144
|
-
expect(relSorted(root, discoverPlaywrightZips(root))).toEqual([
|
|
145
|
-
"e2e/run_trace.zip",
|
|
146
|
-
]);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
// ── frontendIntegration.manualWalkGrep (non-git fallback) ────────────────────
|
|
150
|
-
describe("checkFrontendFileIntegration — manualWalkGrep traversal (non-git)", () => {
|
|
151
|
-
it("finds an importer in a normal directory (real content grep)", () => {
|
|
152
|
-
const repo = makeTree({
|
|
153
|
-
"src/components/Foo.tsx": `export function Foo() { return null; }\n`,
|
|
154
|
-
"src/components/Bar.tsx": `import { Foo } from './Foo';\nexport function Bar() { return Foo(); }\n`,
|
|
155
|
-
});
|
|
156
|
-
const [result] = checkFrontendFileIntegration(repo, [
|
|
157
|
-
"src/components/Foo.tsx",
|
|
158
|
-
]);
|
|
159
|
-
expect(result.integrated).toBe(true);
|
|
160
|
-
expect(result.importers).toEqual(["src/components/Bar.tsx"]);
|
|
161
|
-
});
|
|
162
|
-
it("does not count importers inside EXCLUDED_DIR_PATTERN dirs (node_modules)", () => {
|
|
163
|
-
// Only importer lives under node_modules — the walk must skip that dir, so
|
|
164
|
-
// the component reads as unintegrated.
|
|
165
|
-
const repo = makeTree({
|
|
166
|
-
"src/components/Foo.tsx": `export function Foo() { return null; }\n`,
|
|
167
|
-
"node_modules/pkg/Consumer.tsx": `import { Foo } from '../../src/components/Foo';\n`,
|
|
168
|
-
});
|
|
169
|
-
const [result] = checkFrontendFileIntegration(repo, [
|
|
170
|
-
"src/components/Foo.tsx",
|
|
171
|
-
]);
|
|
172
|
-
expect(result.integrated).toBe(false);
|
|
173
|
-
expect(result.reason).toBe("no-importers");
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
// ── TestExecutionService.collectVideoPath ────────────────────────────────────
|
|
177
|
-
describe("collectVideoPath — first-match recursive walk", () => {
|
|
178
|
-
it("returns undefined for an empty/missing directory", () => {
|
|
179
|
-
const root = makeTree({ "other.txt": "" });
|
|
180
|
-
expect(collectVideoPath(root)).toBeUndefined();
|
|
181
|
-
expect(collectVideoPath("")).toBeUndefined();
|
|
182
|
-
});
|
|
183
|
-
it("finds video.webm nested several levels deep", () => {
|
|
184
|
-
const root = makeTree({ "a/b/c/video.webm": "data" });
|
|
185
|
-
const found = collectVideoPath(root);
|
|
186
|
-
expect(found).toBe(path.join(root, "a", "b", "c", "video.webm"));
|
|
187
|
-
});
|
|
188
|
-
it("returns a single video.webm path when several exist (first match wins)", () => {
|
|
189
|
-
const root = makeTree({
|
|
190
|
-
"x/video.webm": "1",
|
|
191
|
-
"y/video.webm": "2",
|
|
192
|
-
});
|
|
193
|
-
const found = collectVideoPath(root);
|
|
194
|
-
expect(found).toBeDefined();
|
|
195
|
-
expect(path.basename(found ?? "")).toBe("video.webm");
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
// ── TestExecutionService.findExcludedPaths ───────────────────────────────────
|
|
199
|
-
describe("findExcludedPaths — name-list recursive walk", () => {
|
|
200
|
-
it("collects every matching file recursively, as absolute paths", () => {
|
|
201
|
-
const root = makeTree({
|
|
202
|
-
"package.json": "{}",
|
|
203
|
-
"sub/package.json": "{}",
|
|
204
|
-
"sub/deep/package.json": "{}",
|
|
205
|
-
"sub/other.json": "{}",
|
|
206
|
-
});
|
|
207
|
-
const out = findExcludedPaths(root, ["package.json"]);
|
|
208
|
-
expect(relSorted(root, out)).toEqual([
|
|
209
|
-
"package.json",
|
|
210
|
-
"sub/deep/package.json",
|
|
211
|
-
"sub/package.json",
|
|
212
|
-
]);
|
|
213
|
-
});
|
|
214
|
-
it("does not descend into EXCLUDED_MOUNT_ITEMS directories (node_modules)", () => {
|
|
215
|
-
const root = makeTree({
|
|
216
|
-
"package.json": "{}",
|
|
217
|
-
"node_modules/pkg/package.json": "{}",
|
|
218
|
-
});
|
|
219
|
-
const out = findExcludedPaths(root, ["package.json"]);
|
|
220
|
-
expect(relSorted(root, out)).toEqual(["package.json"]);
|
|
221
|
-
});
|
|
222
|
-
it("does not descend into directories whose name is itself excluded", () => {
|
|
223
|
-
// A directory named like an excluded item is skipped for recursion, so a
|
|
224
|
-
// matching file *inside* it is never collected — matching the pre-refactor
|
|
225
|
-
// shouldSkipDir. `keep/config.json` (a real match) is still found.
|
|
226
|
-
const root = makeTree({
|
|
227
|
-
"keep/config.json": "{}",
|
|
228
|
-
"config.json/config.json": "{}", // parent dir excluded → inner file skipped
|
|
229
|
-
});
|
|
230
|
-
const out = findExcludedPaths(root, ["config.json"]);
|
|
231
|
-
expect(relSorted(root, out)).toEqual(["keep/config.json"]);
|
|
232
|
-
});
|
|
233
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck - Jest ESM mock type inference issues
|
|
2
|
-
import { jest } from "@jest/globals";
|
|
3
|
-
const REPO = "/some/repo";
|
|
4
|
-
const twoServiceConfig = {
|
|
5
|
-
services: [
|
|
6
|
-
{
|
|
7
|
-
serviceName: "backend",
|
|
8
|
-
language: "python",
|
|
9
|
-
testDirectory: "backend/tests",
|
|
10
|
-
api: { baseUrl: "http://localhost:8000" },
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
serviceName: "frontend",
|
|
14
|
-
language: "typescript",
|
|
15
|
-
testDirectory: "frontend/tests",
|
|
16
|
-
api: { baseUrl: "http://localhost:5173" },
|
|
17
|
-
},
|
|
18
|
-
],
|
|
19
|
-
};
|
|
20
|
-
jest.unstable_mockModule("../workspace/workspace.js", () => ({
|
|
21
|
-
WorkspaceConfigManager: jest.fn().mockImplementation(() => ({
|
|
22
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
23
|
-
read: jest.fn().mockResolvedValue(twoServiceConfig),
|
|
24
|
-
})),
|
|
25
|
-
}));
|
|
26
|
-
const { getWorkspaceBaseUrl } = await import("./workspaceAuth.js");
|
|
27
|
-
describe("getWorkspaceBaseUrl", () => {
|
|
28
|
-
it("should return no match when testFile is not provided", async () => {
|
|
29
|
-
const result = await getWorkspaceBaseUrl(REPO);
|
|
30
|
-
expect(result.baseUrl).toBeUndefined();
|
|
31
|
-
expect(result.candidates).toHaveLength(0);
|
|
32
|
-
});
|
|
33
|
-
it("should match backend service by testDirectory prefix", async () => {
|
|
34
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/backend/tests/test_api.py`);
|
|
35
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
36
|
-
expect(result.candidates).toHaveLength(0);
|
|
37
|
-
});
|
|
38
|
-
it("should match frontend service by testDirectory prefix", async () => {
|
|
39
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/frontend/tests/auth.spec.ts`);
|
|
40
|
-
expect(result.baseUrl).toBe("http://localhost:5173");
|
|
41
|
-
expect(result.candidates).toHaveLength(0);
|
|
42
|
-
});
|
|
43
|
-
it("should return no match when testFile does not match any service testDirectory", async () => {
|
|
44
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/other/tests/test_something.py`);
|
|
45
|
-
expect(result.baseUrl).toBeUndefined();
|
|
46
|
-
expect(result.candidates).toHaveLength(0);
|
|
47
|
-
});
|
|
48
|
-
it("should strip pathname from baseUrl (scheme+host+port only)", async () => {
|
|
49
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
50
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
51
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
52
|
-
read: jest.fn().mockResolvedValue({
|
|
53
|
-
services: [
|
|
54
|
-
{
|
|
55
|
-
serviceName: "api",
|
|
56
|
-
testDirectory: "tests",
|
|
57
|
-
api: { baseUrl: "http://localhost:8000/api/v2" },
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
}),
|
|
61
|
-
}));
|
|
62
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/tests/test_api.py`);
|
|
63
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
64
|
-
expect(result.candidates).toHaveLength(0);
|
|
65
|
-
});
|
|
66
|
-
it("should return no match when workspace does not exist", async () => {
|
|
67
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
68
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
69
|
-
exists: jest.fn().mockResolvedValue(false),
|
|
70
|
-
read: jest.fn(),
|
|
71
|
-
}));
|
|
72
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/tests/test_api.py`);
|
|
73
|
-
expect(result.baseUrl).toBeUndefined();
|
|
74
|
-
expect(result.candidates).toHaveLength(0);
|
|
75
|
-
});
|
|
76
|
-
it("should disambiguate by language when multiple services share the same testDirectory", async () => {
|
|
77
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
78
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
79
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
80
|
-
read: jest.fn().mockResolvedValue({
|
|
81
|
-
services: [
|
|
82
|
-
{
|
|
83
|
-
serviceName: "svc-python",
|
|
84
|
-
language: "python",
|
|
85
|
-
testDirectory: "shared/tests",
|
|
86
|
-
api: { baseUrl: "http://localhost:8000" },
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
serviceName: "svc-ts",
|
|
90
|
-
language: "typescript",
|
|
91
|
-
testDirectory: "shared/tests",
|
|
92
|
-
api: { baseUrl: "http://localhost:9000" },
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
}),
|
|
96
|
-
}));
|
|
97
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/shared/tests/test_api.py`, "python");
|
|
98
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
99
|
-
expect(result.candidates).toHaveLength(0);
|
|
100
|
-
});
|
|
101
|
-
it("should return candidates when testDirectory and language are both shared across services", async () => {
|
|
102
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
103
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
104
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
105
|
-
read: jest.fn().mockResolvedValue({
|
|
106
|
-
services: [
|
|
107
|
-
{
|
|
108
|
-
serviceName: "svc-a",
|
|
109
|
-
language: "python",
|
|
110
|
-
testDirectory: "shared/tests",
|
|
111
|
-
api: { baseUrl: "http://localhost:8000" },
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
serviceName: "svc-b",
|
|
115
|
-
language: "python",
|
|
116
|
-
testDirectory: "shared/tests",
|
|
117
|
-
api: { baseUrl: "http://localhost:9000" },
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
}),
|
|
121
|
-
}));
|
|
122
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/shared/tests/test_api.py`, "python");
|
|
123
|
-
expect(result.baseUrl).toBeUndefined();
|
|
124
|
-
expect(result.candidates).toHaveLength(2);
|
|
125
|
-
expect(result.candidates.map((c) => c.serviceName)).toEqual(["svc-a", "svc-b"]);
|
|
126
|
-
expect(result.candidates.map((c) => c.baseUrl)).toEqual([
|
|
127
|
-
"http://localhost:8000",
|
|
128
|
-
"http://localhost:9000",
|
|
129
|
-
]);
|
|
130
|
-
});
|
|
131
|
-
it("should match service using testDirectory as the workspace field for test file lookup", async () => {
|
|
132
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
133
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
134
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
135
|
-
read: jest.fn().mockResolvedValue({
|
|
136
|
-
services: [
|
|
137
|
-
{
|
|
138
|
-
serviceName: "api",
|
|
139
|
-
testDirectory: "tests",
|
|
140
|
-
api: { baseUrl: "http://localhost:9000" },
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
}),
|
|
144
|
-
}));
|
|
145
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/tests/test_api.py`);
|
|
146
|
-
expect(result.baseUrl).toBe("http://localhost:9000");
|
|
147
|
-
expect(result.candidates).toHaveLength(0);
|
|
148
|
-
});
|
|
149
|
-
it("should return dockerNetwork when matched service has runtimeDetails.dockerNetwork", async () => {
|
|
150
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
151
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
152
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
153
|
-
read: jest.fn().mockResolvedValue({
|
|
154
|
-
services: [
|
|
155
|
-
{
|
|
156
|
-
serviceName: "backend",
|
|
157
|
-
testDirectory: "tests",
|
|
158
|
-
api: { baseUrl: "http://localhost:8000" },
|
|
159
|
-
runtimeDetails: { dockerNetwork: "myapp_default" },
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
}),
|
|
163
|
-
}));
|
|
164
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/tests/test_api.py`);
|
|
165
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
166
|
-
expect(result.dockerNetwork).toBe("myapp_default");
|
|
167
|
-
});
|
|
168
|
-
it("should return undefined dockerNetwork when service has no runtimeDetails", async () => {
|
|
169
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/backend/tests/test_api.py`);
|
|
170
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
171
|
-
expect(result.dockerNetwork).toBeUndefined();
|
|
172
|
-
});
|
|
173
|
-
it("should return undefined dockerNetwork when ambiguous", async () => {
|
|
174
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
175
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
176
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
177
|
-
read: jest.fn().mockResolvedValue({
|
|
178
|
-
services: [
|
|
179
|
-
{
|
|
180
|
-
serviceName: "svc-a",
|
|
181
|
-
language: "python",
|
|
182
|
-
testDirectory: "shared/tests",
|
|
183
|
-
api: { baseUrl: "http://localhost:8000" },
|
|
184
|
-
runtimeDetails: { dockerNetwork: "net-a" },
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
serviceName: "svc-b",
|
|
188
|
-
language: "python",
|
|
189
|
-
testDirectory: "shared/tests",
|
|
190
|
-
api: { baseUrl: "http://localhost:9000" },
|
|
191
|
-
runtimeDetails: { dockerNetwork: "net-b" },
|
|
192
|
-
},
|
|
193
|
-
],
|
|
194
|
-
}),
|
|
195
|
-
}));
|
|
196
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/shared/tests/test_api.py`, "python");
|
|
197
|
-
expect(result.baseUrl).toBeUndefined();
|
|
198
|
-
expect(result.dockerNetwork).toBeUndefined();
|
|
199
|
-
expect(result.candidates).toHaveLength(2);
|
|
200
|
-
});
|
|
201
|
-
it("should return no match when matched service baseUrl is not a valid URL", async () => {
|
|
202
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
203
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
204
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
205
|
-
read: jest.fn().mockResolvedValue({
|
|
206
|
-
services: [{ api: { baseUrl: "not-a-valid-url" }, testDirectory: "tests" }],
|
|
207
|
-
}),
|
|
208
|
-
}));
|
|
209
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/tests/test_api.py`);
|
|
210
|
-
expect(result.baseUrl).toBeUndefined();
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
// SKYR-3819: in a cross-repo run, delivered test files live under testsRepoDir
|
|
214
|
-
// (a sibling of the SUT repo) but mirror the service's testDirectory structure.
|
|
215
|
-
// getWorkspaceBaseUrl must also match testDirectory against the test-repo root,
|
|
216
|
-
// or cross-repo executions lose SKYRAMP_TEST_BASE_URL and dockerNetwork.
|
|
217
|
-
describe("getWorkspaceBaseUrl with testRepoPath (cross-repo)", () => {
|
|
218
|
-
const TEST_REPO = "/some/test-repo";
|
|
219
|
-
it("matches a cross-repo test file against testDirectory resolved from testRepoPath", async () => {
|
|
220
|
-
const result = await getWorkspaceBaseUrl(REPO, `${TEST_REPO}/backend/tests/orders_test.py`, "python", TEST_REPO);
|
|
221
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
222
|
-
expect(result.candidates).toHaveLength(0);
|
|
223
|
-
});
|
|
224
|
-
it("returns dockerNetwork for a cross-repo match", async () => {
|
|
225
|
-
const { WorkspaceConfigManager } = await import("../workspace/workspace.js");
|
|
226
|
-
WorkspaceConfigManager.mockImplementationOnce(() => ({
|
|
227
|
-
exists: jest.fn().mockResolvedValue(true),
|
|
228
|
-
read: jest.fn().mockResolvedValue({
|
|
229
|
-
services: [
|
|
230
|
-
{
|
|
231
|
-
serviceName: "backend",
|
|
232
|
-
testDirectory: "tests",
|
|
233
|
-
api: { baseUrl: "http://localhost:8000" },
|
|
234
|
-
runtimeDetails: { dockerNetwork: "myapp_default" },
|
|
235
|
-
},
|
|
236
|
-
],
|
|
237
|
-
}),
|
|
238
|
-
}));
|
|
239
|
-
const result = await getWorkspaceBaseUrl(REPO, `${TEST_REPO}/tests/orders_test.py`, undefined, TEST_REPO);
|
|
240
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
241
|
-
expect(result.dockerNetwork).toBe("myapp_default");
|
|
242
|
-
});
|
|
243
|
-
it("still matches SUT-repo test files when testRepoPath is provided", async () => {
|
|
244
|
-
const result = await getWorkspaceBaseUrl(REPO, `${REPO}/backend/tests/orders_test.py`, "python", TEST_REPO);
|
|
245
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
246
|
-
});
|
|
247
|
-
it("does not match a cross-repo file that is outside every testDirectory", async () => {
|
|
248
|
-
const result = await getWorkspaceBaseUrl(REPO, `${TEST_REPO}/unrelated/orders_test.py`, "python", TEST_REPO);
|
|
249
|
-
expect(result.baseUrl).toBeUndefined();
|
|
250
|
-
expect(result.candidates).toHaveLength(0);
|
|
251
|
-
});
|
|
252
|
-
it("does not match a cross-repo file without testRepoPath (pre-existing behavior)", async () => {
|
|
253
|
-
const result = await getWorkspaceBaseUrl(REPO, `${TEST_REPO}/backend/tests/orders_test.py`, "python");
|
|
254
|
-
expect(result.baseUrl).toBeUndefined();
|
|
255
|
-
});
|
|
256
|
-
it("normalizes '..' segments in an absolute testFile before prefix matching", async () => {
|
|
257
|
-
const result = await getWorkspaceBaseUrl(REPO, `${TEST_REPO}/somewhere/../backend/tests/orders_test.py`, "python", TEST_REPO);
|
|
258
|
-
expect(result.baseUrl).toBe("http://localhost:8000");
|
|
259
|
-
});
|
|
260
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { resolveSuites } from "./testSuites.js";
|
|
2
|
-
const svc = (over) => ({ serviceName: "s", ...over });
|
|
3
|
-
describe("resolveSuites", () => {
|
|
4
|
-
it("returns each entry of runtimeDetails.testSuites, framework falling back to the service", () => {
|
|
5
|
-
const out = resolveSuites(svc({
|
|
6
|
-
framework: "playwright",
|
|
7
|
-
runtimeDetails: {
|
|
8
|
-
runtime: "local",
|
|
9
|
-
testSuites: [
|
|
10
|
-
{ testRunCommand: "pw test" },
|
|
11
|
-
{ framework: "jest", testRunCommand: "jest" },
|
|
12
|
-
],
|
|
13
|
-
},
|
|
14
|
-
}));
|
|
15
|
-
expect(out).toHaveLength(2);
|
|
16
|
-
expect(out[0]).toMatchObject({ serviceName: "s", framework: "playwright", testRunCommand: "pw test" });
|
|
17
|
-
expect(out[1]).toMatchObject({ framework: "jest", testRunCommand: "jest" });
|
|
18
|
-
});
|
|
19
|
-
it("returns [] when there is no runtimeDetails or no testSuites", () => {
|
|
20
|
-
expect(resolveSuites(svc({}))).toEqual([]);
|
|
21
|
-
expect(resolveSuites(svc({ runtimeDetails: { runtime: "local" } }))).toEqual([]);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|