@testchimp/cli 0.1.7 → 0.1.9
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/dist/cli/program.d.ts +1 -1
- package/dist/cli/program.js +80 -1
- package/dist/core/schemas.d.ts +15 -0
- package/dist/core/schemas.js +19 -0
- package/dist/core/tools.js +50 -0
- package/dist/mcp/server.js +1 -1
- package/package.json +1 -1
package/dist/cli/program.d.ts
CHANGED
package/dist/cli/program.js
CHANGED
|
@@ -5,7 +5,26 @@ import { DEFAULT_BACKEND, postMcp } from "../core/client.js";
|
|
|
5
5
|
import { deepMerge } from "../core/merge.js";
|
|
6
6
|
import { runTool } from "../core/tools.js";
|
|
7
7
|
import { TOOL_DEFINITIONS } from "../core/tools.js";
|
|
8
|
-
export const PACKAGE_VERSION = "0.1.
|
|
8
|
+
export const PACKAGE_VERSION = "0.1.7";
|
|
9
|
+
function parseRecordTypesCsv(raw) {
|
|
10
|
+
return String(raw)
|
|
11
|
+
.split(",")
|
|
12
|
+
.map((s) => s.trim())
|
|
13
|
+
.filter(Boolean)
|
|
14
|
+
.map((s) => s.toLowerCase())
|
|
15
|
+
.map((s) => {
|
|
16
|
+
if (s === "automated")
|
|
17
|
+
return "smart_test";
|
|
18
|
+
if (s === "smarttest")
|
|
19
|
+
return "smart_test";
|
|
20
|
+
if (s === "smart_test")
|
|
21
|
+
return "smart_test";
|
|
22
|
+
if (s === "manual")
|
|
23
|
+
return "manual";
|
|
24
|
+
return s;
|
|
25
|
+
})
|
|
26
|
+
.filter((v) => v === "smart_test" || v === "manual");
|
|
27
|
+
}
|
|
9
28
|
function parseJsonInput(raw) {
|
|
10
29
|
if (raw == null || raw.trim() === "")
|
|
11
30
|
return {};
|
|
@@ -47,6 +66,9 @@ export function buildCliProgram() {
|
|
|
47
66
|
.option("--environment <s>")
|
|
48
67
|
.option("--branch-name <s>")
|
|
49
68
|
.option("--platform <web|ios|android>")
|
|
69
|
+
.option("--record-types <csv>", "coverage sources: smart_test,manual (aliases: automated,smarttest)")
|
|
70
|
+
.option("--include-manual", "include manual sessions in addition to automated (default)")
|
|
71
|
+
.option("--manual-only", "manual-only coverage (no automated)")
|
|
50
72
|
.option("--file-paths <csv>", "comma-separated paths under platform tests root")
|
|
51
73
|
.option("--folder-path <path>", "folder under tests root, slash-separated")
|
|
52
74
|
.action(async (opts) => {
|
|
@@ -59,6 +81,15 @@ export function buildCliProgram() {
|
|
|
59
81
|
body.branchName = opts.branchName;
|
|
60
82
|
if (opts.platform)
|
|
61
83
|
body.platform = opts.platform;
|
|
84
|
+
let recordTypes;
|
|
85
|
+
if (opts.recordTypes)
|
|
86
|
+
recordTypes = parseRecordTypesCsv(String(opts.recordTypes));
|
|
87
|
+
if (opts.includeManual)
|
|
88
|
+
recordTypes = Array.from(new Set([...(recordTypes ?? ["smart_test"]), "manual"]));
|
|
89
|
+
if (opts.manualOnly)
|
|
90
|
+
recordTypes = ["manual"];
|
|
91
|
+
if (recordTypes && recordTypes.length > 0)
|
|
92
|
+
body.recordTypes = recordTypes;
|
|
62
93
|
const scope = {};
|
|
63
94
|
if (opts.filePaths)
|
|
64
95
|
scope.filePaths = String(opts.filePaths).split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -166,6 +197,54 @@ export function buildCliProgram() {
|
|
|
166
197
|
const out = await runTool("update-user-story", merged, { postMcp });
|
|
167
198
|
console.log(out);
|
|
168
199
|
});
|
|
200
|
+
program
|
|
201
|
+
.command("get-user-stories")
|
|
202
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-user-stories").description)
|
|
203
|
+
.addOption(jsonInputOption())
|
|
204
|
+
.option("--user-story-ordinal-ids <csv>", "comma-separated US-<n> numeric ids")
|
|
205
|
+
.action(async (opts) => {
|
|
206
|
+
const body = {};
|
|
207
|
+
if (opts.userStoryOrdinalIds) {
|
|
208
|
+
body.userStoryOrdinalIds = String(opts.userStoryOrdinalIds)
|
|
209
|
+
.split(",")
|
|
210
|
+
.map((s) => Number(s.trim()))
|
|
211
|
+
.filter((n) => Number.isFinite(n) && n > 0);
|
|
212
|
+
}
|
|
213
|
+
const merged = mergeBodies(body, opts.jsonInput);
|
|
214
|
+
const out = await runTool("get-user-stories", merged, { postMcp });
|
|
215
|
+
console.log(out);
|
|
216
|
+
});
|
|
217
|
+
program
|
|
218
|
+
.command("get-test-scenarios")
|
|
219
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-test-scenarios").description)
|
|
220
|
+
.addOption(jsonInputOption())
|
|
221
|
+
.option("--scenario-ordinal-ids <csv>", "comma-separated TS-<n> numeric ids")
|
|
222
|
+
.action(async (opts) => {
|
|
223
|
+
const body = {};
|
|
224
|
+
if (opts.scenarioOrdinalIds) {
|
|
225
|
+
body.scenarioOrdinalIds = String(opts.scenarioOrdinalIds)
|
|
226
|
+
.split(",")
|
|
227
|
+
.map((s) => Number(s.trim()))
|
|
228
|
+
.filter((n) => Number.isFinite(n) && n > 0);
|
|
229
|
+
}
|
|
230
|
+
const merged = mergeBodies(body, opts.jsonInput);
|
|
231
|
+
const out = await runTool("get-test-scenarios", merged, { postMcp });
|
|
232
|
+
console.log(out);
|
|
233
|
+
});
|
|
234
|
+
program
|
|
235
|
+
.command("get-manual-session-details")
|
|
236
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-manual-session-details").description)
|
|
237
|
+
.addOption(jsonInputOption())
|
|
238
|
+
.option("--manual-session-id <id>", "manual test session id (same as job id in the viewer URL)")
|
|
239
|
+
.action(async (opts) => {
|
|
240
|
+
const body = {};
|
|
241
|
+
if (opts.manualSessionId) {
|
|
242
|
+
body.manualSessionId = String(opts.manualSessionId).trim();
|
|
243
|
+
}
|
|
244
|
+
const merged = mergeBodies(body, opts.jsonInput);
|
|
245
|
+
const out = await runTool("get-manual-session-details", merged, { postMcp });
|
|
246
|
+
console.log(out);
|
|
247
|
+
});
|
|
169
248
|
program
|
|
170
249
|
.command("mark-plan-items-implementation-done")
|
|
171
250
|
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "mark-plan-items-implementation-done").description)
|
package/dist/core/schemas.d.ts
CHANGED
|
@@ -22,6 +22,12 @@ export declare const listCoverageInput: z.ZodObject<{
|
|
|
22
22
|
ios: "ios";
|
|
23
23
|
android: "android";
|
|
24
24
|
}>>;
|
|
25
|
+
recordTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
26
|
+
smart_test: "smart_test";
|
|
27
|
+
manual: "manual";
|
|
28
|
+
SMART_TEST: "SMART_TEST";
|
|
29
|
+
MANUAL: "MANUAL";
|
|
30
|
+
}>>>;
|
|
25
31
|
}, z.core.$strip>;
|
|
26
32
|
export declare const listExecutionInput: z.ZodObject<{
|
|
27
33
|
release: z.ZodOptional<z.ZodString>;
|
|
@@ -64,6 +70,15 @@ export declare const markPlanItemsImplementationDoneInput: z.ZodObject<{
|
|
|
64
70
|
scenarioOrdinalIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
|
|
65
71
|
userStoryOrdinalIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
|
|
66
72
|
}, z.core.$strip>;
|
|
73
|
+
export declare const getUserStoriesInput: z.ZodObject<{
|
|
74
|
+
userStoryOrdinalIds: z.ZodArray<z.ZodCoercedNumber<unknown>>;
|
|
75
|
+
}, z.core.$strip>;
|
|
76
|
+
export declare const getTestScenariosInput: z.ZodObject<{
|
|
77
|
+
scenarioOrdinalIds: z.ZodArray<z.ZodCoercedNumber<unknown>>;
|
|
78
|
+
}, z.core.$strip>;
|
|
79
|
+
export declare const getManualSessionDetailsInput: z.ZodObject<{
|
|
80
|
+
manualSessionId: z.ZodString;
|
|
81
|
+
}, z.core.$strip>;
|
|
67
82
|
export declare const emptyInput: z.ZodObject<{}, z.core.$strip>;
|
|
68
83
|
export declare const getBranchSpecificEndpointConfigInput: z.ZodObject<{
|
|
69
84
|
branchName: z.ZodOptional<z.ZodString>;
|
package/dist/core/schemas.js
CHANGED
|
@@ -6,6 +6,7 @@ export const scopeSchema = z
|
|
|
6
6
|
})
|
|
7
7
|
.optional();
|
|
8
8
|
const executionPlatformSchema = z.enum(["web", "ios", "android"]);
|
|
9
|
+
const requirementCoverageRecordTypeSchema = z.enum(["smart_test", "manual", "SMART_TEST", "MANUAL"]);
|
|
9
10
|
export const executionJobDimensionFilterSchema = z.object({
|
|
10
11
|
dimension: z.string().min(1),
|
|
11
12
|
values: z.array(z.string()).min(1),
|
|
@@ -18,6 +19,13 @@ export const listCoverageInput = z.object({
|
|
|
18
19
|
includeNonCoveredTestScenarios: z.boolean().optional(),
|
|
19
20
|
branchName: z.string().optional(),
|
|
20
21
|
platform: executionPlatformSchema.optional(),
|
|
22
|
+
/**
|
|
23
|
+
* Which coverage sources to include.
|
|
24
|
+
*
|
|
25
|
+
* Omit for legacy default: SMART_TEST only.
|
|
26
|
+
* When provided, send proto enum names ("SMART_TEST", "MANUAL") or CLI-friendly aliases ("smart_test", "manual").
|
|
27
|
+
*/
|
|
28
|
+
recordTypes: z.array(requirementCoverageRecordTypeSchema).optional(),
|
|
21
29
|
});
|
|
22
30
|
export const listExecutionInput = z.object({
|
|
23
31
|
release: z.string().optional(),
|
|
@@ -61,6 +69,17 @@ export const markPlanItemsImplementationDoneInput = z.object({
|
|
|
61
69
|
scenarioOrdinalIds: z.array(z.coerce.number().int().positive()).optional(),
|
|
62
70
|
userStoryOrdinalIds: z.array(z.coerce.number().int().positive()).optional(),
|
|
63
71
|
});
|
|
72
|
+
export const getUserStoriesInput = z
|
|
73
|
+
.object({
|
|
74
|
+
userStoryOrdinalIds: z.array(z.coerce.number().int().positive()).min(1),
|
|
75
|
+
});
|
|
76
|
+
export const getTestScenariosInput = z
|
|
77
|
+
.object({
|
|
78
|
+
scenarioOrdinalIds: z.array(z.coerce.number().int().positive()).min(1),
|
|
79
|
+
});
|
|
80
|
+
export const getManualSessionDetailsInput = z.object({
|
|
81
|
+
manualSessionId: z.string().min(1),
|
|
82
|
+
});
|
|
64
83
|
export const emptyInput = z.object({});
|
|
65
84
|
export const getBranchSpecificEndpointConfigInput = z.object({
|
|
66
85
|
branchName: z.string().optional(),
|
package/dist/core/tools.js
CHANGED
|
@@ -28,6 +28,17 @@ function listCoverageBody(args) {
|
|
|
28
28
|
body.branchName = args.branchName.trim();
|
|
29
29
|
if (args.platform != null)
|
|
30
30
|
body.platform = platformToProtoEnum(args.platform);
|
|
31
|
+
if (args.recordTypes != null && args.recordTypes.length > 0) {
|
|
32
|
+
const normalized = args.recordTypes.map((t) => {
|
|
33
|
+
const raw = String(t).trim();
|
|
34
|
+
if (raw === "manual")
|
|
35
|
+
return "MANUAL";
|
|
36
|
+
if (raw === "smart_test")
|
|
37
|
+
return "SMART_TEST";
|
|
38
|
+
return raw;
|
|
39
|
+
});
|
|
40
|
+
body.recordTypes = normalized;
|
|
41
|
+
}
|
|
31
42
|
return body;
|
|
32
43
|
}
|
|
33
44
|
function listExecutionBody(args) {
|
|
@@ -148,6 +159,45 @@ export const TOOL_DEFINITIONS = [
|
|
|
148
159
|
return postMcp("/api/mcp/update_test_scenario", { content: a.content });
|
|
149
160
|
},
|
|
150
161
|
},
|
|
162
|
+
{
|
|
163
|
+
kebab: "get-user-stories",
|
|
164
|
+
description: "Fetch user stories from the TestChimp platform by ordinal id (numeric part of US-<n>). " +
|
|
165
|
+
"Returns full plan markdown content, title, and platform file path for each found story. " +
|
|
166
|
+
"Use when plan files are not yet synced to the repo.",
|
|
167
|
+
inputSchema: S.getUserStoriesInput,
|
|
168
|
+
execute: async (args, { postMcp }) => {
|
|
169
|
+
const a = args;
|
|
170
|
+
return postMcp("/api/mcp/get_user_stories", {
|
|
171
|
+
userStoryOrdinalIds: a.userStoryOrdinalIds,
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
kebab: "get-test-scenarios",
|
|
177
|
+
description: "Fetch test scenarios from the TestChimp platform by ordinal id (numeric part of TS-<n>). " +
|
|
178
|
+
"Returns full plan markdown content, title, platform file path, and linked user story ordinal ids. " +
|
|
179
|
+
"Use when plan files are not yet synced to the repo.",
|
|
180
|
+
inputSchema: S.getTestScenariosInput,
|
|
181
|
+
execute: async (args, { postMcp }) => {
|
|
182
|
+
const a = args;
|
|
183
|
+
return postMcp("/api/mcp/get_test_scenarios", {
|
|
184
|
+
scenarioOrdinalIds: a.scenarioOrdinalIds,
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
kebab: "get-manual-session-details",
|
|
190
|
+
description: "Fetch a manual test session by id. Returns project id, title, environment, steps " +
|
|
191
|
+
"(playwright commands, signed screenshot URLs, notes), and linked scenario ordinal ids. " +
|
|
192
|
+
"Use when authoring a SmartTest from a recorded manual session.",
|
|
193
|
+
inputSchema: S.getManualSessionDetailsInput,
|
|
194
|
+
execute: async (args, { postMcp }) => {
|
|
195
|
+
const a = args;
|
|
196
|
+
return postMcp("/api/mcp/get_manual_session_details", {
|
|
197
|
+
manualSessionId: a.manualSessionId,
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
},
|
|
151
201
|
{
|
|
152
202
|
kebab: "mark-plan-items-implementation-done",
|
|
153
203
|
description: "Mark user stories and/or test scenarios implementation-complete in platform lifecycle (DB only; does not rewrite plan markdown). " +
|
package/dist/mcp/server.js
CHANGED
|
@@ -2,7 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { postMcp } from "../core/client.js";
|
|
4
4
|
import { TOOL_DEFINITIONS, runTool } from "../core/tools.js";
|
|
5
|
-
const PACKAGE_VERSION = "0.1.
|
|
5
|
+
const PACKAGE_VERSION = "0.1.7";
|
|
6
6
|
function textResult(json) {
|
|
7
7
|
return {
|
|
8
8
|
content: [{ type: "text", text: json }],
|