@rbaileysr/zephyr-managed-api 1.2.0 → 1.2.8

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
@@ -1,606 +1,238 @@
1
- # Zephyr Managed API
1
+ # ScriptRunner Connect Managed API for Zephyr Scale
2
+ Managed API for Zephyr Scale Cloud is an API Client for Zephyr Scale Cloud by [Adaptavist](https://www.adaptavist.com/). You can read more about Managed APIs [here](https://docs.adaptavist.com/src/managed-apis).
2
3
 
3
- A comprehensive Managed API wrapper for Zephyr Cloud REST API v2, providing type-safe, hierarchical access to all Zephyr API endpoints.
4
-
5
- > **⚠️ Important: ScriptRunner Connect Runtime Only**
6
- >
7
- > This package is specifically designed for **ScriptRunner Connect's custom runtime** and will **NOT work in standard Node.js projects**. It uses web standards-based APIs (fetch, etc.) and ES modules, making it compatible with ScriptRunner Connect's runtime environment.
8
-
9
- ## Overview
10
-
11
- This Managed API wrapper provides a clean, type-safe interface to interact with the Zephyr Cloud API. It follows the same hierarchical pattern as other ScriptRunner Connect Managed APIs, making it easy to use and consistent with the platform's conventions.
12
-
13
- ## Features
14
-
15
- - **Type-Safe**: Full TypeScript support with IntelliSense
16
- - **Hierarchical Structure**: Organized by resource type (TestCase, TestCycle, TestPlan, etc.)
17
- - **Comprehensive Coverage**: Supports all Zephyr Cloud REST API v2 endpoints
18
- - **Error Handling**: Built-in error parsing and handling using Commons Core error types
19
- - **Pagination Support**: Both offset-based and cursor-based pagination
20
- - **Flexible Authentication**: Supports OAuth tokens and ScriptRunner Connect API Connections (base URL configured in Generic Connector)
21
- - **Custom Fields**: Full support for dynamic custom fields
22
- - **Web App Compatible**: Works seamlessly in ScriptRunner Connect web app
23
- - **Single Import**: Convenient default export for all utilities and types
4
+ This is [ScriptRunner Connect](https://scriptrunnerconnect.com) runtime specific version of the Managed API. This package is specifically designed for **ScriptRunner Connect's custom runtime** and will **NOT work in standard Node.js projects**. It uses web standards-based APIs (fetch, etc.) and ES modules, making it compatible with ScriptRunner Connect's runtime environment.
24
5
 
25
6
  ## Installation
26
7
 
27
- ### NPM Package
28
-
29
8
  ```bash
30
9
  npm install @rbaileysr/zephyr-managed-api
31
10
  ```
32
11
 
33
12
  **Important:** After installing via NPM, you must also add the package through ScriptRunner Connect's Package Manager in the web UI. The package will then be available in your workspace.
34
13
 
35
- ### ScriptRunner Connect Workspace Setup
36
-
37
- 1. **Add Package via Web UI:**
38
- - Go to Package Manager in ScriptRunner Connect web UI
39
- - Click "Add Package"
40
- - Enter: `@rbaileysr/zephyr-managed-api`
41
- - Click Add/Save
42
-
43
- 2. **Sync Workspace Files:**
44
- - Download latest workspace files from SFTP server
45
- - Or use `SFTP: Sync Remote → Local` if using VS Code + SFTP
46
-
47
- 3. **Install Dependencies:**
48
- ```bash
49
- npm install
50
- ```
51
-
52
- 4. **Use in Scripts:**
53
- ```typescript
54
- // Single import (recommended) - everything in one import
55
- import Zephyr from '@rbaileysr/zephyr-managed-api';
56
- import ZephyrApiConnection from '../api/zephyr';
57
-
58
- // Using API Connection (recommended for ScriptRunner Connect)
59
- // Base URL is configured in the Generic Connector
60
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
61
-
62
- // Access utilities and error types from the same import
63
- const pages = await Zephyr.getAllPages(...);
64
- const errorStrategy = new Zephyr.ErrorStrategyBuilder()...;
65
- ```
66
-
67
- **Alternative - Named Imports:**
68
- ```typescript
69
- // Named imports (if you prefer)
70
- import { createZephyrApi, getAllPages, ErrorStrategyBuilder } from '@rbaileysr/zephyr-managed-api';
71
- ```
72
-
73
- ## Usage
74
-
75
- ### Basic Examples
76
-
77
- #### Using API Connection (ScriptRunner Connect) - Single Import
78
-
79
- ```typescript
80
- // Single import for everything
81
- import Zephyr from '@rbaileysr/zephyr-managed-api';
82
- import ZephyrApiConnection from '../api/zephyr';
14
+ ## Constructing Managed API
83
15
 
84
- // Create API instance (base URL configured in Generic Connector)
85
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
86
-
87
- // Get a test case
88
- const testCase = await api.TestCase.getTestCase({ testCaseKey: 'PROJ-T1' });
89
- console.log(`Test case: ${testCase.name}`);
90
- ```
91
-
92
- #### Using API Connection - Named Imports
16
+ In ScriptRunner Connect a Managed API is constructed for you, but if you need to construct it manually, here's how you can do it:
93
17
 
18
+ **Using API Connection (recommended for ScriptRunner Connect):**
94
19
  ```typescript
95
- // Named imports (alternative)
96
20
  import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
97
21
  import ZephyrApiConnection from '../api/zephyr';
98
22
 
99
- const api = createZephyrApi(ZephyrApiConnection);
100
- const testCase = await api.TestCase.getTestCase({ testCaseKey: 'PROJ-T1' });
101
- ```
102
-
103
- #### Using OAuth Token
104
-
105
- ```typescript
106
- import Zephyr from '@rbaileysr/zephyr-managed-api';
107
-
108
- // OAuth token with full base URL (US region)
109
- const api = Zephyr.createZephyrApi(
110
- 'your-oauth-token-here',
111
- 'https://api.zephyrscale.smartbear.com/v2'
112
- );
113
-
114
- // OAuth token with full base URL (EU region)
115
- const apiEU = Zephyr.createZephyrApi(
116
- 'your-oauth-token-here',
117
- 'https://eu.api.zephyrscale.smartbear.com/v2'
118
- );
119
-
120
- // List test cases
121
- const testCases = await api.TestCase.listTestCases({
122
- projectKey: 'PROJ',
123
- maxResults: 10,
124
- startAt: 0
125
- });
126
- console.log(`Found ${testCases.values.length} test cases`);
127
- ```
128
-
129
- #### Create a Test Case
130
-
131
- ```typescript
132
- const testCase = await api.TestCase.createTestCase({
133
- body: {
134
- projectKey: 'PROJ',
135
- name: 'Login Test Case',
136
- objective: 'Verify user can login successfully',
137
- precondition: 'User account exists',
138
- priorityName: 'High',
139
- statusName: 'Draft',
140
- labels: ['automated', 'regression'],
141
- customFields: {
142
- 'Build Number': '2024.1',
143
- 'Release Date': '2024-01-15'
144
- }
145
- }
146
- });
147
- console.log(`Created test case: ${testCase.key}`);
148
- ```
149
-
150
- #### Create a Test Cycle
151
-
152
- ```typescript
153
- const testCycle = await api.TestCycle.createTestCycle({
154
- body: {
155
- projectKey: 'PROJ',
156
- name: 'Sprint 1 Regression',
157
- description: 'Regression tests for Sprint 1',
158
- plannedStartDate: '2024-01-15T09:00:00Z',
159
- plannedEndDate: '2024-01-22T17:00:00Z',
160
- statusName: 'In Progress',
161
- customFields: {
162
- 'Environment': 'Production'
163
- }
164
- }
165
- });
166
- console.log(`Created test cycle: ${testCycle.key}`);
167
- ```
168
-
169
- #### Create a Test Execution
170
-
171
- ```typescript
172
- const testExecution = await api.TestExecution.createTestExecution({
173
- body: {
174
- projectKey: 'PROJ',
175
- testCaseKey: 'PROJ-T1',
176
- testCycleKey: 'PROJ-R1',
177
- statusName: 'Pass',
178
- environmentName: 'Chrome Latest',
179
- executionTime: 120000, // 2 minutes in milliseconds
180
- comment: 'Test passed successfully'
181
- }
182
- });
183
- console.log(`Created test execution: ${testExecution.key || testExecution.id}`);
184
- ```
185
-
186
- #### Update a Test Case
187
-
188
- ```typescript
189
- // First, get the test case
190
- const testCase = await api.TestCase.getTestCase({ testCaseKey: 'PROJ-T1' });
191
-
192
- // Update it
193
- testCase.name = 'Updated Test Case Name';
194
- testCase.objective = 'Updated objective';
195
- testCase.labels = [...(testCase.labels || []), 'updated'];
196
-
197
- await api.TestCase.updateTestCase({
198
- testCaseKey: 'PROJ-T1',
199
- body: testCase
200
- });
201
- ```
202
-
203
- #### List with Filters and Pagination
204
-
205
- ```typescript
206
- // Offset-based pagination
207
- const testCases = await api.TestCase.listTestCases({
208
- projectKey: 'PROJ',
209
- folderId: 12345,
210
- maxResults: 50,
211
- startAt: 0
212
- });
213
-
214
- // Cursor-based pagination (for large datasets)
215
- const testCasesCursor = await api.TestCase.listTestCasesCursorPaginated({
216
- projectKey: 'PROJ',
217
- limit: 100,
218
- startAtId: 0
219
- });
220
- ```
221
-
222
- #### Create Links
223
-
224
- ```typescript
225
- // Link test case to Jira issue
226
- const issueLink = await api.TestCase.createTestCaseIssueLink({
227
- testCaseKey: 'PROJ-T1',
228
- body: {
229
- issueId: 12345
230
- }
231
- });
232
-
233
- // Link test case to web URL
234
- const webLink = await api.TestCase.createTestCaseWebLink({
235
- testCaseKey: 'PROJ-T1',
236
- body: {
237
- url: 'https://example.com/test-resource',
238
- description: 'External test resource'
239
- }
240
- });
241
- ```
242
-
243
- ## API Groups
244
-
245
- The Managed API is organized into the following groups:
246
-
247
- ### Project
248
- - `listProjects(options?)` - List all projects
249
- - `getProject(options)` - Get a specific project
250
-
251
- ### Status
252
- - `listStatuses(options)` - List all statuses
253
- - `getStatus(options)` - Get a specific status
254
- - `createStatus(request)` - Create a new status
255
- - `updateStatus(request)` - Update a status
256
-
257
- ### Priority
258
- - `listPriorities(options)` - List all priorities
259
- - `getPriority(options)` - Get a specific priority
260
- - `createPriority(request)` - Create a new priority
261
- - `updatePriority(request)` - Update a priority
262
-
263
- ### Environment
264
- - `listEnvironments(options)` - List all environments
265
- - `getEnvironment(options)` - Get a specific environment
266
- - `createEnvironment(request)` - Create a new environment
267
- - `updateEnvironment(request)` - Update an environment
268
-
269
- ### Folder
270
- - `listFolders(options)` - List all folders
271
- - `getFolder(options)` - Get a specific folder
272
- - `createFolder(request)` - Create a new folder
273
-
274
- ### TestCase
275
- - `listTestCases(options?)` - List all test cases
276
- - `listTestCasesCursorPaginated(options?)` - List test cases with cursor pagination
277
- - `getTestCase(options)` - Get a specific test case
278
- - `createTestCase(request)` - Create a new test case
279
- - `updateTestCase(request)` - Update a test case
280
- - `getTestCaseLinks(testCaseKey)` - Get links for a test case
281
- - `createTestCaseIssueLink(request)` - Create issue link
282
- - `createTestCaseWebLink(request)` - Create web link
283
- - `listTestCaseVersions(options)` - List test case versions
284
- - `getTestCaseVersion(options)` - Get a specific version
285
- - `getTestCaseTestScript(testCaseKey)` - Get test script
286
- - `createTestCaseTestScript(request)` - Create or update test script
287
- - `getTestCaseTestSteps(testCaseKey, options?)` - Get test steps
288
- - `createTestCaseTestSteps(request)` - Create test steps
289
-
290
- ### TestCycle
291
- - `listTestCycles(options?)` - List all test cycles
292
- - `getTestCycle(options)` - Get a specific test cycle
293
- - `createTestCycle(request)` - Create a new test cycle
294
- - `updateTestCycle(request)` - Update a test cycle
295
- - `getTestCycleLinks(testCycleIdOrKey)` - Get links for a test cycle
296
- - `createTestCycleIssueLink(request)` - Create issue link
297
- - `createTestCycleWebLink(request)` - Create web link
298
-
299
- ### TestPlan
300
- - `listTestPlans(options?)` - List all test plans
301
- - `getTestPlan(options)` - Get a specific test plan
302
- - `createTestPlan(request)` - Create a new test plan
303
- - `createTestPlanIssueLink(request)` - Create issue link
304
- - `createTestPlanWebLink(request)` - Create web link
305
- - `createTestPlanTestCycleLink(request)` - Link test cycle to test plan
306
-
307
- ### TestExecution
308
- - `listTestExecutions(options?)` - List all test executions
309
- - `listTestExecutionsNextgen(options?)` - List test executions with cursor pagination
310
- - `getTestExecution(options)` - Get a specific test execution
311
- - `createTestExecution(request)` - Create a new test execution
312
- - `updateTestExecution(request)` - Update a test execution
313
- - `getTestExecutionTestSteps(options)` - Get test steps for execution
314
- - `putTestExecutionTestSteps(request)` - Update test steps
315
- - `syncTestExecutionScript(request)` - Sync with test case script
316
- - `listTestExecutionLinks(testExecutionIdOrKey)` - Get links
317
- - `createTestExecutionIssueLink(request)` - Create issue link
318
-
319
- ### Link
320
- - `deleteLink(options)` - Delete a link (idempotent)
321
-
322
- ### IssueLink
323
- - `getIssueLinkTestCases(options)` - Get test cases linked to issue
324
- - `getIssueLinkTestCycles(options)` - Get test cycles linked to issue
325
- - `getIssueLinkTestPlans(options)` - Get test plans linked to issue
326
- - `getIssueLinkExecutions(options)` - Get test executions linked to issue
327
-
328
- ### Automation
329
- - `createCustomExecutions(request)` - Upload custom format results
330
- - `createCucumberExecutions(request)` - Upload Cucumber results
331
- - `createJUnitExecutions(request)` - Upload JUnit XML results
332
- - `retrieveBDDTestCases(options)` - Retrieve BDD feature files
333
-
334
- ### Private API ⚠️
335
- > **⚠️ WARNING: Private API Methods**
336
- >
337
- > The following methods use Zephyr's private/unofficial API endpoints that are:
338
- > - **Not officially supported** by SmartBear
339
- > - **Not part of the public API documentation**
340
- > - **Subject to change at any time** without notice
341
- > - **Not covered by Standard Support**
342
- >
343
- > Use these methods at your own risk. They may break with future Zephyr updates.
344
-
345
- - `getContextJwt(userEmail, apiToken, jiraInstanceUrl)` - Get Jira Context JWT token (required for private API calls)
346
- - `createCustomField(userEmail, apiToken, jiraInstanceUrl, category, request)` - Create custom fields for test cases, test plans, test runs, or test steps
347
- - `createTestCaseVersion(userEmail, apiToken, jiraInstanceUrl, request)` - Create a new test case version
348
- - `createTestCaseComment(userEmail, apiToken, jiraInstanceUrl, request)` - Create a comment on a test case
349
- - `getTestCaseAttachments(userEmail, apiToken, jiraInstanceUrl, request)` - Get all attachments for a test case
350
- - `downloadAttachment(userEmail, apiToken, jiraInstanceUrl, request)` - Download an attachment file into memory
351
- - `createAttachment(userEmail, apiToken, jiraInstanceUrl, request)` - Upload an attachment to a test case
352
-
353
- ## Authentication
354
-
355
- ### Using ScriptRunner Connect API Connection (Recommended)
356
-
357
- When using in ScriptRunner Connect, configure a Generic Connector with the full base URL in the web UI:
358
-
359
- **For US region:** `https://api.zephyrscale.smartbear.com/v2`
360
- **For EU region:** `https://eu.api.zephyrscale.smartbear.com/v2`
361
-
362
- Then use it in your script:
363
-
364
- ```typescript
365
- import Zephyr from '@rbaileysr/zephyr-managed-api';
366
- import ZephyrApiConnection from '../api/zephyr';
367
-
368
23
  // Base URL is configured in the Generic Connector
369
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
24
+ const api = createZephyrApi(ZephyrApiConnection);
370
25
  ```
371
26
 
372
- ### Using OAuth Token
373
-
374
- For local testing or when using OAuth tokens directly, provide the full base URL:
375
-
27
+ **Using OAuth Token:**
376
28
  ```typescript
377
- import Zephyr from '@rbaileysr/zephyr-managed-api';
29
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
378
30
 
379
31
  // US region
380
- const api = Zephyr.createZephyrApi(
32
+ const api = createZephyrApi(
381
33
  'your-oauth-token',
382
34
  'https://api.zephyrscale.smartbear.com/v2'
383
35
  );
384
36
 
385
37
  // EU region
386
- const apiEU = Zephyr.createZephyrApi(
38
+ const apiEU = createZephyrApi(
387
39
  'your-oauth-token',
388
40
  'https://eu.api.zephyrscale.smartbear.com/v2'
389
41
  );
390
42
  ```
391
43
 
392
- ## Private API ⚠️
393
-
394
- > **⚠️ WARNING: Private API Usage**
395
- >
396
- > The Private API methods use Zephyr's private/unofficial endpoints that are not officially supported by SmartBear. These endpoints may change or be removed at any time without notice and are not covered by Standard Support. Use these methods at your own risk.
397
-
398
- The Private API group provides access to functionality not available in the public Zephyr API, such as creating custom fields and test case versions. These methods require Jira user credentials (email and API token) rather than OAuth tokens.
399
-
400
- ### Authentication
401
-
402
- Private API methods use Jira Basic Authentication (email + API token) to retrieve a Context JWT token, which is then used to authenticate with Zephyr's private endpoints.
44
+ ## Supported API calls
45
+
46
+ - [fetch](https://docs.adaptavist.com/src/managed-apis/managed-api-abstractions)
47
+ - Project
48
+ - [listProjects](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listProjects)
49
+ - [getProject](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getProject)
50
+ - Status
51
+ - [listStatuses](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listStatuses)
52
+ - [getStatus](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getStatus)
53
+ - [createStatus](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createStatus)
54
+ - [updateStatus](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/updateStatus)
55
+ - Priority
56
+ - [listPriorities](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listPriorities)
57
+ - [getPriority](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getPriority)
58
+ - [createPriority](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createPriority)
59
+ - [updatePriority](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/updatePriority)
60
+ - Environment
61
+ - [listEnvironments](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listEnvironments)
62
+ - [getEnvironment](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getEnvironment)
63
+ - [createEnvironment](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createEnvironment)
64
+ - [updateEnvironment](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/updateEnvironment)
65
+ - Folder
66
+ - [listFolders](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listFolders)
67
+ - [getFolder](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getFolder)
68
+ - [createFolder](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createFolder)
69
+ - TestCase
70
+ - [listTestCases](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestCases)
71
+ - [listTestCasesCursorPaginated](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestCasesCursorPaginated)
72
+ - [getTestCase](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestCase)
73
+ - [createTestCase](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCase)
74
+ - [updateTestCase](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/updateTestCase)
75
+ - [getTestCaseLinks](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestCaseLinks)
76
+ - [createTestCaseIssueLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCaseIssueLink)
77
+ - [createTestCaseWebLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCaseWebLink)
78
+ - [listTestCaseVersions](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestCaseVersions)
79
+ - [getTestCaseVersion](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestCaseVersion)
80
+ - [getTestCaseTestScript](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestCaseTestScript)
81
+ - [createTestCaseTestScript](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCaseTestScript)
82
+ - [getTestCaseTestSteps](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestCaseTestSteps)
83
+ - [createTestCaseTestSteps](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCaseTestSteps)
84
+ - TestCycle
85
+ - [listTestCycles](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestCycles)
86
+ - [getTestCycle](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestCycle)
87
+ - [createTestCycle](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCycle)
88
+ - [updateTestCycle](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/updateTestCycle)
89
+ - [getTestCycleLinks](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestCycleLinks)
90
+ - [createTestCycleIssueLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCycleIssueLink)
91
+ - [createTestCycleWebLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestCycleWebLink)
92
+ - TestPlan
93
+ - [listTestPlans](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestPlans)
94
+ - [getTestPlan](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestPlan)
95
+ - [createTestPlan](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestPlan)
96
+ - [createTestPlanIssueLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestPlanIssueLink)
97
+ - [createTestPlanWebLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestPlanWebLink)
98
+ - [createTestPlanTestCycleLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestPlanTestCycleLink)
99
+ - TestExecution
100
+ - [listTestExecutions](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestExecutions)
101
+ - [listTestExecutionsNextgen](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestExecutionsNextgen)
102
+ - [getTestExecution](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestExecution)
103
+ - [createTestExecution](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestExecution)
104
+ - [updateTestExecution](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/updateTestExecution)
105
+ - [getTestExecutionTestSteps](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getTestExecutionTestSteps)
106
+ - [putTestExecutionTestSteps](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/putTestExecutionTestSteps)
107
+ - [syncTestExecutionScript](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/syncTestExecutionScript)
108
+ - [listTestExecutionLinks](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/listTestExecutionLinks)
109
+ - [createTestExecutionIssueLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createTestExecutionIssueLink)
110
+ - Link
111
+ - [deleteLink](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/deleteLink)
112
+ - IssueLink
113
+ - [getIssueLinkTestCases](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getIssueLinkTestCases)
114
+ - [getIssueLinkTestCycles](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getIssueLinkTestCycles)
115
+ - [getIssueLinkTestPlans](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getIssueLinkTestPlans)
116
+ - [getIssueLinkExecutions](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/getIssueLinkExecutions)
117
+ - Automation
118
+ - [createCustomExecutions](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createCustomExecutions)
119
+ - [createCucumberExecutions](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createCucumberExecutions)
120
+ - [createJUnitExecutions](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/createJUnitExecutions)
121
+ - [retrieveBDDTestCases](https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/#operation/retrieveBDDTestCases)
122
+ - Private ⚠️
123
+ > **⚠️ WARNING: Private API Methods**
124
+ >
125
+ > The following methods use Zephyr's private/unofficial API endpoints that are:
126
+ > - **Not officially supported** by SmartBear
127
+ > - **Not part of the public API documentation**
128
+ > - **Subject to change at any time** without notice
129
+ > - **Not covered by Standard Support**
130
+ >
131
+ > Use these methods at your own risk. They may break with future Zephyr updates.
132
+
133
+ - Authentication
134
+ - [getContextJwt] - Get Jira Context JWT token (required for all private API calls)
135
+ - Comments
136
+ - [getTestCaseComments] - Get all comments for a test case
137
+ - [getTestCycleComments] - Get all comments for a test cycle
138
+ - [getTestPlanComments] - Get all comments for a test plan
139
+ - [createTestCaseComment] - Create a comment on a test case
140
+ - [createTestCycleComment] - Create a comment on a test cycle
141
+ - [createTestPlanComment] - Create a comment on a test plan
142
+ - CustomFields
143
+ - [createCustomField] - Create custom fields for test cases, test plans, test runs, test steps, or test executions
144
+ - [getCustomFields] - Get all custom fields for test cases, test plans, test runs, test steps, or test executions
145
+ - Versions
146
+ - [createTestCaseVersion] - Create a new test case version
147
+ - Attachments
148
+ - [getTestCaseAttachments] - Get all attachments for a test case
149
+ - [downloadAttachment] - Download an attachment from a test case
150
+ - [createAttachment] - Upload an attachment to a test case
151
+ - [getTestStepAttachments] - Get all attachments for a test step
152
+ - [downloadTestStepAttachment] - Download an attachment from a test step
153
+ - [createTestStepAttachment] - Upload an attachment to a test step
154
+ - [getTestCycleAttachments] - Get all attachments for a test cycle
155
+ - [downloadTestCycleAttachment] - Download an attachment from a test cycle
156
+ - [createTestCycleAttachment] - Upload an attachment to a test cycle
157
+ - [getTestPlanAttachments] - Get all attachments for a test plan
158
+ - [downloadTestPlanAttachment] - Download an attachment from a test plan
159
+ - [createTestPlanAttachment] - Upload an attachment to a test plan
160
+ - [getTestExecutionAttachments] - Get all attachments for a test execution
161
+ - [downloadTestExecutionAttachment] - Download an attachment from a test execution
162
+ - [createTestExecutionAttachment] - Upload an attachment to a test execution
163
+ - [getTestExecutionStepAttachments] - Get all attachments for a test execution step
164
+ - [downloadTestExecutionStepAttachment] - Download an attachment from a test execution step
165
+ - [createTestExecutionStepAttachment] - Upload an attachment to a test execution step
166
+
167
+ ## Private API Authentication
168
+
169
+ Private API methods require Jira user credentials (email and API token) rather than OAuth tokens. These methods use Jira Basic Authentication to retrieve a Context JWT token, which is then used to authenticate with Zephyr's private endpoints.
403
170
 
404
171
  ### Get Context JWT
405
172
 
406
173
  The Context JWT is a short-lived token (15 minutes) required for all private API calls:
407
174
 
408
175
  ```typescript
409
- import Zephyr from '@rbaileysr/zephyr-managed-api';
176
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
410
177
  import ZephyrApiConnection from '../api/zephyr';
411
178
 
412
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
179
+ const api = createZephyrApi(ZephyrApiConnection);
180
+
181
+ // Define credentials once
182
+ const credentials = {
183
+ userEmail: 'user@example.com',
184
+ apiToken: 'jira-api-token',
185
+ jiraInstanceUrl: 'https://your-instance.atlassian.net'
186
+ };
413
187
 
414
188
  // Get Context JWT token
415
- const contextJwt = await api.Private.getContextJwt(
416
- 'user@example.com',
417
- 'jira-api-token',
418
- 'https://your-instance.atlassian.net'
419
- );
189
+ const contextJwt = await api.Private.Authentication.getContextJwt(credentials);
420
190
  ```
421
191
 
422
- ### Create Custom Fields
423
-
424
- Create custom fields for test cases, test plans, test runs, or test steps:
192
+ ### Example: Create Custom Field
425
193
 
426
194
  ```typescript
427
- // Create a basic custom field for test cases
428
- const customField = await api.Private.createCustomField(
429
- 'user@example.com',
430
- 'jira-api-token',
431
- 'https://your-instance.atlassian.net',
432
- 'TEST_CASE', // Category: TEST_CASE, TEST_PLAN, TEST_RUN, or TEST_STEP
195
+ // Create a custom field for test cases
196
+ const customField = await api.Private.CustomFields.createCustomField(
197
+ credentials,
198
+ 'TEST_CASE',
433
199
  {
434
200
  projectId: 10017,
435
201
  name: 'Build Number',
436
- type: 'SINGLE_LINE_TEXT', // CHECKBOX, NUMBER, DECIMAL, SINGLE_LINE_TEXT, MULTI_LINE_TEXT, SINGLE_CHOICE_SELECT_LIST, MULTI_CHOICE_SELECT_LIST, USER_LIST, DATE
202
+ type: 'SINGLE_LINE_TEXT',
437
203
  required: false,
438
204
  index: 4,
439
205
  category: 'TEST_CASE',
440
- options: [], // Only for SINGLE_CHOICE_SELECT_LIST or MULTI_CHOICE_SELECT_LIST
441
- archived: false
442
- }
443
- );
444
-
445
- // Create a custom field with options (select list)
446
- const selectField = await api.Private.createCustomField(
447
- 'user@example.com',
448
- 'jira-api-token',
449
- 'https://your-instance.atlassian.net',
450
- 'TEST_CASE',
451
- {
452
- projectId: 10017,
453
- name: 'Test Category',
454
- type: 'MULTI_CHOICE_SELECT_LIST',
455
- required: false,
456
- index: 5,
457
- category: 'TEST_CASE',
458
- options: [
459
- { index: 1, name: 'Smoke', archived: false },
460
- { index: 2, name: 'Regression', archived: false },
461
- { index: 3, name: 'Performance', archived: false }
462
- ],
463
206
  archived: false
464
207
  }
465
208
  );
466
209
  ```
467
210
 
468
- **Available Custom Field Types:**
469
- - `CHECKBOX` - Checkbox
470
- - `NUMBER` - Number
471
- - `DECIMAL` - Decimal number
472
- - `SINGLE_LINE_TEXT` - Single-line text
473
- - `MULTI_LINE_TEXT` - Multi-line text
474
- - `SINGLE_CHOICE_SELECT_LIST` - Single-choice select list
475
- - `MULTI_CHOICE_SELECT_LIST` - Multi-choice select list
476
- - `USER_LIST` - User picker
477
- - `DATE` - Date picker
478
-
479
- **Available Categories:**
480
- - `TEST_CASE` - Custom field for test cases
481
- - `TEST_PLAN` - Custom field for test plans
482
- - `TEST_RUN` - Custom field for test cycles (test runs)
483
- - `TEST_STEP` - Custom field for test steps
484
-
485
- ### Create Test Case Version
486
-
487
- Create a new version of an existing test case. **Note:** When a new version is created, the `testCaseId` changes for that test case.
211
+ ### Example: Create Test Case Version
488
212
 
489
213
  ```typescript
490
- // Create a new version (test case ID is looked up automatically from key)
491
- const newVersion = await api.Private.createTestCaseVersion(
492
- 'user@example.com',
493
- 'jira-api-token',
494
- 'https://your-instance.atlassian.net',
214
+ // Create a new version of an existing test case
215
+ const newVersion = await api.Private.Versions.createTestCaseVersion(
216
+ credentials,
495
217
  {
496
218
  testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
497
219
  projectId: 10017 // Numeric project ID
498
220
  }
499
221
  );
500
- // Returns: { id: 286693656, key: "ZEP-T18" }
501
- ```
502
-
503
- **Important Notes:**
504
- - The method accepts `testCaseKey` and automatically looks up the numeric ID
505
- - The `projectId` must be numeric, not the project key
506
- - If a new version already exists, the API will return a 409 Conflict error
507
- - The test case ID changes after creating a new version
508
-
509
- ### Create Test Case Comment
510
-
511
- Add a comment to an existing test case.
512
-
513
- ```typescript
514
- const comment = await api.Private.createTestCaseComment(
515
- 'user@example.com',
516
- 'jira-api-token',
517
- 'https://your-instance.atlassian.net',
518
- {
519
- testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
520
- projectId: 10233, // Numeric project ID
521
- body: 'This is a test comment', // Comment text
522
- createdBy: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
523
- }
524
- );
525
222
  ```
526
223
 
527
- ### Get Test Case Attachments
528
-
529
- Retrieve all attachment details for a test case, including signed S3 URLs for downloading.
224
+ ### Example: Upload Attachment
530
225
 
531
226
  ```typescript
532
- const attachments = await api.Private.getTestCaseAttachments(
533
- 'user@example.com',
534
- 'jira-api-token',
535
- 'https://your-instance.atlassian.net',
536
- {
537
- testCaseKey: 'PROJ-T1',
538
- projectId: 10233
539
- }
540
- );
541
-
542
- console.log(`Found ${attachments.attachments.length} attachments`);
543
- attachments.attachments.forEach(att => {
544
- console.log(`- ${att.name} (${att.fileSize} bytes, ${att.mimeType})`);
545
- console.log(` ID: ${att.id}`);
546
- console.log(` URL: ${att.url}`);
547
- });
548
- ```
549
-
550
- **Response Structure:**
551
- Each attachment includes:
552
- - `id` - Attachment UUID
553
- - `name` - File name
554
- - `mimeType` - MIME type (e.g., 'image/jpeg', 'application/pdf')
555
- - `fileSize` - File size in bytes
556
- - `url` - Signed S3 URL for downloading (expires after ~90 minutes)
557
- - `createdOn` - Creation timestamp
558
- - `userKey` - Atlassian account ID of the uploader
559
- - `s3Key` - S3 storage key
560
-
561
- ### Download Attachment
562
-
563
- Download an attachment file into memory. This method automatically gets a fresh signed URL and downloads the file.
227
+ // Upload an attachment to a test case
228
+ const file = new Blob(['file content'], { type: 'text/plain' });
564
229
 
565
- ```typescript
566
- const fileBlob = await api.Private.downloadAttachment(
567
- 'user@example.com',
568
- 'jira-api-token',
569
- 'https://your-instance.atlassian.net',
230
+ const attachment = await api.Private.Attachments.createAttachment(
231
+ credentials,
570
232
  {
571
233
  testCaseKey: 'PROJ-T1',
572
234
  projectId: 10233,
573
- attachmentId: 'c3f14125-638f-47f9-9211-12a9777c09e7' // Attachment UUID
574
- }
575
- );
576
-
577
- // Use the blob (e.g., save to Record Storage, upload elsewhere, etc.)
578
- console.log(`Downloaded file: ${fileBlob.size} bytes, type: ${fileBlob.type}`);
579
-
580
- // Example: Convert to ArrayBuffer if needed
581
- const arrayBuffer = await fileBlob.arrayBuffer();
582
- ```
583
-
584
- **Important Notes:**
585
- - The method automatically gets a fresh signed URL to ensure it hasn't expired
586
- - Returns a `Blob` object that can be used directly or converted to `ArrayBuffer`
587
- - The signed URLs from `getTestCaseAttachments` expire after ~90 minutes, but `downloadAttachment` always gets a fresh URL
588
-
589
- ### Upload Attachment
590
-
591
- Upload a file attachment to a test case.
592
-
593
- ```typescript
594
- const file = new Blob(['file content'], { type: 'text/plain' });
595
-
596
- const attachment = await api.Private.createAttachment(
597
- 'user@example.com',
598
- 'jira-api-token',
599
- 'https://your-instance.atlassian.net',
600
- {
601
- testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
602
- projectId: 10233, // Numeric project ID
603
- file: file, // Blob or ArrayBuffer
235
+ file: file,
604
236
  fileName: 'test-file.txt',
605
237
  userAccountId: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
606
238
  }
@@ -608,372 +240,77 @@ const attachment = await api.Private.createAttachment(
608
240
  ```
609
241
 
610
242
  **Important Notes:**
611
- - The method handles the complete upload flow: getting S3 credentials, uploading to S3, and saving metadata
612
- - Supports both `Blob` and `ArrayBuffer` file types
613
- - MIME type is automatically detected from file name extension
614
-
615
- ### Error Handling for Private API
243
+ - Private API methods require a `PrivateApiCredentials` object with `userEmail`, `apiToken`, and `jiraInstanceUrl`
244
+ - The Context JWT token expires after 15 minutes and must be retrieved for each private API call
245
+ - All private API methods automatically handle Context JWT retrieval internally
246
+ - Methods that accept keys (like `testCaseKey`) automatically look up numeric IDs when needed
616
247
 
617
- Private API methods use the same error types as the public API:
248
+ ## Contact
618
249
 
619
- ```typescript
620
- try {
621
- await api.Private.createCustomField(...);
622
- } catch (error) {
623
- if (error instanceof Zephyr.BadRequestError) {
624
- console.log('Invalid request parameters');
625
- } else if (error instanceof Zephyr.UnauthorizedError) {
626
- console.log('Authentication failed - check your credentials');
627
- } else if (error instanceof Zephyr.ForbiddenError) {
628
- console.log('Insufficient permissions');
629
- } else if (error instanceof Zephyr.NotFoundError) {
630
- console.log('Resource not found');
631
- } else if (error instanceof Zephyr.ServerError) {
632
- if (error.status === 409) {
633
- console.log('Conflict - version already exists');
634
- }
635
- }
636
- }
637
- ```
250
+ Feel free to drop ideas, suggestions or improvements into our [Community hub](https://loop.scriptrunnerhq.com/c/integration-forum).
638
251
 
639
- ## Custom Fields
640
-
641
- Custom fields are supported as flexible key-value pairs:
642
-
643
- ```typescript
644
- const customFields = {
645
- 'Build Number': 20,
646
- 'Release Date': '2024-01-15',
647
- 'Pre-Condition(s)': 'User should have logged in.<br>User should have navigated to the panel.',
648
- 'Implemented': false,
649
- 'Category': ['Performance', 'Regression'],
650
- 'Tester': 'user-account-id-here'
651
- };
652
-
653
- await api.TestCase.createTestCase({
654
- body: {
655
- projectKey: 'PROJ',
656
- name: 'Test Case',
657
- customFields: customFields
658
- }
659
- });
660
- ```
661
-
662
- **Note**:
663
- - Multi-line text fields support HTML with `<br>` tags
664
- - Dates should be in format `yyyy-MM-dd`
665
- - Users should have values of Jira User Account IDs
666
- - Custom field types are defined in your Zephyr project configuration
667
-
668
- ## Error Handling
669
-
670
- The API uses Commons Core-compatible error types for consistent error handling. All API methods automatically retry on rate limiting (HTTP 429) with exponential backoff.
671
-
672
- ### Error Types
673
-
674
- ```typescript
675
- // Single import for everything
676
- import Zephyr from '@rbaileysr/zephyr-managed-api';
677
- import ZephyrApiConnection from '../api/zephyr';
678
-
679
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
680
-
681
- try {
682
- const testCase = await api.TestCase.getTestCase({ testCaseKey: 'INVALID-T1' });
683
- } catch (error) {
684
- if (error instanceof Zephyr.NotFoundError) {
685
- console.log('Test case not found');
686
- } else if (error instanceof Zephyr.BadRequestError) {
687
- console.log('Invalid request');
688
- } else if (error instanceof Zephyr.TooManyRequestsError) {
689
- console.log('Rate limited - this should have been retried automatically');
690
- } else if (error instanceof Zephyr.HttpError) {
691
- console.log(`HTTP error: ${error.message}`);
692
- }
693
- }
694
- ```
695
-
696
- **Alternative - Named Imports:**
697
- ```typescript
698
- import {
699
- createZephyrApi,
700
- BadRequestError,
701
- UnauthorizedError,
702
- ForbiddenError,
703
- NotFoundError,
704
- TooManyRequestsError,
705
- ServerError,
706
- HttpError,
707
- UnexpectedError
708
- } from '@rbaileysr/zephyr-managed-api';
709
-
710
- // Use named imports as before
711
- ```
712
-
713
- ### Automatic Rate Limiting Handling
714
-
715
- All API methods automatically handle rate limiting (HTTP 429) with:
716
-
717
- - **Exponential Backoff**: Starts at 1 second, doubles with each retry
718
- - **Retry-After Header Support**: Respects `Retry-After` header when present
719
- - **Configurable Retries**: Defaults to 5 retries, max delay of 60 seconds
720
- - **Transparent Operation**: Retries happen automatically - no code changes needed
721
-
722
- **Default Retry Configuration:**
723
- - Maximum retries: 5
724
- - Initial delay: 1 second
725
- - Maximum delay: 60 seconds
726
- - Backoff multiplier: 2x
727
-
728
- **Example:**
729
- ```typescript
730
- // This call will automatically retry on 429 errors
731
- // You don't need to handle rate limiting manually
732
- const testCases = await api.TestCase.listTestCases({ projectKey: 'PROJ' });
733
- ```
734
-
735
- If rate limiting occurs:
736
- 1. The API waits (using Retry-After header if present, otherwise exponential backoff)
737
- 2. Retries the request automatically
738
- 3. Repeats up to 5 times
739
- 4. Only throws `TooManyRequestsError` if all retries are exhausted
740
-
741
- ### Error Strategy Support
742
-
743
- For advanced error handling, you can provide an `errorStrategy` parameter to customize how errors are handled:
744
-
745
- ```typescript
746
- import Zephyr from '@rbaileysr/zephyr-managed-api';
747
- import ZephyrApiConnection from '../api/zephyr';
748
-
749
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
750
-
751
- // Return null instead of throwing on 404
752
- const testCase = await api.TestCase.getTestCase(
753
- { testCaseKey: 'PROJ-T1' },
754
- {
755
- handleHttp404Error: () => ({ type: 'return', value: null })
756
- }
757
- );
758
-
759
- // Using ErrorStrategyBuilder for cleaner syntax
760
- const errorStrategy = new Zephyr.ErrorStrategyBuilder<TestCase | null>()
761
- .http404Error(() => ({ type: 'return', value: null }))
762
- .retryOnRateLimiting(10) // Retry up to 10 times on rate limiting
763
- .http500Error(() => Zephyr.retry(5000)) // Retry server errors with 5s delay
764
- .build();
765
-
766
- const testCase2 = await api.TestCase.getTestCase(
767
- { testCaseKey: 'PROJ-T2' },
768
- errorStrategy
769
- );
770
- ```
771
-
772
- **Available Error Strategy Handlers:**
773
- - `handleHttp400Error` - Handle 400 Bad Request
774
- - `handleHttp401Error` - Handle 401 Unauthorized
775
- - `handleHttp403Error` - Handle 403 Forbidden
776
- - `handleHttp404Error` - Handle 404 Not Found
777
- - `handleHttp429Error` - Handle 429 Too Many Requests (receives retryCount)
778
- - `handleHttp500Error` - Handle 500+ Server Errors
779
- - `handleHttpError` - Handle any HTTP error (fallback)
780
-
781
- **Error Strategy Actions:**
782
- - `retry(delay)` - Retry the request after the specified delay (milliseconds)
783
- - `continuePropagation()` - Let the error propagate normally (default)
784
- - `{ type: 'return', value: T }` - Return a specific value instead of throwing
785
-
786
- ### Error Type Reference
787
-
788
- | Error Type | HTTP Status | Description |
789
- |------------|-------------|-------------|
790
- | `BadRequestError` | 400 | Invalid request parameters |
791
- | `UnauthorizedError` | 401 | Authentication required or invalid |
792
- | `ForbiddenError` | 403 | Insufficient permissions |
793
- | `NotFoundError` | 404 | Resource not found |
794
- | `TooManyRequestsError` | 429 | Rate limit exceeded (after retries) |
795
- | `ServerError` | 500+ | Server-side error |
796
- | `HttpError` | Other | Generic HTTP error |
797
- | `UnexpectedError` | N/A | Network or parsing errors |
798
-
799
- ## Pagination
800
-
801
- ### Manual Pagination
802
-
803
- #### Offset-Based Pagination
804
-
805
- ```typescript
806
- const testCases = await api.TestCase.listTestCases({
807
- projectKey: 'PROJ',
808
- maxResults: 50,
809
- startAt: 0
810
- });
811
-
812
- // Check if more results available
813
- if (!testCases.isLast) {
814
- const nextPage = await api.TestCase.listTestCases({
815
- projectKey: 'PROJ',
816
- maxResults: 50,
817
- startAt: testCases.startAt + testCases.maxResults
818
- });
819
- }
820
- ```
821
-
822
- #### Cursor-Based Pagination
823
-
824
- ```typescript
825
- const testCases = await api.TestCase.listTestCasesCursorPaginated({
826
- projectKey: 'PROJ',
827
- limit: 100,
828
- startAtId: 0
829
- });
830
-
831
- // Get next page
832
- if (testCases.nextStartAtId !== null) {
833
- const nextPage = await api.TestCase.listTestCasesCursorPaginated({
834
- projectKey: 'PROJ',
835
- limit: 100,
836
- startAtId: testCases.nextStartAtId
837
- });
838
- }
839
- ```
840
-
841
- ### Automatic Pagination with `getAllPages()`
842
-
843
- For convenience, use `getAllPages()` to automatically fetch all pages:
844
-
845
- #### Offset-Based Pagination
846
-
847
- ```typescript
848
- import Zephyr from '@rbaileysr/zephyr-managed-api';
849
- import ZephyrApiConnection from '../api/zephyr';
850
-
851
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
852
-
853
- // Automatically fetches all pages
854
- const allTestCases = await Zephyr.getAllPages(
855
- (startAt, maxResults) => api.TestCase.listTestCases({
856
- projectKey: 'PROJ',
857
- startAt,
858
- maxResults
859
- }),
860
- { maxResults: 50 } // Optional: page size
861
- );
862
-
863
- // allTestCases is an array of all TestCase objects from all pages
864
- console.log(`Found ${allTestCases.length} test cases`);
865
- ```
866
-
867
- #### Cursor-Based Pagination
868
-
869
- ```typescript
870
- import Zephyr from '@rbaileysr/zephyr-managed-api';
871
- import ZephyrApiConnection from '../api/zephyr';
872
-
873
- const api = Zephyr.createZephyrApi(ZephyrApiConnection);
874
-
875
- // Automatically fetches all pages
876
- const allTestCases = await Zephyr.getAllPagesCursor(
877
- (startAtId, limit) => api.TestCase.listTestCasesCursorPaginated({
878
- projectKey: 'PROJ',
879
- startAtId,
880
- limit
881
- }),
882
- { limit: 100 } // Optional: page size
883
- );
884
-
885
- // allTestCases is an array of all TestCase objects from all pages
886
- console.log(`Found ${allTestCases.length} test cases`);
887
- ```
888
-
889
- **Note**: `getAllPages()` and `getAllPagesCursor()` automatically handle pagination and will make multiple API calls as needed. Be mindful of rate limits when fetching large datasets.
890
-
891
- ## API Documentation
252
+ ## Changelog
892
253
 
893
- All API methods include comprehensive JSDoc comments with:
894
- - Detailed descriptions of what each endpoint does
895
- - Parameter documentation with types and requirements
896
- - Return type documentation
897
- - Links to official Zephyr API documentation
254
+ ### 1.2.8
898
255
 
899
- When using the package in ScriptRunner Connect, IntelliSense will display these descriptions and links in the code editor.
256
+ - **Added**: Attachment support for test steps, test executions, and test execution steps
257
+ - **Changed**: Updated `PrivateBase` to include `TestExecutionGroup` for test execution key-to-ID lookups
900
258
 
901
- ## Type Definitions
259
+ ### 1.2.7
902
260
 
903
- All TypeScript types are exported from the main module:
261
+ - **Added**: Attachment support for test cycles and test plans
904
262
 
905
- ```typescript
906
- import type {
907
- TestCase,
908
- TestCycle,
909
- TestExecution,
910
- TestPlan,
911
- CustomFields,
912
- ZephyrApiConnection,
913
- ErrorStrategy,
914
- ErrorStrategyBuilder
915
- } from '@rbaileysr/zephyr-managed-api';
916
- ```
263
+ ### 1.2.6
917
264
 
918
- ## All Group
265
+ - **Added**: `createTestCycleComment()` and `createTestPlanComment()` methods
266
+ - **Changed**: Private API reorganized into sub-groups for better organization
919
267
 
920
- For programmatic access to all methods, use the `All` group:
268
+ ### 1.2.5
921
269
 
922
- ```typescript
923
- // Access all methods through the All group
924
- const testCase = await Zephyr.All.getTestCase({ testCaseKey: 'PROJ-T1' });
925
- const testCycle = await Zephyr.All.createTestCycle({ body: { ... } });
926
- ```
270
+ - **Added**: `getTestPlanComments()` method
271
+ - **Changed**: Private API reorganized into sub-groups (Authentication, Comments, CustomFields, Versions, Attachments)
927
272
 
928
- The `All` group provides a single point of access to all API methods across all resource groups, useful for dynamic method invocation or when you need to iterate over all available methods.
273
+ ### 1.2.4
929
274
 
930
- ## License
275
+ - **Added**: `getTestCaseComments()` and `getTestCycleComments()` methods
931
276
 
932
- UNLICENSED - Copyright Adaptavist 2025 (c) All rights reserved
277
+ ### 1.2.3
933
278
 
934
- ## Support
279
+ - **Changed**: All private API methods now accept a single `PrivateApiCredentials` interface instead of three separate parameters
935
280
 
936
- For issues, questions, or contributions, please refer to the project repository on GitHub.
281
+ ### 1.2.2
937
282
 
938
- ## Links
283
+ - **Added**: `getCustomFields()` method for retrieving custom fields
284
+ - **Added**: Support for `TEST_EXECUTION` category in custom field operations
939
285
 
940
- - **NPM Package**: https://www.npmjs.com/package/@rbaileysr/zephyr-managed-api
941
- - **Zephyr API Documentation**: https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/
942
- - **ScriptRunner Connect Documentation**: https://docs.adaptavist.com/src/latest/
286
+ ### 1.2.1
943
287
 
944
- ## Changelog
288
+ - **Fixed**: UUID generation for attachment uploads - replaced `crypto.randomUUID()` with custom implementation compatible with ScriptRunner Connect runtime
945
289
 
946
- ### 1.1.0
290
+ ### 1.2.0
947
291
 
948
292
  - **Added**: Private API group with support for unofficial Zephyr endpoints
949
- - `getContextJwt()` - Retrieve Jira Context JWT token for private API authentication
950
- - `createCustomField()` - Create custom fields for test cases, test plans, test runs, and test steps
951
- - `createTestCaseVersion()` - Create new test case versions (now accepts testCaseKey and looks up ID automatically)
293
+ - `getContextJwt()` - Retrieve Jira Context JWT token
294
+ - `createCustomField()` - Create custom fields for test cases, test plans, test runs, test steps, and test executions
295
+ - `createTestCaseVersion()` - Create new test case versions
952
296
  - `createTestCaseComment()` - Create comments on test cases
953
297
  - `getTestCaseAttachments()` - Get all attachment details for a test case
954
- - `downloadAttachment()` - Download attachment files into memory with automatic fresh URL retrieval
298
+ - `downloadAttachment()` - Download attachment files into memory
955
299
  - `createAttachment()` - Upload file attachments to test cases
956
- - **Added**: Type definitions for private API requests and responses
957
- - **Changed**: `createTestCaseVersion()` now uses interface structure and automatically looks up test case ID from key
958
- - **Warning**: Private API methods are not officially supported and may change without notice
959
300
 
960
301
  ### 1.0.1
961
302
 
962
- - **Added**: Comprehensive JSDoc comments with API endpoint descriptions and links to official documentation
963
- - **Added**: Single import option via default export for convenient usage
303
+ - **Added**: Comprehensive JSDoc comments with API endpoint descriptions
304
+ - **Added**: Single import option via default export
964
305
  - **Changed**: Removed `region` parameter from `createZephyrApi` - base URL now configured in Generic Connector
965
- - **Improved**: Error handling to support both `BadRequestError` and `NotFoundError` in test examples
966
- - **Improved**: Type safety and IntelliSense support throughout the API
967
306
 
968
307
  ### 1.0.0
969
308
 
970
309
  - **Initial Release**: Complete Managed API wrapper for Zephyr Cloud REST API v2
971
- - **Added**: Full support for all Zephyr API endpoints (Test Cases, Test Cycles, Test Plans, Test Executions, etc.)
972
- - **Added**: Type-safe TypeScript definitions for all API operations
310
+ - **Added**: Full support for all Zephyr API endpoints
311
+ - **Added**: Type-safe TypeScript definitions
973
312
  - **Added**: Hierarchical API structure matching ScriptRunner Connect conventions
974
313
  - **Added**: Automatic rate limiting retry with exponential backoff
975
314
  - **Added**: Support for both API Connection and OAuth token authentication
976
- - **Added**: Pagination helpers (`getAllPages`, `getAllPagesCursor`)
977
- - **Added**: Error strategy builder for advanced error handling
978
- - **Added**: Comprehensive error types compatible with Commons Core
979
315
 
316
+ Copyright Adaptavist 2025 (c) All rights reserved