@skyramp/mcp 0.0.37 → 0.0.39
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/index.js +14 -0
- package/build/prompts/test-recommendation/repository-analysis-prompt.js +287 -0
- package/build/prompts/test-recommendation/test-mapping-prompt.js +266 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +125 -0
- package/build/prompts/testGenerationPrompt.js +7 -0
- package/build/services/TestGenerationService.js +0 -6
- package/build/tools/executeSkyrampTestTool.js +7 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.js +4 -3
- package/build/tools/test-recommendation/analyzeRepositoryTool.js +96 -0
- package/build/tools/test-recommendation/mapTestsTool.js +195 -0
- package/build/tools/test-recommendation/recommendTestsTool.js +131 -0
- package/build/types/RepositoryAnalysis.js +106 -0
- package/build/types/TestMapping.js +173 -0
- package/build/types/TestRecommendation.js +52 -0
- package/build/types/TestTypes.js +1 -1
- package/build/utils/scoring-engine.js +262 -0
- package/package.json +2 -2
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { TestType } from "./TestTypes.js";
|
|
3
|
+
// Re-export TestType for convenience
|
|
4
|
+
export { TestType };
|
|
5
|
+
// Base impact scores for each test type
|
|
6
|
+
export const BASE_SCORES = {
|
|
7
|
+
[TestType.E2E]: 100,
|
|
8
|
+
[TestType.UI]: 95,
|
|
9
|
+
[TestType.INTEGRATION]: 90,
|
|
10
|
+
[TestType.LOAD]: 60,
|
|
11
|
+
[TestType.FUZZ]: 50,
|
|
12
|
+
[TestType.CONTRACT]: 80,
|
|
13
|
+
[TestType.SMOKE]: 70,
|
|
14
|
+
};
|
|
15
|
+
export const CONTEXT_RULES = {
|
|
16
|
+
[TestType.E2E]: [
|
|
17
|
+
{
|
|
18
|
+
condition: "full-stack",
|
|
19
|
+
multiplier: 1.2,
|
|
20
|
+
description: "Full-stack apps benefit most from E2E tests",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
condition: "backend-only",
|
|
24
|
+
multiplier: 0.7,
|
|
25
|
+
description: "Limited E2E applicability for backend-only",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
condition: "frontend-spa",
|
|
29
|
+
multiplier: 0.9,
|
|
30
|
+
description: "Slightly reduced without backend",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
condition: "library",
|
|
34
|
+
multiplier: 0,
|
|
35
|
+
description: "Not applicable to libraries",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
[TestType.LOAD]: [
|
|
39
|
+
{
|
|
40
|
+
condition: "hasKubernetes",
|
|
41
|
+
multiplier: 1.2,
|
|
42
|
+
description: "K8s suggests high-traffic expectations",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
condition: "hasDockerCompose",
|
|
46
|
+
multiplier: 1.15,
|
|
47
|
+
description: "Scaled infrastructure indicates traffic needs",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
condition: "cli-or-library",
|
|
51
|
+
multiplier: 0.4,
|
|
52
|
+
description: "Low traffic expected",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
condition: "internal-tool",
|
|
56
|
+
multiplier: 0.4,
|
|
57
|
+
description: "Minimal load",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
[TestType.FUZZ]: [
|
|
61
|
+
{
|
|
62
|
+
condition: "handles-payments",
|
|
63
|
+
multiplier: 1.2,
|
|
64
|
+
description: "Security critical for payments",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
condition: "handles-pii",
|
|
68
|
+
multiplier: 1.2,
|
|
69
|
+
description: "Security critical for PII",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
condition: "oauth2",
|
|
73
|
+
multiplier: 1.15,
|
|
74
|
+
description: "Public API security needs",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
condition: "internal-service",
|
|
78
|
+
multiplier: 0.9,
|
|
79
|
+
description: "Lower security priority",
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
[TestType.CONTRACT]: [
|
|
83
|
+
{
|
|
84
|
+
condition: "microservices",
|
|
85
|
+
multiplier: 1.2,
|
|
86
|
+
description: "Critical for service contracts",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
condition: "multiple-services",
|
|
90
|
+
multiplier: 1.15,
|
|
91
|
+
description: "Service interactions important",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
condition: "monolith",
|
|
95
|
+
multiplier: 0.9,
|
|
96
|
+
description: "Less critical",
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
[TestType.INTEGRATION]: [
|
|
100
|
+
{
|
|
101
|
+
condition: "microservices",
|
|
102
|
+
multiplier: 1.1,
|
|
103
|
+
description: "Service communication important",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
condition: "has-unit-missing-integration",
|
|
107
|
+
multiplier: 1.2,
|
|
108
|
+
description: "Fill coverage gap",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
condition: "has-integration-tests",
|
|
112
|
+
multiplier: 0.9,
|
|
113
|
+
description: "Less urgent",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
[TestType.UI]: [
|
|
117
|
+
{
|
|
118
|
+
condition: "frontend-spa-or-fullstack",
|
|
119
|
+
multiplier: 1.2,
|
|
120
|
+
description: "Full value for UI apps",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
condition: "backend-only",
|
|
124
|
+
multiplier: 0,
|
|
125
|
+
description: "Not applicable",
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
[TestType.SMOKE]: [
|
|
129
|
+
{
|
|
130
|
+
condition: "no-existing-tests",
|
|
131
|
+
multiplier: 1.2,
|
|
132
|
+
description: "Quick wins needed",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
condition: "has-cicd",
|
|
136
|
+
multiplier: 1.1,
|
|
137
|
+
description: "Deployment validation",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
condition: "comprehensive-tests",
|
|
141
|
+
multiplier: 0.8,
|
|
142
|
+
description: "Less valuable",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
// Zod schemas for validation
|
|
147
|
+
export const testPriorityScoreSchema = z.object({
|
|
148
|
+
testType: z.nativeEnum(TestType),
|
|
149
|
+
_baseScore: z.number().min(0).max(120),
|
|
150
|
+
contextMultiplier: z.number().min(0).max(2),
|
|
151
|
+
_finalScore: z.number().min(0).max(150),
|
|
152
|
+
feasibility: z.enum(["high", "medium", "low", "not-applicable"]),
|
|
153
|
+
requiredArtifacts: z.object({
|
|
154
|
+
available: z.array(z.string()),
|
|
155
|
+
missing: z.array(z.string()),
|
|
156
|
+
}),
|
|
157
|
+
reasoning: z.string(),
|
|
158
|
+
});
|
|
159
|
+
export const testMappingResultSchema = z.object({
|
|
160
|
+
priorityScores: z.array(testPriorityScoreSchema),
|
|
161
|
+
contextFactors: z.object({
|
|
162
|
+
applied: z.array(z.object({
|
|
163
|
+
factor: z.string(),
|
|
164
|
+
impact: z.string(),
|
|
165
|
+
multiplier: z.number(),
|
|
166
|
+
})),
|
|
167
|
+
}),
|
|
168
|
+
summary: z.object({
|
|
169
|
+
highPriority: z.array(z.nativeEnum(TestType)),
|
|
170
|
+
mediumPriority: z.array(z.nativeEnum(TestType)),
|
|
171
|
+
lowPriority: z.array(z.nativeEnum(TestType)),
|
|
172
|
+
}),
|
|
173
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { TestType } from "./TestTypes.js";
|
|
3
|
+
// Test type to documentation URL mapping
|
|
4
|
+
export const TEST_TYPE_DOCS = {
|
|
5
|
+
[TestType.SMOKE]: "https://www.skyramp.dev/docs/smoke-tests",
|
|
6
|
+
[TestType.CONTRACT]: "https://www.skyramp.dev/docs/contract-tests",
|
|
7
|
+
[TestType.FUZZ]: "https://www.skyramp.dev/docs/fuzz-tests",
|
|
8
|
+
[TestType.INTEGRATION]: "https://www.skyramp.dev/docs/integration-tests",
|
|
9
|
+
[TestType.LOAD]: "https://www.skyramp.dev/docs/load-tests",
|
|
10
|
+
[TestType.E2E]: "https://www.skyramp.dev/docs/e2e-tests",
|
|
11
|
+
[TestType.UI]: "https://www.skyramp.dev/docs/ui-tests",
|
|
12
|
+
};
|
|
13
|
+
// Zod schemas for validation
|
|
14
|
+
export const specificTestSchema = z.object({
|
|
15
|
+
testName: z.string(),
|
|
16
|
+
description: z.string(),
|
|
17
|
+
targetEndpoint: z.string().optional(),
|
|
18
|
+
targetFlow: z.string().optional(),
|
|
19
|
+
// generationPrompt: z.string(),
|
|
20
|
+
requiredInputs: z.object({
|
|
21
|
+
available: z.array(z.object({
|
|
22
|
+
name: z.string(),
|
|
23
|
+
path: z.string(),
|
|
24
|
+
})),
|
|
25
|
+
missing: z.array(z.object({
|
|
26
|
+
name: z.string(),
|
|
27
|
+
guidance: z.string(),
|
|
28
|
+
})),
|
|
29
|
+
}),
|
|
30
|
+
estimatedValue: z.string(),
|
|
31
|
+
});
|
|
32
|
+
export const testTypeRecommendationSchema = z.object({
|
|
33
|
+
priority: z.enum(["high", "medium", "low"]),
|
|
34
|
+
testType: z.nativeEnum(TestType),
|
|
35
|
+
rationale: z.string(),
|
|
36
|
+
specificTests: z.array(specificTestSchema),
|
|
37
|
+
gettingStarted: z.object({
|
|
38
|
+
prerequisites: z.array(z.string()),
|
|
39
|
+
quickStartCommand: z.string().optional(),
|
|
40
|
+
documentationUrl: z.string(),
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
export const testRecommendationSchema = z.object({
|
|
44
|
+
summary: z.object({
|
|
45
|
+
totalRecommended: z.number(),
|
|
46
|
+
highPriorityCount: z.number(),
|
|
47
|
+
estimatedEffort: z.string(),
|
|
48
|
+
quickWins: z.array(z.string()),
|
|
49
|
+
}),
|
|
50
|
+
recommendations: z.array(testTypeRecommendationSchema),
|
|
51
|
+
nextSteps: z.array(z.string()),
|
|
52
|
+
});
|
package/build/types/TestTypes.js
CHANGED
|
@@ -68,7 +68,7 @@ export const baseSchema = z.object({
|
|
|
68
68
|
export const baseTraceSchema = z.object({
|
|
69
69
|
trace: z
|
|
70
70
|
.string()
|
|
71
|
-
.describe("
|
|
71
|
+
.describe("Absolute path to the trace file in JSON format (e.g., /path/to/trace.json). Must use .json extension only. Do not use .jsonl files."),
|
|
72
72
|
include: z
|
|
73
73
|
.array(z.string())
|
|
74
74
|
.default([])
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { BASE_SCORES, CONTEXT_RULES, } from "../types/TestMapping.js";
|
|
2
|
+
import { TestType } from "../types/TestTypes.js";
|
|
3
|
+
/**
|
|
4
|
+
* Scoring Engine
|
|
5
|
+
* Calculates priority scores for test types based on repository analysis
|
|
6
|
+
*/
|
|
7
|
+
export class ScoringEngine {
|
|
8
|
+
/**
|
|
9
|
+
* Calculate priority score for a specific test type
|
|
10
|
+
*/
|
|
11
|
+
static calculateTestScore(testType, analysis) {
|
|
12
|
+
const _baseScore = BASE_SCORES[testType];
|
|
13
|
+
const contextMultiplier = this.calculateContextMultiplier(testType, analysis);
|
|
14
|
+
const _finalScore = _baseScore * contextMultiplier;
|
|
15
|
+
const feasibility = this.assessFeasibility(testType, analysis);
|
|
16
|
+
const requiredArtifacts = this.identifyRequiredArtifacts(testType, analysis);
|
|
17
|
+
const reasoning = this.generateReasoning(testType, _baseScore, contextMultiplier, _finalScore, analysis);
|
|
18
|
+
return {
|
|
19
|
+
testType,
|
|
20
|
+
_baseScore,
|
|
21
|
+
contextMultiplier,
|
|
22
|
+
_finalScore: Math.round(_finalScore * 10) / 10,
|
|
23
|
+
feasibility,
|
|
24
|
+
requiredArtifacts,
|
|
25
|
+
reasoning,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Calculate context multiplier based on repository characteristics
|
|
30
|
+
*/
|
|
31
|
+
static calculateContextMultiplier(testType, analysis) {
|
|
32
|
+
const rules = CONTEXT_RULES[testType];
|
|
33
|
+
let multiplier = 1.0;
|
|
34
|
+
for (const rule of rules) {
|
|
35
|
+
if (this.evaluateCondition(rule.condition, analysis)) {
|
|
36
|
+
multiplier = rule.multiplier;
|
|
37
|
+
break; // Use first matching rule
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return multiplier;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Evaluate a context condition against repository analysis
|
|
44
|
+
*/
|
|
45
|
+
static evaluateCondition(condition, analysis) {
|
|
46
|
+
const { projectClassification, infrastructure, existingTests, artifacts } = analysis;
|
|
47
|
+
switch (condition) {
|
|
48
|
+
// Project type conditions
|
|
49
|
+
case "full-stack":
|
|
50
|
+
return projectClassification.projectType === "full-stack";
|
|
51
|
+
case "backend-only":
|
|
52
|
+
return projectClassification.projectType === "rest-api";
|
|
53
|
+
case "frontend-spa":
|
|
54
|
+
return projectClassification.projectType === "frontend";
|
|
55
|
+
case "library":
|
|
56
|
+
return projectClassification.projectType === "library";
|
|
57
|
+
case "cli-or-library":
|
|
58
|
+
return ["library", "cli"].includes(projectClassification.projectType);
|
|
59
|
+
case "microservices":
|
|
60
|
+
return (projectClassification.projectType === "microservices" ||
|
|
61
|
+
projectClassification.deploymentPattern === "microservices");
|
|
62
|
+
case "monolith":
|
|
63
|
+
return (projectClassification.deploymentPattern === "containerized-monolith");
|
|
64
|
+
// Infrastructure conditions
|
|
65
|
+
case "hasKubernetes":
|
|
66
|
+
return infrastructure.hasKubernetes;
|
|
67
|
+
case "hasDockerCompose":
|
|
68
|
+
return infrastructure.hasDockerCompose;
|
|
69
|
+
case "has-cicd":
|
|
70
|
+
return infrastructure.hasCiCd;
|
|
71
|
+
// Testing conditions
|
|
72
|
+
case "no-existing-tests":
|
|
73
|
+
return Object.values(existingTests.coverage).every((v) => v === 0);
|
|
74
|
+
case "has-unit-missing-integration":
|
|
75
|
+
return (existingTests.coverage.unit > 0 &&
|
|
76
|
+
existingTests.coverage.integration === 0);
|
|
77
|
+
case "has-integration-tests":
|
|
78
|
+
return existingTests.coverage.integration > 0;
|
|
79
|
+
case "comprehensive-tests":
|
|
80
|
+
return (Object.values(existingTests.coverage).reduce((a, b) => a + b, 0) > 20);
|
|
81
|
+
// Artifact conditions
|
|
82
|
+
case "frontend-spa-or-fullstack":
|
|
83
|
+
return ["frontend", "full-stack"].includes(projectClassification.projectType);
|
|
84
|
+
case "multiple-services":
|
|
85
|
+
return projectClassification.deploymentPattern === "microservices";
|
|
86
|
+
// Security conditions (inferred)
|
|
87
|
+
case "handles-payments":
|
|
88
|
+
return (analysis.businessContext.mainPurpose
|
|
89
|
+
.toLowerCase()
|
|
90
|
+
.includes("payment") ||
|
|
91
|
+
analysis.businessContext.mainPurpose
|
|
92
|
+
.toLowerCase()
|
|
93
|
+
.includes("commerce"));
|
|
94
|
+
case "handles-pii":
|
|
95
|
+
return (analysis.businessContext.mainPurpose.toLowerCase().includes("user") ||
|
|
96
|
+
analysis.businessContext.mainPurpose.toLowerCase().includes("profile"));
|
|
97
|
+
case "oauth2":
|
|
98
|
+
return analysis.authentication.method === "oauth2";
|
|
99
|
+
case "internal-service":
|
|
100
|
+
case "internal-tool":
|
|
101
|
+
return analysis.businessContext.mainPurpose
|
|
102
|
+
.toLowerCase()
|
|
103
|
+
.includes("internal");
|
|
104
|
+
default:
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Assess feasibility of generating a test type
|
|
110
|
+
*/
|
|
111
|
+
static assessFeasibility(testType, analysis) {
|
|
112
|
+
const { artifacts, projectClassification } = analysis;
|
|
113
|
+
// Check for N/A cases first
|
|
114
|
+
if (testType === TestType.UI &&
|
|
115
|
+
projectClassification.projectType === "rest-api") {
|
|
116
|
+
return "not-applicable";
|
|
117
|
+
}
|
|
118
|
+
if (testType === TestType.E2E &&
|
|
119
|
+
projectClassification.projectType === "library") {
|
|
120
|
+
return "not-applicable";
|
|
121
|
+
}
|
|
122
|
+
// Check artifact requirements
|
|
123
|
+
const requiredArtifacts = this.identifyRequiredArtifacts(testType, analysis);
|
|
124
|
+
const missingCount = requiredArtifacts.missing.length;
|
|
125
|
+
if (missingCount === 0) {
|
|
126
|
+
return "high";
|
|
127
|
+
}
|
|
128
|
+
else if (missingCount === 1) {
|
|
129
|
+
return "medium";
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
return "low";
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Identify required artifacts and their availability
|
|
137
|
+
*/
|
|
138
|
+
static identifyRequiredArtifacts(testType, analysis) {
|
|
139
|
+
const available = [];
|
|
140
|
+
const missing = [];
|
|
141
|
+
const { artifacts } = analysis;
|
|
142
|
+
// Check OpenAPI spec
|
|
143
|
+
if (artifacts.openApiSpecs.length > 0) {
|
|
144
|
+
available.push("openApiSpec");
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
if ([
|
|
148
|
+
TestType.SMOKE,
|
|
149
|
+
TestType.CONTRACT,
|
|
150
|
+
TestType.FUZZ,
|
|
151
|
+
TestType.INTEGRATION,
|
|
152
|
+
TestType.LOAD,
|
|
153
|
+
].includes(testType)) {
|
|
154
|
+
missing.push("openApiSpec");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Check Playwright recordings
|
|
158
|
+
if (artifacts.playwrightRecordings.length > 0) {
|
|
159
|
+
available.push("playwrightRecording");
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
if ([TestType.UI, TestType.E2E].includes(testType)) {
|
|
163
|
+
missing.push("playwrightRecording");
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Check trace files
|
|
167
|
+
if (artifacts.traceFiles.length > 0) {
|
|
168
|
+
available.push("traceFile");
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
if ([TestType.E2E, TestType.INTEGRATION].includes(testType)) {
|
|
172
|
+
// Trace files are helpful but not required if OpenAPI is available
|
|
173
|
+
if (artifacts.openApiSpecs.length === 0) {
|
|
174
|
+
missing.push("traceFile");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return { available, missing };
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Generate reasoning explanation for the score
|
|
182
|
+
*/
|
|
183
|
+
static generateReasoning(testType, _baseScore, multiplier, _finalScore, analysis) {
|
|
184
|
+
const { projectClassification, existingTests, artifacts, infrastructure } = analysis;
|
|
185
|
+
let reasoning = "";
|
|
186
|
+
// Base reasoning by test type
|
|
187
|
+
switch (testType) {
|
|
188
|
+
case TestType.INTEGRATION:
|
|
189
|
+
if (existingTests.coverage.integration === 0) {
|
|
190
|
+
reasoning = `No integration tests exist for ${analysis.apiEndpoints.totalCount} endpoints. `;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
reasoning = `${existingTests.coverage.integration} integration tests exist. `;
|
|
194
|
+
}
|
|
195
|
+
if (projectClassification.deploymentPattern === "microservices") {
|
|
196
|
+
reasoning +=
|
|
197
|
+
"Microservices architecture makes integration testing critical. ";
|
|
198
|
+
}
|
|
199
|
+
break;
|
|
200
|
+
case TestType.E2E:
|
|
201
|
+
if (projectClassification.projectType === "full-stack") {
|
|
202
|
+
reasoning =
|
|
203
|
+
"Full-stack application - E2E tests validate complete user journeys. ";
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
reasoning =
|
|
207
|
+
"E2E tests have limited applicability for this project type. ";
|
|
208
|
+
}
|
|
209
|
+
break;
|
|
210
|
+
case TestType.UI:
|
|
211
|
+
if (["frontend", "full-stack"].includes(projectClassification.projectType)) {
|
|
212
|
+
reasoning = "UI testing essential for frontend validation. ";
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
reasoning = "No UI components detected. ";
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
case TestType.SMOKE:
|
|
219
|
+
if (Object.values(existingTests.coverage).every((v) => v === 0)) {
|
|
220
|
+
reasoning = "No existing tests - smoke tests provide quick wins. ";
|
|
221
|
+
}
|
|
222
|
+
if (infrastructure.hasCiCd) {
|
|
223
|
+
reasoning += "CI/CD pipeline benefits from smoke test validation. ";
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
case TestType.LOAD:
|
|
227
|
+
if (infrastructure.hasKubernetes) {
|
|
228
|
+
reasoning =
|
|
229
|
+
"Kubernetes deployment suggests high-traffic expectations. ";
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
reasoning = "Load testing validates performance and scalability. ";
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
case TestType.FUZZ:
|
|
236
|
+
if (analysis.authentication.method !== "none") {
|
|
237
|
+
reasoning =
|
|
238
|
+
"API handles authentication - security testing important. ";
|
|
239
|
+
}
|
|
240
|
+
reasoning += "Fuzz testing discovers input validation issues. ";
|
|
241
|
+
break;
|
|
242
|
+
case TestType.CONTRACT:
|
|
243
|
+
if (artifacts.openApiSpecs.length > 0) {
|
|
244
|
+
reasoning =
|
|
245
|
+
"OpenAPI spec available - contract validation straightforward. ";
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
reasoning = "No OpenAPI spec - contract tests harder to generate. ";
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
// Add artifact status
|
|
253
|
+
const requiredArtifacts = this.identifyRequiredArtifacts(testType, analysis);
|
|
254
|
+
if (requiredArtifacts.missing.length > 0) {
|
|
255
|
+
reasoning += `Missing: ${requiredArtifacts.missing.join(", ")}. `;
|
|
256
|
+
}
|
|
257
|
+
else if (requiredArtifacts.available.length > 0) {
|
|
258
|
+
reasoning += `All required artifacts available. `;
|
|
259
|
+
}
|
|
260
|
+
return reasoning.trim();
|
|
261
|
+
}
|
|
262
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyramp/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.39",
|
|
4
4
|
"main": "build/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.11.4",
|
|
45
|
-
"@skyramp/skyramp": "^1.2.
|
|
45
|
+
"@skyramp/skyramp": "^1.2.29",
|
|
46
46
|
"@playwright/test": "^1.55.0",
|
|
47
47
|
"dockerode": "^4.0.6",
|
|
48
48
|
"zod": "^3.25.3"
|