@rbaileysr/zephyr-managed-api 1.4.2 → 1.4.3

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
@@ -279,6 +279,10 @@ Feel free to drop ideas, suggestions or improvements into our [Community hub](ht
279
279
 
280
280
  ## Changelog
281
281
 
282
+ ### 1.4.3
283
+
284
+ - **Fixed**: `createTestExecutionWithVersion()` now automatically adds the test case to the test cycle if it's not already present (matching public API behavior). This ensures executions can be created for older test case versions even if they weren't previously added to the cycle. The function now properly handles the complete workflow: adding the test case to the cycle (if needed) before creating the execution.
285
+
282
286
  ### 1.4.2
283
287
 
284
288
  - **Added**: Delete comment methods - `deleteTestCaseComment()`, `deleteTestCycleComment()`, `deleteTestPlanComment()`. All support version-specific operations for test cases.
@@ -292,6 +296,7 @@ Feel free to drop ideas, suggestions or improvements into our [Community hub](ht
292
296
  - **Added**: `AI_AGENT_GUIDE.md` - Comprehensive guide for AI coding agents covering all API functions, capabilities, limitations, and best practices. This file is included in the NPM package and visible on the NPM website.
293
297
  - **Changed**: All test case-related private API methods that accept a test case key now support an optional `version` parameter. When a version is specified, the method automatically resolves the test case ID for that specific version.
294
298
 
299
+
295
300
  ### 1.4.1
296
301
 
297
302
  - **Added**: `listAllTestExecutionsForTestCase()` - List all test executions for a test case across all versions. Unlike the public API which only returns executions for the latest version, this method returns executions from all test case versions. Returns minimal data (key and testCase info) - use the public API to get full execution details if needed.
package/dist/README.md CHANGED
@@ -279,6 +279,10 @@ Feel free to drop ideas, suggestions or improvements into our [Community hub](ht
279
279
 
280
280
  ## Changelog
281
281
 
282
+ ### 1.4.3
283
+
284
+ - **Fixed**: `createTestExecutionWithVersion()` now automatically adds the test case to the test cycle if it's not already present (matching public API behavior). This ensures executions can be created for older test case versions even if they weren't previously added to the cycle. The function now properly handles the complete workflow: adding the test case to the cycle (if needed) before creating the execution.
285
+
282
286
  ### 1.4.2
283
287
 
284
288
  - **Added**: Delete comment methods - `deleteTestCaseComment()`, `deleteTestCycleComment()`, `deleteTestPlanComment()`. All support version-specific operations for test cases.
@@ -292,6 +296,7 @@ Feel free to drop ideas, suggestions or improvements into our [Community hub](ht
292
296
  - **Added**: `AI_AGENT_GUIDE.md` - Comprehensive guide for AI coding agents covering all API functions, capabilities, limitations, and best practices. This file is included in the NPM package and visible on the NPM website.
293
297
  - **Changed**: All test case-related private API methods that accept a test case key now support an optional `version` parameter. When a version is specified, the method automatically resolves the test case ID for that specific version.
294
298
 
299
+
295
300
  ### 1.4.1
296
301
 
297
302
  - **Added**: `listAllTestExecutionsForTestCase()` - List all test executions for a test case across all versions. Unlike the public API which only returns executions for the latest version, this method returns executions from all test case versions. Returns minimal data (key and testCase info) - use the public API to get full execution details if needed.
@@ -1 +1 @@
1
- {"version":3,"file":"PrivateTestExecutions.d.ts","sourceRoot":"","sources":["../../../groups/Private/PrivateTestExecutions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AAEH,OAAO,KAAK,EACX,qBAAqB,EACrB,sCAAsC,EACtC,uCAAuC,EACvC,qCAAqC,EACrC,sCAAsC,EACtC,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,4BAA4B,EAC5B,6BAA6B,EAC7B,oCAAoC,EACpC,qCAAqC,EACrC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AA0D5C,qBAAa,qBAAsB,SAAQ,WAAW;IACrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,+BAA+B,CACpC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,sCAAsC,GAC7C,OAAO,CAAC,uCAAuC,CAAC;IAgInD;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,iBAAiB,CACtB,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,wBAAwB,GAC/B,OAAO,CAAC,yBAAyB,CAAC;IAgErC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,mBAAmB,CACxB,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,IAAI,CAAC;IAuFhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,qBAAqB,CAC1B,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,6BAA6B,CAAC;IA6EzC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,6BAA6B,CAClC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,oCAAoC,GAC3C,OAAO,CAAC,IAAI,CAAC;IA2DhB;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,8BAA8B,CACnC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,qCAAqC,GAC5C,OAAO,CAAC,IAAI,CAAC;IA0DhB;;OAEG;YACW,aAAa;IA0B3B;;OAEG;YACW,uBAAuB;IA6BrC;;OAEG;YACW,cAAc;IA0B5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACG,8BAA8B,CACnC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,qCAAqC,GAC5C,OAAO,CAAC,sCAAsC,CAAC;IAsGlD;;OAEG;YACW,gBAAgB;CA0B9B"}
1
+ {"version":3,"file":"PrivateTestExecutions.d.ts","sourceRoot":"","sources":["../../../groups/Private/PrivateTestExecutions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AAEH,OAAO,KAAK,EACX,qBAAqB,EACrB,sCAAsC,EACtC,uCAAuC,EACvC,qCAAqC,EACrC,sCAAsC,EACtC,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,4BAA4B,EAC5B,6BAA6B,EAC7B,oCAAoC,EACpC,qCAAqC,EACrC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AA0D5C,qBAAa,qBAAsB,SAAQ,WAAW;IACrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,+BAA+B,CACpC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,sCAAsC,GAC7C,OAAO,CAAC,uCAAuC,CAAC;IAgInD;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,iBAAiB,CACtB,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,wBAAwB,GAC/B,OAAO,CAAC,yBAAyB,CAAC;IAgErC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,mBAAmB,CACxB,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,IAAI,CAAC;IAuFhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,qBAAqB,CAC1B,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,6BAA6B,CAAC;IA6EzC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,6BAA6B,CAClC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,oCAAoC,GAC3C,OAAO,CAAC,IAAI,CAAC;IA2DhB;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,8BAA8B,CACnC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,qCAAqC,GAC5C,OAAO,CAAC,IAAI,CAAC;IA0DhB;;OAEG;YACW,aAAa;IA0B3B;;OAEG;YACW,uBAAuB;IA6BrC;;OAEG;YACW,cAAc;IA0B5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACG,8BAA8B,CACnC,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,qCAAqC,GAC5C,OAAO,CAAC,sCAAsC,CAAC;IA0NlD;;OAEG;YACW,gBAAgB;CA0B9B"}
@@ -655,12 +655,98 @@ export class PrivateTestExecutions extends PrivateBase {
655
655
  const testCaseId = await this.getTestCaseIdForVersion(request.body.testCaseKey, request.body.version);
656
656
  // Step 2: Get test cycle ID from key
657
657
  const testCycleId = await this.getTestCycleId(request.body.testCycleKey);
658
- // Step 3: Get testRunItemId from private API
659
- const testRunItemId = await this.getTestRunItemId(credentials, {
660
- testCycleKey: request.body.testCycleKey,
661
- testCaseId,
662
- projectId: request.projectId,
663
- });
658
+ // Step 3: Check if test case is already in the cycle, if not add it
659
+ let testRunItemId;
660
+ try {
661
+ testRunItemId = await this.getTestRunItemId(credentials, {
662
+ testCycleKey: request.body.testCycleKey,
663
+ testCaseId,
664
+ projectId: request.projectId,
665
+ });
666
+ }
667
+ catch (error) {
668
+ // If test case not found in cycle, add it first
669
+ if (error instanceof NotFoundError) {
670
+ // Get current cycle items to determine next index
671
+ const cycleItems = await this.getTestCycleItems(credentials, {
672
+ testCycleKey: request.body.testCycleKey,
673
+ projectId: request.projectId,
674
+ });
675
+ // Determine next index (highest index + 1, or 0 if no items)
676
+ const nextIndex = cycleItems.testRunItems.length > 0
677
+ ? Math.max(...cycleItems.testRunItems.map((item) => item.index)) + 1
678
+ : 0;
679
+ // Prepare assignedTo - use from request if provided, otherwise from body.assignedToId
680
+ let assignedTo = request.assignedTo;
681
+ if (!assignedTo && request.body.assignedToId) {
682
+ // Note: assignedToId is an account ID, but assignedTo should be a user key
683
+ // For now, we'll use the account ID as-is and let the API handle it
684
+ assignedTo = request.body.assignedToId;
685
+ }
686
+ // Add test case to cycle using bulk save endpoint
687
+ const bulkSaveUrl = `${this.privateApiBaseUrl}/testrunitem/bulk/save`;
688
+ const bulkSaveHeaders = {
689
+ 'Content-Type': 'application/json',
690
+ authorization: `JWT ${contextJwt}`,
691
+ 'jira-project-id': String(request.projectId),
692
+ };
693
+ const bulkSaveBody = {
694
+ addedTestRunItems: [
695
+ {
696
+ index: nextIndex,
697
+ lastTestResult: {
698
+ testCaseId,
699
+ ...(assignedTo && { assignedTo }),
700
+ ...(request.iterationId && { iterationId: request.iterationId }),
701
+ ...(request.jiraVersionId && {
702
+ jiraVersionId: typeof request.jiraVersionId === 'string'
703
+ ? request.jiraVersionId
704
+ : String(request.jiraVersionId),
705
+ }),
706
+ },
707
+ },
708
+ ],
709
+ updatedTestRunItemsIndexes: cycleItems.testRunItems.map((item) => ({
710
+ id: item.id,
711
+ index: item.index,
712
+ })),
713
+ updatedTestRunItems: [],
714
+ deletedTestRunItems: [],
715
+ testRunId: testCycleId,
716
+ autoReorder: false,
717
+ };
718
+ const bulkSaveResponse = await fetch(bulkSaveUrl, {
719
+ method: 'PUT',
720
+ headers: bulkSaveHeaders,
721
+ body: JSON.stringify(bulkSaveBody),
722
+ });
723
+ if (!bulkSaveResponse.ok) {
724
+ if (bulkSaveResponse.status === 400) {
725
+ throw new BadRequestError('Invalid request parameters for adding test case to test cycle. Ensure test case version and cycle are valid.');
726
+ }
727
+ if (bulkSaveResponse.status === 401) {
728
+ throw new UnauthorizedError('Failed to authenticate. Please check your credentials.');
729
+ }
730
+ if (bulkSaveResponse.status === 403) {
731
+ throw new ForbiddenError('Insufficient permissions to add test case to test cycle.');
732
+ }
733
+ if (bulkSaveResponse.status === 404) {
734
+ throw new NotFoundError(`Test case '${request.body.testCaseKey}' (version ${request.body.version}) or test cycle '${request.body.testCycleKey}' not found.`);
735
+ }
736
+ throw new ServerError(`Failed to add test case to test cycle. Status: ${bulkSaveResponse.status}`, bulkSaveResponse.status, bulkSaveResponse.statusText);
737
+ }
738
+ // Now get the testRunItemId
739
+ testRunItemId = await this.getTestRunItemId(credentials, {
740
+ testCycleKey: request.body.testCycleKey,
741
+ testCaseId,
742
+ projectId: request.projectId,
743
+ });
744
+ }
745
+ else {
746
+ // Re-throw other errors
747
+ throw error;
748
+ }
749
+ }
664
750
  // Step 4: Create execution via private API
665
751
  const url = `${this.privateApiBaseUrl}/testresult`;
666
752
  const headers = {
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbaileysr/zephyr-managed-api",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Managed API wrapper for Zephyr Cloud REST API v2 - Comprehensive type-safe access to all Zephyr API endpoints for ScriptRunner Connect",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbaileysr/zephyr-managed-api",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "Managed API wrapper for Zephyr Cloud REST API v2 - Comprehensive type-safe access to all Zephyr API endpoints for ScriptRunner Connect",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",