@msalaam/xray-qe-toolkit 1.4.1 → 1.5.0

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/README.md CHANGED
@@ -55,17 +55,17 @@ openapi.yaml + business-rules.yaml
55
55
  ↓ (AI agent generates tests.json)
56
56
  tests.json — structured test definitions
57
57
 
58
- xqt validate ← schema check
58
+ xqt validate ← schema check
59
59
 
60
- xqt push-tests ← creates/updates Tests + Test Sets in Xray
60
+ xqt push ← creates/updates Tests + Test Sets in Xray
61
61
 
62
62
  xray-mapping.json ← auto-populated with Jira issue keys
63
63
 
64
64
  Playwright API tests ← created by Copilot (reads tests.json + xray-mapping.json)
65
65
 
66
- Sprint starts ← xqt create-plan → link Test Sets to Test Plan
66
+ Sprint starts ← xqt plan → link Test Sets to Test Plan
67
67
 
68
- CI runs tests ← xqt import-results → Test Execution in Xray
68
+ CI runs tests ← xqt import → Test Execution in Xray
69
69
  ```
70
70
 
71
71
  **Key design decisions:**
@@ -118,18 +118,18 @@ cp .env.example .env
118
118
 
119
119
  # 5. Validate and push to Xray
120
120
  npx xqt validate
121
- npx xqt push-tests
121
+ npx xqt push
122
122
  # → Tests + Test Sets created in Jira
123
123
  # → xray-mapping.json populated with issue keys
124
124
 
125
125
  # 6. Create Playwright tests (done by Copilot skill — reads tests.json + xray-mapping.json)
126
126
 
127
127
  # 7. When entering a sprint, create a Test Plan and link Test Sets
128
- npx xqt create-plan --summary "Sprint 12 — My Service Regression"
128
+ npx xqt plan --summary "Sprint 12 — My Service Regression"
129
129
 
130
130
  # 8. Run tests and import results
131
131
  npx playwright test
132
- npx xqt import-results --file test-results/results.json --env IOP-QA
132
+ npx xqt import --file test-results/results.json --env IOP-QA
133
133
  ```
134
134
 
135
135
  ---
@@ -167,13 +167,14 @@ npx xqt edit --port 3000
167
167
 
168
168
  ---
169
169
 
170
- ### `xqt create-plan`
170
+ ### `xqt plan`
171
171
 
172
172
  Create a new Xray Test Plan in JIRA. Automatically saves the key to `.xrayrc` and `tests.json`.
173
+ `create-plan` is accepted as a legacy alias.
173
174
 
174
175
  ```bash
175
- npx xqt create-plan --summary "My Service v2 Regression"
176
- npx xqt create-plan --summary "Sprint 12 Smoke Tests" --version "2024.12"
176
+ npx xqt plan --summary "My Service v2 Regression"
177
+ npx xqt plan --summary "Sprint 12 Smoke Tests" --version "2024.12"
177
178
  ```
178
179
 
179
180
  | Flag | Description |
@@ -184,35 +185,43 @@ npx xqt create-plan --summary "Sprint 12 Smoke Tests" --version "2024.12"
184
185
 
185
186
  ---
186
187
 
187
- ### `xqt push-tests`
188
+ ### `xqt push`
188
189
 
189
190
  Create or update tests in Xray Cloud, then sync Test Plan membership and the Xray folder structure.
191
+ Optionally create a Test Execution linked to the plan in a single command.
192
+ `push-tests` is accepted as a legacy alias.
190
193
 
191
194
  ```bash
192
- npx xqt push-tests
193
- npx xqt push-tests --plan APIEE-1234
195
+ npx xqt push
196
+ npx xqt push --plan APIEE-1234
197
+ npx xqt push --plan APIEE-1234 --create-execution --execution-env IOP-QA
194
198
  ```
195
199
 
196
200
  | Flag | Description |
197
201
  |---|---|
198
202
  | `--plan <key>` | Test Plan key (overrides `.xrayrc testPlanKey`) |
203
+ | `--create-execution` | Create a Test Execution linked to the Test Plan after pushing |
204
+ | `--execution-env <label>` | Environment label for the created execution (e.g. `IOP-QA`) |
205
+ | `--execution-summary <text>` | Custom summary for the created execution |
199
206
 
200
207
  **Behaviour:**
201
208
  - Tests in `xray-mapping.json` → **updated** in Xray
202
209
  - Tests not in mapping → **created** in Xray, mapping entry added
203
210
  - Tests with `"skip": true` → excluded entirely
204
- - Tests are added to **Test Sets** based on the `testSet` field in `tests.json`
211
+ - **Test Sets auto-created** from the `testSet` field and tests added to them (see below)
205
212
  - Xray folder structure synced from `folder` fields
213
+ - With `--create-execution`, a new Test Execution is created and linked to the Test Plan
206
214
 
207
215
  ---
208
216
 
209
- ### `xqt pull-tests`
217
+ ### `xqt pull`
210
218
 
211
219
  Pull test definitions from Xray Cloud and merge them into `tests.json`. Useful for onboarding to an existing Xray project.
220
+ `pull-tests` is accepted as a legacy alias.
212
221
 
213
222
  ```bash
214
- npx xqt pull-tests --plan APIEE-1234
215
- npx xqt pull-tests --project APIEE --limit 200
223
+ npx xqt pull --plan APIEE-1234
224
+ npx xqt pull --project APIEE --limit 200
216
225
  ```
217
226
 
218
227
  | Flag | Description |
@@ -223,20 +232,21 @@ npx xqt pull-tests --project APIEE --limit 200
223
232
 
224
233
  ---
225
234
 
226
- ### `xqt create-execution`
235
+ ### `xqt exec`
227
236
 
228
237
  Pre-create a Test Execution with a specific set of tests before running them.
229
- Use `--quiet` to capture the key in CI for use with `import-results --exec`.
238
+ Use `--quiet` to capture the key in CI for use with `import --exec`.
239
+ `create-execution` is accepted as a legacy alias.
230
240
 
231
241
  ```bash
232
242
  # Standard output
233
- npx xqt create-execution --env IOP-QA
243
+ npx xqt exec --env IOP-QA
234
244
 
235
245
  # CI mode — prints ONLY the key
236
- EXEC_KEY=$(npx xqt create-execution --env IOP-QA --quiet)
246
+ EXEC_KEY=$(npx xqt exec --env IOP-QA --quiet)
237
247
 
238
248
  # Specific test selection
239
- npx xqt create-execution --env IOP-QA --plan APIEE-1234 --tests TC-001,TC-002
249
+ npx xqt exec --env IOP-QA --plan APIEE-1234 --tests TC-001,TC-002
240
250
  ```
241
251
 
242
252
  | Flag | Description |
@@ -247,13 +257,14 @@ npx xqt create-execution --env IOP-QA --plan APIEE-1234 --tests TC-001,TC-002
247
257
  | `--summary <text>` | Custom execution title |
248
258
  | `--quiet` | Print only the execution key |
249
259
 
250
- > `import-results` creates an execution automatically — this command is only needed when pre-selecting a specific subset of tests.
260
+ > `xqt import` creates an execution automatically — this command is only needed when pre-selecting a specific subset of tests.
251
261
 
252
262
  ---
253
263
 
254
- ### `xqt import-results`
264
+ ### `xqt import`
255
265
 
256
266
  Import test execution results into Xray Cloud.
267
+ `import-results` is accepted as a legacy alias.
257
268
 
258
269
  - **Without `--exec`** — creates a **new** Test Execution linked to the Test Plan
259
270
  - **With `--exec`** — imports results INTO a pre-created execution
@@ -262,16 +273,16 @@ Supported: Playwright JSON (`.json`) and JUnit XML (`.xml`).
262
273
 
263
274
  ```bash
264
275
  # Auto-create execution (standard CI)
265
- npx xqt import-results --file test-results/results.json --env IOP-QA
276
+ npx xqt import --file test-results/results.json --env IOP-QA
266
277
 
267
278
  # Import into a pre-created execution
268
- npx xqt import-results --file test-results/results.json --exec APIEE-9876
279
+ npx xqt import --file test-results/results.json --exec APIEE-9876
269
280
 
270
281
  # JUnit XML
271
- npx xqt import-results --file test-results/results.xml --env IOP-PROD
282
+ npx xqt import --file test-results/results.xml --env IOP-PROD
272
283
 
273
284
  # Full options
274
- npx xqt import-results \
285
+ npx xqt import \
275
286
  --file test-results/results.json \
276
287
  --env IOP-QA \
277
288
  --plan APIEE-1234 \
@@ -284,19 +295,20 @@ npx xqt import-results \
284
295
  | `--file <path>` | Path to results file **(required)** |
285
296
  | `--env <label>` | Environment label (default: `defaultEnvironment` from `.xrayrc`) |
286
297
  | `--plan <key>` | Test Plan key (overrides `.xrayrc`; used when no `--exec`) |
287
- | `--exec <key>` | Import INTO an existing execution (from `create-execution`) |
298
+ | `--exec <key>` | Import INTO an existing execution (from `xqt exec`) |
288
299
  | `--version <ver>` | Fix version / release label |
289
300
  | `--revision <rev>` | Build number or git SHA |
290
301
  | `--summary <text>` | Custom execution summary |
291
302
 
292
303
  ---
293
304
 
294
- ### `xqt sync-folders`
305
+ ### `xqt sync`
295
306
 
296
307
  Sync the Xray Test Repository folder structure from `folder` fields in `tests.json` without touching test content.
308
+ `sync-folders` is accepted as a legacy alias.
297
309
 
298
310
  ```bash
299
- npx xqt sync-folders
311
+ npx xqt sync
300
312
  ```
301
313
 
302
314
  ---
@@ -327,13 +339,14 @@ npx xqt validate --file path/to/tests.json
327
339
 
328
340
  ---
329
341
 
330
- ### `xqt gen-pipeline`
342
+ ### `xqt pipeline`
331
343
 
332
344
  Generate an Azure Pipelines YAML template for the current project.
345
+ `gen-pipeline` is accepted as a legacy alias.
333
346
 
334
347
  ```bash
335
- npx xqt gen-pipeline
336
- npx xqt gen-pipeline --output .azure/ci.yml
348
+ npx xqt pipeline
349
+ npx xqt pipeline --output .azure/ci.yml
337
350
  ```
338
351
 
339
352
  ---
@@ -440,7 +453,7 @@ JIRA_EMAIL=your.email@company.com
440
453
  | `test_id` | string | Yes | Stable local ID — maps to the Xray key in `xray-mapping.json` |
441
454
  | `type` | string | — | `api` / `ui` / `e2e` (informational) |
442
455
  | `skip` | boolean | — | `true` to exclude from `push-tests` |
443
- | `tags` | string[] | — | QE tags for categorisation and filtering |
456
+ | `tags` | string[] | — | QE tags for categorisation and filtering. Allowed: `regression`, `smoke`, `edge`, `critical`, `integration`, `e2e`, `security`, `performance`, `contract`, `functional`, `negative`, `positive`, `boundary`, `acceptance`, `sanity`, `data-driven`, `exploratory`, `accessibility` |
444
457
  | `folder` | string | — | Xray repository folder path — must start with `/` |
445
458
  | `testSet` | string | — | Test Set name in Jira — tests are grouped into Test Sets by this value |
446
459
  | `requirementKeys` | string[] | — | JIRA keys this test covers (creates traceability links) |
@@ -457,27 +470,51 @@ JIRA_EMAIL=your.email@company.com
457
470
 
458
471
  ### Test Sets (persistent groupings)
459
472
 
460
- Tests live in **Test Sets** in Jira. Each Test Set groups related tests — typically by feature (matching the feature name in `business-rules.yaml`).
473
+ Tests live in **Test Sets** in Jira. Each Test Set groups related tests by feature or area they persist across every sprint.
461
474
 
462
- - Created automatically by `push-tests` from the `testSet` field in `tests.json`
463
- - Persistent across sprints — they represent what tests exist
464
- - Link Test Sets to Test Plans when entering a sprint
475
+ Set the `testSet` field on each test in `tests.json`:
476
+
477
+ ```json
478
+ { "test_id": "TC-001", "testSet": "Client Lookup", ... }
479
+ { "test_id": "TC-002", "testSet": "Client Lookup", ... }
480
+ { "test_id": "TC-003", "testSet": "Health Check", ... }
481
+ ```
482
+
483
+ When you run `xqt push`:
484
+ 1. Tests are created/updated in Xray
485
+ 2. For each unique `testSet` value, the Test Set JIRA issue is **created automatically** if it doesn't exist yet
486
+ 3. Tests are added to their Test Set (idempotent — Xray ignores tests already in the set)
487
+ 4. Test Set → JIRA key mappings (e.g. `"Client Lookup" → APIEE-99`) are stored in `xray-mapping.json` under `_testSets`
488
+
489
+ ```json
490
+ // xray-mapping.json (auto-managed)
491
+ {
492
+ "_testSets": {
493
+ "Client Lookup": { "key": "APIEE-99", "id": "123456" },
494
+ "Health Check": { "key": "APIEE-100", "id": "123457" }
495
+ },
496
+ "TC-001": { "key": "APIEE-200", "id": "234001" },
497
+ ...
498
+ }
499
+ ```
500
+
501
+ Test Sets are **not deleted** when tests are removed from `tests.json`. They persist in Jira as a record of all tests that have ever existed for that feature.
465
502
 
466
503
  ### Test Plans (per-sprint)
467
504
 
468
505
  A Test Plan scopes testing work for a specific sprint or release.
469
506
 
470
- - Create with `xqt create-plan --summary "Sprint 12 — My Service"`
471
- - Link relevant Test Sets to the Test Plan in Jira
507
+ - Create with `xqt plan --summary "Sprint 12 — My Service"`
508
+ - Link relevant Test Sets to the Test Plan in Jira (manual step in Jira UI)
472
509
  - Key stored in `.xrayrc` (`testPlanKey`)
473
- - `import-results` links executions to the active plan
510
+ - `xqt import` links executions to the active plan
474
511
 
475
512
  ### Test Executions (ephemeral per run)
476
513
 
477
514
  A Test Execution represents a single CI run.
478
515
 
479
- - **Auto-created** by `xqt import-results` — one new execution per run
480
- - **Pre-created** by `xqt create-execution` for controlled test selection
516
+ - **Auto-created** by `xqt import` — one new execution per run
517
+ - **Pre-created** by `xqt exec` for controlled test selection
481
518
  - Tagged with environment labels (`IOP-DEV`, `IOP-QA`, `IOP-PROD`)
482
519
  - Linked to the Test Plan automatically
483
520
 
@@ -489,18 +526,25 @@ A Test Execution represents a single CI run.
489
526
  | **Test Plan** | Per-sprint | Scopes testing for a sprint — links Test Sets |
490
527
  | **Test Execution** | Per-CI-run | Records pass/fail for one run |
491
528
 
492
- ### Two execution modes
529
+ ### Three execution modes
493
530
 
494
531
  **Mode A — Auto (standard CI):**
495
532
  ```bash
496
- npx xqt import-results --file results.json --env IOP-QA
533
+ npx xqt import --file results.json --env IOP-QA
497
534
  ```
498
535
 
499
536
  **Mode B — Pre-create (controlled test selection):**
500
537
  ```bash
501
- EXEC_KEY=$(npx xqt create-execution --env IOP-QA --plan APIEE-1234 --quiet)
538
+ EXEC_KEY=$(npx xqt exec --env IOP-QA --plan APIEE-1234 --quiet)
539
+ npx playwright test
540
+ npx xqt import --file results.json --exec $EXEC_KEY
541
+ ```
542
+
543
+ **Mode C — Push & execute (single command):**
544
+ ```bash
545
+ npx xqt push --plan APIEE-1234 --create-execution --execution-env IOP-QA
502
546
  npx playwright test
503
- npx xqt import-results --file results.json --exec $EXEC_KEY
547
+ npx xqt import --file results.json --env IOP-QA
504
548
  ```
505
549
 
506
550
  ---
@@ -571,7 +615,7 @@ Tests are organised in the Xray Test Repository using the `folder` field in `tes
571
615
 
572
616
  - Paths must start with `/`
573
617
  - `folderRoot` in `.xrayrc` sets the base path
574
- - Folders are created automatically by `push-tests` and `sync-folders`
618
+ - Folders are created automatically by `xqt push` and `xqt sync`
575
619
 
576
620
  ---
577
621
 
@@ -579,7 +623,7 @@ Tests are organised in the Xray Test Repository using the `folder` field in `tes
579
623
 
580
624
  ### Azure DevOps pipeline
581
625
 
582
- Generate a template: `npx xqt gen-pipeline`
626
+ Generate a template: `npx xqt pipeline`
583
627
 
584
628
  ```yaml
585
629
  - script: npx xqt validate
@@ -590,7 +634,7 @@ Generate a template: `npx xqt gen-pipeline`
590
634
  continueOnError: true
591
635
 
592
636
  - script: |
593
- npx xqt import-results \
637
+ npx xqt import \
594
638
  --file test-results/results.json \
595
639
  --env $(XQT_ENV)
596
640
  displayName: Import results to Xray
@@ -619,7 +663,7 @@ Generate a template: `npx xqt gen-pipeline`
619
663
 
620
664
  ```yaml
621
665
  - script: |
622
- EXEC_KEY=$(npx xqt create-execution --env $(XQT_ENV) --quiet)
666
+ EXEC_KEY=$(npx xqt exec --env $(XQT_ENV) --quiet)
623
667
  echo "##vso[task.setvariable variable=EXEC_KEY]$EXEC_KEY"
624
668
  displayName: Pre-create Test Execution
625
669
 
@@ -627,7 +671,7 @@ Generate a template: `npx xqt gen-pipeline`
627
671
  continueOnError: true
628
672
 
629
673
  - script: |
630
- npx xqt import-results --file test-results/results.json --exec $(EXEC_KEY)
674
+ npx xqt import --file test-results/results.json --exec $(EXEC_KEY)
631
675
  displayName: Import results into pre-created execution
632
676
  ```
633
677
 
@@ -663,7 +707,7 @@ Key exports: `authenticate`, `createIssue`, `updateIssue`, `getIssue`, `getTest`
663
707
 
664
708
  ## xray-mapping.json
665
709
 
666
- Auto-managed by `push-tests`. Maps local `test_id` → JIRA issue key and numeric Xray ID.
710
+ Auto-managed by `xqt push`. Maps local `test_id` → JIRA issue key and numeric Xray ID.
667
711
 
668
712
  ```json
669
713
  {
@@ -696,7 +740,7 @@ Ensure `.env` exists and is populated.
696
740
  **Test not found in mapping after push**
697
741
  ```bash
698
742
  npx xqt status
699
- npx xqt push-tests --verbose
743
+ npx xqt push --verbose
700
744
  ```
701
745
 
702
746
  **Import results — 0 tests matched**
@@ -708,6 +752,9 @@ test.info().annotations.push({ type: 'xray', description: 'APIEE-1234' });
708
752
  **Validate fails in CI**
709
753
  Fix schema errors before pushing. Common causes: missing `testId`, invalid `priority`, malformed `folder` path (must start with `/`).
710
754
 
755
+ **Old command names still work**
756
+ All previous multi-word commands (`push-tests`, `pull-tests`, `create-plan`, `create-execution`, `import-results`, `sync-folders`, `gen-pipeline`, `mcp-server`) remain valid as aliases.
757
+
711
758
  **EU region**
712
759
  Set `XRAY_REGION=eu` in `.env` or `"xrayRegion": "eu"` in `.xrayrc`.
713
760
 
package/bin/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * @msalaam/xray-qe-toolkit — CLI Entry Point
@@ -7,18 +7,18 @@
7
7
  * npx xqt <command> [options]
8
8
  *
9
9
  * Commands:
10
- * init Scaffold project structure (tests/, playwright.config.ts, tests.json, .xrayrc)
11
- * edit Launch browser-based editor for tests.json
12
- * push-tests Push/update tests in Xray Cloud + sync Test Plan + sync folders
13
- * pull-tests Pull test definitions from Xray Cloud into tests.json
14
- * create-execution Create a new Test Execution with a specific set of tests
15
- * import-results Import test results (JUnit XML or Playwright JSON) — new execution per run
16
- * create-plan Create a new Xray Test Plan in JIRA
17
- * sync-folders Sync Xray repository folder structure from tests.json folder fields
18
- * status Show local + remote project status summary
19
- * validate Validate tests.json against its schema
20
- * gen-pipeline Generate Azure Pipelines YAML
21
- * mcp-server Start the MCP server for GitHub Copilot agent-mode integration
10
+ * init Scaffold project structure (tests/, playwright.config.ts, tests.json, .xrayrc)
11
+ * edit Launch browser-based editor for tests.json
12
+ * push Push/update tests in Xray Cloud + sync Test Plan + sync folders
13
+ * pull Pull test definitions from Xray Cloud into tests.json
14
+ * exec Create a new Test Execution with a specific set of tests
15
+ * import Import test results (JUnit XML or Playwright JSON) — new execution per run
16
+ * plan Create a new Xray Test Plan in JIRA
17
+ * sync Sync Xray repository folder structure from tests.json folder fields
18
+ * status Show local + remote project status summary
19
+ * validate Validate tests.json against its schema
20
+ * pipeline Generate Azure Pipelines YAML
21
+ * mcp Start the MCP server for GitHub Copilot agent-mode integration
22
22
  */
23
23
 
24
24
  import { Command } from "commander";
@@ -61,18 +61,23 @@ program
61
61
  });
62
62
 
63
63
  program
64
- .command("push-tests")
64
+ .command("push")
65
+ .alias("push-tests")
65
66
  .description(
66
67
  "Create/update tests in Xray Cloud, sync to Test Plan, sync folder structure"
67
68
  )
68
69
  .option("--plan <key>", "Test Plan key (overrides .xrayrc testPlanKey)")
70
+ .option("--create-execution", "Create a Test Execution linked to the Test Plan after pushing")
71
+ .option("--execution-env <label>", "Environment label for created execution (e.g. IOP-QA)")
72
+ .option("--execution-summary <text>", "Custom summary for created execution")
69
73
  .action(async (opts, cmd) => {
70
74
  const mod = await import("../commands/pushTests.js");
71
75
  await mod.default({ ...opts, ...cmd.optsWithGlobals() });
72
76
  });
73
77
 
74
78
  program
75
- .command("pull-tests")
79
+ .command("pull")
80
+ .alias("pull-tests")
76
81
  .description("Pull test definitions from Xray Cloud into tests.json")
77
82
  .option("--plan <key>", "Fetch tests from a specific Test Plan")
78
83
  .option("--project <key>", "Fetch all tests in a JIRA project")
@@ -83,11 +88,12 @@ program
83
88
  });
84
89
 
85
90
  program
86
- .command("create-execution")
91
+ .command("exec")
92
+ .alias("create-execution")
87
93
  .description(
88
94
  "Create a new Test Execution with a specific set of tests. " +
89
95
  "Use --quiet to print only the execution key for CI variable capture: " +
90
- "EXEC_KEY=$(xqt create-execution --env IOP-QA --quiet)"
96
+ "EXEC_KEY=$(xqt exec --env IOP-QA --quiet)"
91
97
  )
92
98
  .option("--env <environment>", "Environment label (e.g. IOP-QA, IOP-PROD)")
93
99
  .option("--plan <key>", "Test Plan key to link the execution to (overrides .xrayrc)")
@@ -101,14 +107,15 @@ program
101
107
  });
102
108
 
103
109
  program
104
- .command("import-results")
110
+ .command("import")
111
+ .alias("import-results")
105
112
  .description(
106
113
  "Import test results into Xray Cloud — creates a NEW Test Execution per run (JUnit XML or Playwright JSON)"
107
114
  )
108
115
  .requiredOption("--file <path>", "Path to results file (.json for Playwright, .xml for JUnit)")
109
116
  .option("--env <environment>", "Test environment label (e.g. IOP-DEV, IOP-QA, IOP-PROD)")
110
117
  .option("--plan <key>", "Test Plan key to associate execution with (overrides .xrayrc)")
111
- .option("--exec <key>", "Import INTO an existing Test Execution key (from create-execution)")
118
+ .option("--exec <key>", "Import INTO an existing Test Execution key (from xqt exec)")
112
119
  .option("--version <version>", "Fix version / release version")
113
120
  .option("--revision <revision>", "Revision / build number")
114
121
  .option("--summary <text>", "Custom Test Execution summary")
@@ -119,7 +126,8 @@ program
119
126
  });
120
127
 
121
128
  program
122
- .command("create-plan")
129
+ .command("plan")
130
+ .alias("create-plan")
123
131
  .description("Create a new Test Plan in JIRA and save its key to .xrayrc and tests.json")
124
132
  .requiredOption("--summary <text>", "Test Plan summary / title")
125
133
  .option("--version <version>", "Fix version to associate with the plan")
@@ -130,7 +138,8 @@ program
130
138
  });
131
139
 
132
140
  program
133
- .command("sync-folders")
141
+ .command("sync")
142
+ .alias("sync-folders")
134
143
  .description("Sync Xray repository folder structure from the folder field in tests.json")
135
144
  .action(async (opts, cmd) => {
136
145
  const mod = await import("../commands/syncFolders.js");
@@ -157,7 +166,8 @@ program
157
166
  });
158
167
 
159
168
  program
160
- .command("gen-pipeline")
169
+ .command("pipeline")
170
+ .alias("gen-pipeline")
161
171
  .description("Generate an Azure Pipelines YAML template")
162
172
  .option("--output <path>", "Output file path", "azure-pipelines.yml")
163
173
  .action(async (opts, cmd) => {
@@ -166,7 +176,8 @@ program
166
176
  });
167
177
 
168
178
  program
169
- .command("mcp-server")
179
+ .command("mcp")
180
+ .alias("mcp-server")
170
181
  .description(
171
182
  "Start the MCP server for GitHub Copilot agent-mode integration. " +
172
183
  "Runs in stdio mode by default (for VS Code), or HTTP mode with --port."
@@ -182,4 +193,4 @@ program
182
193
  program.parseAsync(process.argv).catch((err) => {
183
194
  console.error(`\n${err.message}\n`);
184
195
  process.exit(1);
185
- });
196
+ });
@@ -12,7 +12,7 @@
12
12
  import fs from "node:fs";
13
13
  import logger, { setVerbose } from "../lib/logger.js";
14
14
  import { loadConfig, validateConfig } from "../lib/config.js";
15
- import { authenticate, createTestPlan } from "../lib/xrayClient.js";
15
+ import { authenticate, createIssue, createTestPlan, getIssue } from "../lib/xrayClient.js";
16
16
 
17
17
  export default async function createPlan(opts = {}) {
18
18
  if (opts.verbose) setVerbose(true);
@@ -42,47 +42,36 @@ export default async function createPlan(opts = {}) {
42
42
 
43
43
  let planKey;
44
44
  try {
45
- const jiraPayload = {
46
- fields: {
47
- project: { key: cfg.jiraProjectKey },
48
- summary,
49
- issuetype: { name: "Test Plan" },
50
- ...(opts.version && {
51
- fixVersions: [{ name: opts.version }],
52
- }),
53
- ...(opts.label && {
54
- labels: opts.label.split(",").map((l) => l.trim()),
55
- }),
56
- },
45
+ const fields = {
46
+ summary,
47
+ description: summary,
48
+ ...(opts.label && {
49
+ labels: opts.label.split(",").map((l) => l.trim()),
50
+ }),
57
51
  };
58
52
 
59
- const response = await fetch(`${cfg.jiraUrl}/rest/api/3/issue`, {
60
- method: "POST",
61
- headers: {
62
- "Content-Type": "application/json",
63
- Authorization: `Basic ${Buffer.from(`${cfg.jiraEmail}:${cfg.jiraApiToken}`).toString("base64")}`,
64
- },
65
- body: JSON.stringify(jiraPayload),
66
- });
67
-
68
- if (!response.ok) {
69
- const body = await response.text();
70
- throw new Error(`JIRA returned ${response.status}: ${body}`);
71
- }
72
-
73
- const data = await response.json();
74
- planKey = data.key;
53
+ const issue = await createIssue(cfg, "Test Plan", fields);
54
+ planKey = issue.key;
75
55
  } catch (err) {
76
56
  // Fallback: try via Xray GraphQL createTestPlan mutation
77
57
  logger.debug(`JIRA REST failed, trying Xray GraphQL: ${err.message}`);
78
58
  try {
79
59
  const result = await createTestPlan(cfg, xrayToken, {
80
- jira: {
81
- summary,
82
- project: { key: cfg.jiraProjectKey },
83
- },
60
+ projectId: cfg.jiraProjectKey,
61
+ summary,
62
+ description: summary,
84
63
  });
85
- planKey = result?.createTestPlan?.testPlan?.jira?.key;
64
+
65
+ // GraphQL returns { testPlan: { issueId, projectId } } — resolve key via JIRA
66
+ const issueId = result?.testPlan?.issueId;
67
+ if (issueId) {
68
+ try {
69
+ const issue = await getIssue(cfg, issueId);
70
+ planKey = issue?.key;
71
+ } catch {
72
+ logger.debug(`Could not resolve JIRA key for issueId ${issueId}`);
73
+ }
74
+ }
86
75
  } catch (gqlErr) {
87
76
  logger.error(`Could not create Test Plan: ${gqlErr.message}`);
88
77
  process.exit(1);