@testchimp/cli 0.1.5 → 0.1.7

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.
@@ -46,6 +46,7 @@ export function buildCliProgram() {
46
46
  .option("--release <s>")
47
47
  .option("--environment <s>")
48
48
  .option("--branch-name <s>")
49
+ .option("--platform <web|ios|android>")
49
50
  .option("--file-paths <csv>", "comma-separated paths under platform tests root")
50
51
  .option("--folder-path <path>", "folder under tests root, slash-separated")
51
52
  .action(async (opts) => {
@@ -56,6 +57,8 @@ export function buildCliProgram() {
56
57
  body.environment = opts.environment;
57
58
  if (opts.branchName)
58
59
  body.branchName = opts.branchName;
60
+ if (opts.platform)
61
+ body.platform = opts.platform;
59
62
  const scope = {};
60
63
  if (opts.filePaths)
61
64
  scope.filePaths = String(opts.filePaths).split(",").map((s) => s.trim()).filter(Boolean);
@@ -74,6 +77,8 @@ export function buildCliProgram() {
74
77
  .option("--release <s>")
75
78
  .option("--environment <s>")
76
79
  .option("--branch-name <s>")
80
+ .option("--scenario-id <id>")
81
+ .option("--platform <web|ios|android>")
77
82
  .option("--file-paths <csv>")
78
83
  .option("--folder-path <path>")
79
84
  .action(async (opts) => {
@@ -84,6 +89,10 @@ export function buildCliProgram() {
84
89
  body.environment = opts.environment;
85
90
  if (opts.branchName)
86
91
  body.branchName = opts.branchName;
92
+ if (opts.scenarioId)
93
+ body.scenarioId = opts.scenarioId;
94
+ if (opts.platform)
95
+ body.platform = opts.platform;
87
96
  const scope = {};
88
97
  if (opts.filePaths)
89
98
  scope.filePaths = String(opts.filePaths).split(",").map((s) => s.trim()).filter(Boolean);
@@ -332,7 +341,7 @@ export function buildCliProgram() {
332
341
  const out = await runTool("list-rum-environments", merged, { postMcp });
333
342
  console.log(out);
334
343
  });
335
- const truecoverageHelp = "Prefer --json-input with full request JSON (proto-shaped). Flags are optional shortcuts where listed.";
344
+ const truecoverageHelp = "Use --json-input with full request JSON (proto-shaped; set platform inside each ExecutionScope).";
336
345
  program
337
346
  .command("get-truecoverage-events")
338
347
  .description(TOOL_DEFINITIONS.find((t) => t.kebab === "get-truecoverage-events").description + " " + truecoverageHelp)
@@ -3,6 +3,10 @@ export declare const scopeSchema: z.ZodOptional<z.ZodObject<{
3
3
  filePaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
4
4
  folderPath: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodString]>>;
5
5
  }, z.core.$strip>>;
6
+ export declare const executionJobDimensionFilterSchema: z.ZodObject<{
7
+ dimension: z.ZodString;
8
+ values: z.ZodArray<z.ZodString>;
9
+ }, z.core.$strip>;
6
10
  export declare const listCoverageInput: z.ZodObject<{
7
11
  release: z.ZodOptional<z.ZodString>;
8
12
  environment: z.ZodOptional<z.ZodString>;
@@ -13,6 +17,11 @@ export declare const listCoverageInput: z.ZodObject<{
13
17
  includeNonCoveredUserStories: z.ZodOptional<z.ZodBoolean>;
14
18
  includeNonCoveredTestScenarios: z.ZodOptional<z.ZodBoolean>;
15
19
  branchName: z.ZodOptional<z.ZodString>;
20
+ platform: z.ZodOptional<z.ZodEnum<{
21
+ web: "web";
22
+ ios: "ios";
23
+ android: "android";
24
+ }>>;
16
25
  }, z.core.$strip>;
17
26
  export declare const listExecutionInput: z.ZodObject<{
18
27
  release: z.ZodOptional<z.ZodString>;
@@ -22,6 +31,18 @@ export declare const listExecutionInput: z.ZodObject<{
22
31
  folderPath: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodString]>>;
23
32
  }, z.core.$strip>>;
24
33
  branchName: z.ZodOptional<z.ZodString>;
34
+ scenarioId: z.ZodOptional<z.ZodString>;
35
+ platform: z.ZodOptional<z.ZodEnum<{
36
+ web: "web";
37
+ ios: "ios";
38
+ android: "android";
39
+ }>>;
40
+ dimensionFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
41
+ dimension: z.ZodString;
42
+ values: z.ZodArray<z.ZodString>;
43
+ }, z.core.$strip>>>;
44
+ limit: z.ZodOptional<z.ZodNumber>;
45
+ offset: z.ZodOptional<z.ZodNumber>;
25
46
  }, z.core.$strip>;
26
47
  export declare const fetchExecutionReportInput: z.ZodObject<{
27
48
  batchInvocationId: z.ZodOptional<z.ZodString>;
@@ -5,6 +5,11 @@ export const scopeSchema = z
5
5
  folderPath: z.union([z.array(z.string()), z.string()]).optional(),
6
6
  })
7
7
  .optional();
8
+ const executionPlatformSchema = z.enum(["web", "ios", "android"]);
9
+ export const executionJobDimensionFilterSchema = z.object({
10
+ dimension: z.string().min(1),
11
+ values: z.array(z.string()).min(1),
12
+ });
8
13
  export const listCoverageInput = z.object({
9
14
  release: z.string().optional(),
10
15
  environment: z.string().optional(),
@@ -12,12 +17,18 @@ export const listCoverageInput = z.object({
12
17
  includeNonCoveredUserStories: z.boolean().optional(),
13
18
  includeNonCoveredTestScenarios: z.boolean().optional(),
14
19
  branchName: z.string().optional(),
20
+ platform: executionPlatformSchema.optional(),
15
21
  });
16
22
  export const listExecutionInput = z.object({
17
23
  release: z.string().optional(),
18
24
  environment: z.string().optional(),
19
25
  scope: scopeSchema,
20
26
  branchName: z.string().optional(),
27
+ scenarioId: z.string().optional(),
28
+ platform: executionPlatformSchema.optional(),
29
+ dimensionFilters: z.array(executionJobDimensionFilterSchema).optional(),
30
+ limit: z.number().int().positive().max(500).optional(),
31
+ offset: z.number().int().nonnegative().optional(),
21
32
  });
22
33
  export const fetchExecutionReportInput = z
23
34
  .object({
@@ -1,6 +1,16 @@
1
1
  import { normalizeScope } from "./normalize.js";
2
2
  import { runProvisionEphemeralEnvironmentAndWait } from "./ephemeralWait.js";
3
3
  import * as S from "./schemas.js";
4
+ function platformToProtoEnum(platform) {
5
+ switch (platform) {
6
+ case "ios":
7
+ return "IOS_EXECUTION_PLATFORM";
8
+ case "android":
9
+ return "ANDROID_EXECUTION_PLATFORM";
10
+ default:
11
+ return "WEB_EXECUTION_PLATFORM";
12
+ }
13
+ }
4
14
  function listCoverageBody(args) {
5
15
  const body = {};
6
16
  if (args.release != null)
@@ -16,6 +26,8 @@ function listCoverageBody(args) {
16
26
  }
17
27
  if (args.branchName != null && args.branchName.trim() !== "")
18
28
  body.branchName = args.branchName.trim();
29
+ if (args.platform != null)
30
+ body.platform = platformToProtoEnum(args.platform);
19
31
  return body;
20
32
  }
21
33
  function listExecutionBody(args) {
@@ -28,6 +40,24 @@ function listExecutionBody(args) {
28
40
  body.scope = normalizeScope(args.scope);
29
41
  if (args.branchName != null && args.branchName.trim() !== "")
30
42
  body.branchName = args.branchName.trim();
43
+ if (args.scenarioId != null && args.scenarioId.trim() !== "")
44
+ body.scenarioId = args.scenarioId.trim();
45
+ const dimensionFilters = [...(args.dimensionFilters ?? [])];
46
+ if (args.platform != null) {
47
+ const hasPlatformFilter = dimensionFilters.some((f) => f.dimension === "PLATFORM_EXECUTION_JOB_FILTER_DIMENSION");
48
+ if (!hasPlatformFilter) {
49
+ dimensionFilters.push({
50
+ dimension: "PLATFORM_EXECUTION_JOB_FILTER_DIMENSION",
51
+ values: [args.platform.toUpperCase()],
52
+ });
53
+ }
54
+ }
55
+ if (dimensionFilters.length > 0)
56
+ body.dimensionFilters = dimensionFilters;
57
+ if (args.limit != null)
58
+ body.limit = args.limit;
59
+ if (args.offset != null)
60
+ body.offset = args.offset;
31
61
  return body;
32
62
  }
33
63
  export const TOOL_DEFINITIONS = [
@@ -36,7 +66,7 @@ export const TOOL_DEFINITIONS = [
36
66
  description: "Fetch requirement (scenario) coverage under an optional platform-rooted folder scope (tests/... or plans/...). " +
37
67
  "Use scope.filePaths or scope.folderPath (platform tests/plans roots). Omit branchName for cross-branch coverage " +
38
68
  "(aggregates branch copies; execution jobs deduped by stable hash of tests-root-relative path + test name). " +
39
- "Pass branchName only when results must be limited to one Git branch.",
69
+ "Pass branchName only when results must be limited to one Git branch. Optional platform (web|ios|android) filters rollup.",
40
70
  inputSchema: S.listCoverageInput,
41
71
  execute: async (args, { postMcp }) => {
42
72
  const json = await postMcp("/api/mcp/list_requirement_coverage", listCoverageBody(args));
@@ -45,8 +75,8 @@ export const TOOL_DEFINITIONS = [
45
75
  },
46
76
  {
47
77
  kebab: "get-execution-history",
48
- description: "Fetch SmartTest execution history for an optional platform-rooted folder scope. " +
49
- "Use branchName and scope.filePaths as for coverage.",
78
+ description: "Fetch SmartTest execution history for an optional platform-rooted folder scope, or for a scenario when scenarioId is set. " +
79
+ "Use branchName and scope.filePaths as for coverage. Optional platform (web|ios|android) and dimensionFilters narrow results.",
50
80
  inputSchema: S.listExecutionInput,
51
81
  execute: async (args, { postMcp }) => {
52
82
  const json = await postMcp("/api/mcp/list_execution_history", listExecutionBody(args));
@@ -243,31 +273,38 @@ export const TOOL_DEFINITIONS = [
243
273
  },
244
274
  {
245
275
  kebab: "get-truecoverage-events",
246
- description: "TrueCoverage event funnel summaries (ListEventsRequest JSON: baseExecutionScope, comparisonExecutionScope).",
276
+ description: "TrueCoverage event funnel summaries (ListEventsRequest JSON: baseExecutionScope, comparisonExecutionScope). " +
277
+ "Optional ExecutionScope.platform: WEB_EXECUTION_PLATFORM | IOS_EXECUTION_PLATFORM | ANDROID_EXECUTION_PLATFORM " +
278
+ "(filters RUM rows stamped via testchimp-rum-platform header: web=1, ios=2, android=3). " +
279
+ "Use automationEmitsOnly on comparisonExecutionScope for test-tagged emits only.",
247
280
  inputSchema: S.truecoverageJsonInput,
248
281
  execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_list_events", args ?? {}),
249
282
  },
250
283
  {
251
284
  kebab: "get-truecoverage-event-details",
252
- description: "TrueCoverage drill-down for one event title (GetEventDetailsRequest JSON).",
285
+ description: "TrueCoverage drill-down for one event title (GetEventDetailsRequest JSON). " +
286
+ "Optional platform on baseExecutionScope / comparisonExecutionScope (WEB_EXECUTION_PLATFORM, IOS_EXECUTION_PLATFORM, ANDROID_EXECUTION_PLATFORM).",
253
287
  inputSchema: S.truecoverageJsonInput,
254
288
  execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_event_details", args ?? {}),
255
289
  },
256
290
  {
257
291
  kebab: "get-truecoverage-child-event-tree",
258
- description: "TrueCoverage next-event tree for an event (ListChildEventTreeRequest JSON).",
292
+ description: "TrueCoverage next-event tree for an event (ListChildEventTreeRequest JSON). " +
293
+ "Optional platform on baseScope / coverageScope (inside each ExecutionScope).",
259
294
  inputSchema: S.truecoverageJsonInput,
260
295
  execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_list_child_event_tree", args ?? {}),
261
296
  },
262
297
  {
263
298
  kebab: "get-truecoverage-event-transition",
264
- description: "TrueCoverage detailed transition summary between events (GetDetailedEventTransitionSummaryRequest JSON).",
299
+ description: "TrueCoverage detailed transition summary between events (GetDetailedEventTransitionSummaryRequest JSON). " +
300
+ "Optional platform on baseScope / coverageScope (inside each ExecutionScope).",
265
301
  inputSchema: S.truecoverageJsonInput,
266
302
  execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_detailed_event_transition", args ?? {}),
267
303
  },
268
304
  {
269
305
  kebab: "get-truecoverage-event-time-series",
270
- description: "TrueCoverage time series for sessions or metrics (EventTimeSeriesRequest JSON).",
306
+ description: "TrueCoverage time series for sessions or metrics (EventTimeSeriesRequest JSON). " +
307
+ "Optional platform on baseExecutionScope.",
271
308
  inputSchema: S.truecoverageJsonInput,
272
309
  execute: async (args, { postMcp }) => postMcp("/api/mcp/truecoverage_event_time_series", args ?? {}),
273
310
  },
@@ -0,0 +1,16 @@
1
+ /** Maps CLI/MCP shorthand to {@code com.aware.common.ExecutionPlatform} JSON enum names. */
2
+ export declare function platformToProtoEnum(platform: "web" | "ios" | "android"): string;
3
+ export type TruecoveragePlatformCli = "web" | "ios" | "android";
4
+ export interface TruecoveragePlatformOpts {
5
+ base?: TruecoveragePlatformCli;
6
+ /** Secondary / coverage-aligned scope (`comparisonExecutionScope` or `coverageScope` per endpoint). */
7
+ comparison?: TruecoveragePlatformCli;
8
+ }
9
+ /** MCP/CLI top-level shortcuts (`basePlatform`, …) stripped before POST. */
10
+ export declare function parseTruecoveragePlatformArgs(args: unknown): TruecoveragePlatformOpts | undefined;
11
+ export declare function stripTruecoveragePlatformShortcuts(body: Record<string, unknown>): Record<string, unknown>;
12
+ /**
13
+ * Apply CLI/MCP platform shortcuts onto nested execution scopes (scope.platform in JSON wins).
14
+ */
15
+ export declare function applyTruecoveragePlatforms(body: Record<string, unknown>, opts?: TruecoveragePlatformOpts): Record<string, unknown>;
16
+ export declare function prepareTruecoverageRequestBody(args: unknown): Record<string, unknown>;
@@ -0,0 +1,74 @@
1
+ /** Maps CLI/MCP shorthand to {@code com.aware.common.ExecutionPlatform} JSON enum names. */
2
+ export function platformToProtoEnum(platform) {
3
+ switch (platform) {
4
+ case "ios":
5
+ return "IOS_EXECUTION_PLATFORM";
6
+ case "android":
7
+ return "ANDROID_EXECUTION_PLATFORM";
8
+ default:
9
+ return "WEB_EXECUTION_PLATFORM";
10
+ }
11
+ }
12
+ function setScopePlatform(scope, platform) {
13
+ if (!scope)
14
+ return;
15
+ scope.platform = platformToProtoEnum(platform);
16
+ }
17
+ function pickPlatformCli(v) {
18
+ if (v === "web" || v === "ios" || v === "android")
19
+ return v;
20
+ return undefined;
21
+ }
22
+ /** MCP/CLI top-level shortcuts (`basePlatform`, …) stripped before POST. */
23
+ export function parseTruecoveragePlatformArgs(args) {
24
+ if (args == null || typeof args !== "object")
25
+ return undefined;
26
+ const a = args;
27
+ const base = pickPlatformCli(a.basePlatform);
28
+ const comparison = pickPlatformCli(a.comparisonPlatform) ?? pickPlatformCli(a.coveragePlatform);
29
+ if (base == null && comparison == null)
30
+ return undefined;
31
+ return { base, comparison };
32
+ }
33
+ export function stripTruecoveragePlatformShortcuts(body) {
34
+ const { basePlatform: _b, comparisonPlatform: _c, coveragePlatform: _v, ...rest } = body;
35
+ return rest;
36
+ }
37
+ function mergeScopePlatform(scope, platform) {
38
+ if (scope == null || scope.platform != null)
39
+ return scope;
40
+ const next = { ...scope };
41
+ setScopePlatform(next, platform);
42
+ return next;
43
+ }
44
+ /**
45
+ * Apply CLI/MCP platform shortcuts onto nested execution scopes (scope.platform in JSON wins).
46
+ */
47
+ export function applyTruecoveragePlatforms(body, opts) {
48
+ if (!opts)
49
+ return body;
50
+ const out = { ...body };
51
+ if (opts.base != null) {
52
+ const nextBase = mergeScopePlatform(out.baseExecutionScope, opts.base);
53
+ if (nextBase != null)
54
+ out.baseExecutionScope = nextBase;
55
+ const nextBaseScope = mergeScopePlatform(out.baseScope, opts.base);
56
+ if (nextBaseScope != null)
57
+ out.baseScope = nextBaseScope;
58
+ }
59
+ if (opts.comparison != null) {
60
+ const nextComp = mergeScopePlatform(out.comparisonExecutionScope, opts.comparison);
61
+ if (nextComp != null)
62
+ out.comparisonExecutionScope = nextComp;
63
+ const nextCov = mergeScopePlatform(out.coverageScope, opts.comparison);
64
+ if (nextCov != null)
65
+ out.coverageScope = nextCov;
66
+ }
67
+ return out;
68
+ }
69
+ export function prepareTruecoverageRequestBody(args) {
70
+ const raw = args ?? {};
71
+ const platformOpts = parseTruecoveragePlatformArgs(raw);
72
+ const stripped = stripTruecoveragePlatformShortcuts({ ...raw });
73
+ return applyTruecoveragePlatforms(stripped, platformOpts);
74
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testchimp/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "TestChimp CLI and MCP server — coverage, plans, EaaS, TrueCoverage (calls /api/mcp/*)",
5
5
  "type": "module",
6
6
  "main": "dist/bin/testchimp.js",