@testchimp/cli 0.1.8 → 0.1.10
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.js +73 -0
- package/dist/core/schemas.d.ts +35 -0
- package/dist/core/schemas.js +24 -0
- package/dist/core/tools.js +65 -0
- package/package.json +1 -1
package/dist/cli/program.js
CHANGED
|
@@ -197,6 +197,54 @@ export function buildCliProgram() {
|
|
|
197
197
|
const out = await runTool("update-user-story", merged, { postMcp });
|
|
198
198
|
console.log(out);
|
|
199
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
|
+
});
|
|
200
248
|
program
|
|
201
249
|
.command("mark-plan-items-implementation-done")
|
|
202
250
|
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "mark-plan-items-implementation-done").description)
|
|
@@ -460,6 +508,31 @@ export function buildCliProgram() {
|
|
|
460
508
|
const out = await runTool("upsert-screen-states", merged, { postMcp });
|
|
461
509
|
console.log(out);
|
|
462
510
|
});
|
|
511
|
+
program
|
|
512
|
+
.command("list-semantic-similar-tests")
|
|
513
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "list-semantic-similar-tests").description)
|
|
514
|
+
.addOption(jsonInputOption())
|
|
515
|
+
.option("--folder-path <path>", "folder under tests root, slash-separated")
|
|
516
|
+
.action(async (opts) => {
|
|
517
|
+
const body = {};
|
|
518
|
+
const scope = {};
|
|
519
|
+
if (opts.folderPath)
|
|
520
|
+
scope.folderPath = opts.folderPath;
|
|
521
|
+
if (Object.keys(scope).length)
|
|
522
|
+
body.scope = scope;
|
|
523
|
+
const merged = mergeBodies(body, opts.jsonInput);
|
|
524
|
+
const out = await runTool("list-semantic-similar-tests", merged, { postMcp });
|
|
525
|
+
console.log(out);
|
|
526
|
+
});
|
|
527
|
+
program
|
|
528
|
+
.command("mark-semantic-tests-distinct")
|
|
529
|
+
.description(TOOL_DEFINITIONS.find((t) => t.kebab === "mark-semantic-tests-distinct").description)
|
|
530
|
+
.addOption(jsonInputOption())
|
|
531
|
+
.action(async (opts) => {
|
|
532
|
+
const merged = mergeBodies({}, opts.jsonInput);
|
|
533
|
+
const out = await runTool("mark-semantic-tests-distinct", merged, { postMcp });
|
|
534
|
+
console.log(out);
|
|
535
|
+
});
|
|
463
536
|
program.on("--help", () => {
|
|
464
537
|
/* default */
|
|
465
538
|
});
|
package/dist/core/schemas.d.ts
CHANGED
|
@@ -70,6 +70,15 @@ export declare const markPlanItemsImplementationDoneInput: z.ZodObject<{
|
|
|
70
70
|
scenarioOrdinalIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
|
|
71
71
|
userStoryOrdinalIds: z.ZodOptional<z.ZodArray<z.ZodCoercedNumber<unknown>>>;
|
|
72
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>;
|
|
73
82
|
export declare const emptyInput: z.ZodObject<{}, z.core.$strip>;
|
|
74
83
|
export declare const getBranchSpecificEndpointConfigInput: z.ZodObject<{
|
|
75
84
|
branchName: z.ZodOptional<z.ZodString>;
|
|
@@ -114,3 +123,29 @@ export declare const upsertScreenStatesInput: z.ZodObject<{
|
|
|
114
123
|
states: z.ZodArray<z.ZodString>;
|
|
115
124
|
}, z.core.$strip>>;
|
|
116
125
|
}, z.core.$strip>;
|
|
126
|
+
export declare const testLocatorSchema: z.ZodObject<{
|
|
127
|
+
folderPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
128
|
+
fileName: z.ZodString;
|
|
129
|
+
testSuite: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
130
|
+
testName: z.ZodString;
|
|
131
|
+
}, z.core.$strip>;
|
|
132
|
+
export declare const listSemanticSimilarTestsInput: z.ZodObject<{
|
|
133
|
+
scope: z.ZodOptional<z.ZodObject<{
|
|
134
|
+
filePaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
135
|
+
folderPath: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodString]>>;
|
|
136
|
+
}, z.core.$strip>>;
|
|
137
|
+
}, z.core.$strip>;
|
|
138
|
+
export declare const markSemanticTestsDistinctInput: z.ZodObject<{
|
|
139
|
+
focusTest: z.ZodObject<{
|
|
140
|
+
folderPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
141
|
+
fileName: z.ZodString;
|
|
142
|
+
testSuite: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
143
|
+
testName: z.ZodString;
|
|
144
|
+
}, z.core.$strip>;
|
|
145
|
+
distinctTest: z.ZodObject<{
|
|
146
|
+
folderPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
147
|
+
fileName: z.ZodString;
|
|
148
|
+
testSuite: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
149
|
+
testName: z.ZodString;
|
|
150
|
+
}, z.core.$strip>;
|
|
151
|
+
}, z.core.$strip>;
|
package/dist/core/schemas.js
CHANGED
|
@@ -69,6 +69,17 @@ export const markPlanItemsImplementationDoneInput = z.object({
|
|
|
69
69
|
scenarioOrdinalIds: z.array(z.coerce.number().int().positive()).optional(),
|
|
70
70
|
userStoryOrdinalIds: z.array(z.coerce.number().int().positive()).optional(),
|
|
71
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
|
+
});
|
|
72
83
|
export const emptyInput = z.object({});
|
|
73
84
|
export const getBranchSpecificEndpointConfigInput = z.object({
|
|
74
85
|
branchName: z.string().optional(),
|
|
@@ -114,3 +125,16 @@ const screenStatesEntrySchema = z.object({
|
|
|
114
125
|
export const upsertScreenStatesInput = z.object({
|
|
115
126
|
screenStates: z.array(screenStatesEntrySchema).min(1),
|
|
116
127
|
});
|
|
128
|
+
export const testLocatorSchema = z.object({
|
|
129
|
+
folderPath: z.array(z.string()).optional(),
|
|
130
|
+
fileName: z.string().min(1),
|
|
131
|
+
testSuite: z.array(z.string()).optional(),
|
|
132
|
+
testName: z.string().min(1),
|
|
133
|
+
});
|
|
134
|
+
export const listSemanticSimilarTestsInput = z.object({
|
|
135
|
+
scope: scopeSchema,
|
|
136
|
+
});
|
|
137
|
+
export const markSemanticTestsDistinctInput = z.object({
|
|
138
|
+
focusTest: testLocatorSchema,
|
|
139
|
+
distinctTest: testLocatorSchema,
|
|
140
|
+
});
|
package/dist/core/tools.js
CHANGED
|
@@ -159,6 +159,45 @@ export const TOOL_DEFINITIONS = [
|
|
|
159
159
|
return postMcp("/api/mcp/update_test_scenario", { content: a.content });
|
|
160
160
|
},
|
|
161
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
|
+
},
|
|
162
201
|
{
|
|
163
202
|
kebab: "mark-plan-items-implementation-done",
|
|
164
203
|
description: "Mark user stories and/or test scenarios implementation-complete in platform lifecycle (DB only; does not rewrite plan markdown). " +
|
|
@@ -357,6 +396,32 @@ export const TOOL_DEFINITIONS = [
|
|
|
357
396
|
return postMcp("/api/mcp/upsert_screen_states", { screenStates: a.screenStates });
|
|
358
397
|
},
|
|
359
398
|
},
|
|
399
|
+
{
|
|
400
|
+
kebab: "list-semantic-similar-tests",
|
|
401
|
+
description: "List semantically similar SmartTest pairs in scope using TestLocators (no test_id). " +
|
|
402
|
+
"Pairs are deduped (A→B only when A.testId < B.testId). Distinct-marked pairs are excluded.",
|
|
403
|
+
inputSchema: S.listSemanticSimilarTestsInput,
|
|
404
|
+
execute: async (args, { postMcp }) => {
|
|
405
|
+
const a = args;
|
|
406
|
+
const body = {};
|
|
407
|
+
if (a.scope != null)
|
|
408
|
+
body.scope = normalizeScope(a.scope);
|
|
409
|
+
return postMcp("/api/mcp/list_semantic_similar_tests", body);
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
kebab: "mark-semantic-tests-distinct",
|
|
414
|
+
description: "Mark two SmartTests as legitimately distinct (symmetric) using TestLocators. " +
|
|
415
|
+
"Agent/API calls use marked_by_user_id = 0.",
|
|
416
|
+
inputSchema: S.markSemanticTestsDistinctInput,
|
|
417
|
+
execute: async (args, { postMcp }) => {
|
|
418
|
+
const a = args;
|
|
419
|
+
return postMcp("/api/mcp/mark_semantic_tests_distinct", {
|
|
420
|
+
focusTest: a.focusTest,
|
|
421
|
+
distinctTest: a.distinctTest,
|
|
422
|
+
});
|
|
423
|
+
},
|
|
424
|
+
},
|
|
360
425
|
];
|
|
361
426
|
const TOOL_BY_KEBAB = new Map(TOOL_DEFINITIONS.map((t) => [t.kebab, t]));
|
|
362
427
|
export function getToolDefinition(kebab) {
|