@rbaileysr/zephyr-managed-api 1.0.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.
Files changed (56) hide show
  1. package/README.md +618 -0
  2. package/dist/error-strategy.d.ts +69 -0
  3. package/dist/error-strategy.d.ts.map +1 -0
  4. package/dist/error-strategy.js +125 -0
  5. package/dist/groups/All.d.ts +90 -0
  6. package/dist/groups/All.d.ts.map +1 -0
  7. package/dist/groups/All.js +236 -0
  8. package/dist/groups/Automation.d.ts +75 -0
  9. package/dist/groups/Automation.d.ts.map +1 -0
  10. package/dist/groups/Automation.js +133 -0
  11. package/dist/groups/Environment.d.ts +73 -0
  12. package/dist/groups/Environment.d.ts.map +1 -0
  13. package/dist/groups/Environment.js +93 -0
  14. package/dist/groups/Folder.d.ts +55 -0
  15. package/dist/groups/Folder.d.ts.map +1 -0
  16. package/dist/groups/Folder.js +68 -0
  17. package/dist/groups/IssueLink.d.ts +59 -0
  18. package/dist/groups/IssueLink.d.ts.map +1 -0
  19. package/dist/groups/IssueLink.js +70 -0
  20. package/dist/groups/Link.d.ts +23 -0
  21. package/dist/groups/Link.d.ts.map +1 -0
  22. package/dist/groups/Link.js +34 -0
  23. package/dist/groups/Priority.d.ts +77 -0
  24. package/dist/groups/Priority.d.ts.map +1 -0
  25. package/dist/groups/Priority.js +97 -0
  26. package/dist/groups/Project.d.ts +36 -0
  27. package/dist/groups/Project.d.ts.map +1 -0
  28. package/dist/groups/Project.js +42 -0
  29. package/dist/groups/Status.d.ts +82 -0
  30. package/dist/groups/Status.d.ts.map +1 -0
  31. package/dist/groups/Status.js +102 -0
  32. package/dist/groups/TestCase.d.ts +254 -0
  33. package/dist/groups/TestCase.d.ts.map +1 -0
  34. package/dist/groups/TestCase.js +327 -0
  35. package/dist/groups/TestCycle.d.ts +127 -0
  36. package/dist/groups/TestCycle.d.ts.map +1 -0
  37. package/dist/groups/TestCycle.js +166 -0
  38. package/dist/groups/TestExecution.d.ts +176 -0
  39. package/dist/groups/TestExecution.d.ts.map +1 -0
  40. package/dist/groups/TestExecution.js +239 -0
  41. package/dist/groups/TestPlan.d.ts +103 -0
  42. package/dist/groups/TestPlan.d.ts.map +1 -0
  43. package/dist/groups/TestPlan.js +137 -0
  44. package/dist/index.d.ts +119 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +124 -0
  47. package/dist/types.d.ts +1353 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +7 -0
  50. package/dist/utils-api-call.d.ts +22 -0
  51. package/dist/utils-api-call.d.ts.map +1 -0
  52. package/dist/utils-api-call.js +80 -0
  53. package/dist/utils.d.ts +144 -0
  54. package/dist/utils.d.ts.map +1 -0
  55. package/dist/utils.js +432 -0
  56. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,618 @@
1
+ # Zephyr Managed API
2
+
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
+ - **Region Support**: Configurable US and EU regions
21
+ - **Flexible Authentication**: Supports OAuth tokens and ScriptRunner Connect API Connections
22
+ - **Custom Fields**: Full support for dynamic custom fields
23
+ - **Web App Compatible**: Works seamlessly in ScriptRunner Connect web app
24
+ - **JSDoc Documentation**: All methods include descriptions and links to official API documentation
25
+
26
+ ## Installation
27
+
28
+ ### NPM Package
29
+
30
+ ```bash
31
+ npm install @rbaileysr/zephyr-managed-api
32
+ ```
33
+
34
+ **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.
35
+
36
+ ### ScriptRunner Connect Workspace Setup
37
+
38
+ 1. **Add Package via Web UI:**
39
+ - Go to Package Manager in ScriptRunner Connect web UI
40
+ - Click "Add Package"
41
+ - Enter: `@rbaileysr/zephyr-managed-api`
42
+ - Click Add/Save
43
+
44
+ 2. **Sync Workspace Files:**
45
+ - Download latest workspace files from SFTP server
46
+ - Or use `SFTP: Sync Remote → Local` if using VS Code + SFTP
47
+
48
+ 3. **Install Dependencies:**
49
+ ```bash
50
+ npm install
51
+ ```
52
+
53
+ 4. **Use in Scripts:**
54
+ ```typescript
55
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
56
+ import ZephyrApiConnection from '../api/zephyr';
57
+
58
+ // Using API Connection (recommended for ScriptRunner Connect)
59
+ const Zephyr = createZephyrApi(ZephyrApiConnection, 'us');
60
+ ```
61
+
62
+ ## Usage
63
+
64
+ ### Basic Examples
65
+
66
+ #### Using API Connection (ScriptRunner Connect)
67
+
68
+ ```typescript
69
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
70
+ import ZephyrApiConnection from '../api/zephyr';
71
+
72
+ const Zephyr = createZephyrApi(ZephyrApiConnection, 'us');
73
+
74
+ // Get a test case
75
+ const testCase = await Zephyr.TestCase.getTestCase({ testCaseKey: 'PROJ-T1' });
76
+ console.log(`Test case: ${testCase.name}`);
77
+ ```
78
+
79
+ #### Using OAuth Token
80
+
81
+ ```typescript
82
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
83
+
84
+ const oauthToken = 'your-oauth-token-here';
85
+ const Zephyr = createZephyrApi(oauthToken, 'us');
86
+
87
+ // List test cases
88
+ const testCases = await Zephyr.TestCase.listTestCases({
89
+ projectKey: 'PROJ',
90
+ maxResults: 10,
91
+ startAt: 0
92
+ });
93
+ console.log(`Found ${testCases.values.length} test cases`);
94
+ ```
95
+
96
+ #### Create a Test Case
97
+
98
+ ```typescript
99
+ const testCase = await Zephyr.TestCase.createTestCase({
100
+ body: {
101
+ projectKey: 'PROJ',
102
+ name: 'Login Test Case',
103
+ objective: 'Verify user can login successfully',
104
+ precondition: 'User account exists',
105
+ priorityName: 'High',
106
+ statusName: 'Draft',
107
+ labels: ['automated', 'regression'],
108
+ customFields: {
109
+ 'Build Number': '2024.1',
110
+ 'Release Date': '2024-01-15'
111
+ }
112
+ }
113
+ });
114
+ console.log(`Created test case: ${testCase.key}`);
115
+ ```
116
+
117
+ #### Create a Test Cycle
118
+
119
+ ```typescript
120
+ const testCycle = await Zephyr.TestCycle.createTestCycle({
121
+ body: {
122
+ projectKey: 'PROJ',
123
+ name: 'Sprint 1 Regression',
124
+ description: 'Regression tests for Sprint 1',
125
+ plannedStartDate: '2024-01-15T09:00:00Z',
126
+ plannedEndDate: '2024-01-22T17:00:00Z',
127
+ statusName: 'In Progress',
128
+ customFields: {
129
+ 'Environment': 'Production'
130
+ }
131
+ }
132
+ });
133
+ console.log(`Created test cycle: ${testCycle.key}`);
134
+ ```
135
+
136
+ #### Create a Test Execution
137
+
138
+ ```typescript
139
+ const testExecution = await Zephyr.TestExecution.createTestExecution({
140
+ body: {
141
+ projectKey: 'PROJ',
142
+ testCaseKey: 'PROJ-T1',
143
+ testCycleKey: 'PROJ-R1',
144
+ statusName: 'Pass',
145
+ environmentName: 'Chrome Latest',
146
+ executionTime: 120000, // 2 minutes in milliseconds
147
+ comment: 'Test passed successfully'
148
+ }
149
+ });
150
+ console.log(`Created test execution: ${testExecution.key || testExecution.id}`);
151
+ ```
152
+
153
+ #### Update a Test Case
154
+
155
+ ```typescript
156
+ // First, get the test case
157
+ const testCase = await Zephyr.TestCase.getTestCase({ testCaseKey: 'PROJ-T1' });
158
+
159
+ // Update it
160
+ await Zephyr.TestCase.updateTestCase({
161
+ testCaseKey: 'PROJ-T1',
162
+ body: {
163
+ name: 'Updated Test Case Name',
164
+ objective: 'Updated objective',
165
+ labels: [...(testCase.labels || []), 'updated']
166
+ }
167
+ });
168
+ ```
169
+
170
+ #### List with Filters and Pagination
171
+
172
+ ```typescript
173
+ // Offset-based pagination
174
+ const testCases = await Zephyr.TestCase.listTestCases({
175
+ projectKey: 'PROJ',
176
+ folderId: 12345,
177
+ maxResults: 50,
178
+ startAt: 0
179
+ });
180
+
181
+ // Cursor-based pagination (for large datasets)
182
+ const testCasesCursor = await Zephyr.TestCase.listTestCasesCursorPaginated({
183
+ projectKey: 'PROJ',
184
+ limit: 100,
185
+ startAtId: 0
186
+ });
187
+ ```
188
+
189
+ #### Create Links
190
+
191
+ ```typescript
192
+ // Link test case to Jira issue
193
+ const issueLink = await Zephyr.TestCase.createTestCaseIssueLink({
194
+ testCaseKey: 'PROJ-T1',
195
+ body: {
196
+ issueId: 12345
197
+ }
198
+ });
199
+
200
+ // Link test case to web URL
201
+ const webLink = await Zephyr.TestCase.createTestCaseWebLink({
202
+ testCaseKey: 'PROJ-T1',
203
+ body: {
204
+ url: 'https://example.com/test-resource',
205
+ description: 'External test resource'
206
+ }
207
+ });
208
+ ```
209
+
210
+ ## API Groups
211
+
212
+ The Managed API is organized into the following groups:
213
+
214
+ ### Project
215
+ - `listProjects(options?)` - List all projects
216
+ - `getProject(options)` - Get a specific project
217
+
218
+ ### Status
219
+ - `listStatuses(options)` - List all statuses
220
+ - `getStatus(options)` - Get a specific status
221
+ - `createStatus(request)` - Create a new status
222
+ - `updateStatus(request)` - Update a status
223
+
224
+ ### Priority
225
+ - `listPriorities(options)` - List all priorities
226
+ - `getPriority(options)` - Get a specific priority
227
+ - `createPriority(request)` - Create a new priority
228
+ - `updatePriority(request)` - Update a priority
229
+
230
+ ### Environment
231
+ - `listEnvironments(options)` - List all environments
232
+ - `getEnvironment(options)` - Get a specific environment
233
+ - `createEnvironment(request)` - Create a new environment
234
+ - `updateEnvironment(request)` - Update an environment
235
+
236
+ ### Folder
237
+ - `listFolders(options)` - List all folders
238
+ - `getFolder(options)` - Get a specific folder
239
+ - `createFolder(request)` - Create a new folder
240
+
241
+ ### TestCase
242
+ - `listTestCases(options?)` - List all test cases
243
+ - `listTestCasesCursorPaginated(options?)` - List test cases with cursor pagination
244
+ - `getTestCase(options)` - Get a specific test case
245
+ - `createTestCase(request)` - Create a new test case
246
+ - `updateTestCase(request)` - Update a test case
247
+ - `getTestCaseLinks(testCaseKey)` - Get links for a test case
248
+ - `createTestCaseIssueLink(request)` - Create issue link
249
+ - `createTestCaseWebLink(request)` - Create web link
250
+ - `listTestCaseVersions(options)` - List test case versions
251
+ - `getTestCaseVersion(options)` - Get a specific version
252
+ - `getTestCaseTestScript(testCaseKey)` - Get test script
253
+ - `createTestCaseTestScript(request)` - Create or update test script
254
+ - `getTestCaseTestSteps(testCaseKey, options?)` - Get test steps
255
+ - `createTestCaseTestSteps(request)` - Create test steps
256
+
257
+ ### TestCycle
258
+ - `listTestCycles(options?)` - List all test cycles
259
+ - `getTestCycle(options)` - Get a specific test cycle
260
+ - `createTestCycle(request)` - Create a new test cycle
261
+ - `updateTestCycle(request)` - Update a test cycle
262
+ - `getTestCycleLinks(testCycleIdOrKey)` - Get links for a test cycle
263
+ - `createTestCycleIssueLink(request)` - Create issue link
264
+ - `createTestCycleWebLink(request)` - Create web link
265
+
266
+ ### TestPlan
267
+ - `listTestPlans(options?)` - List all test plans
268
+ - `getTestPlan(options)` - Get a specific test plan
269
+ - `createTestPlan(request)` - Create a new test plan
270
+ - `createTestPlanIssueLink(request)` - Create issue link
271
+ - `createTestPlanWebLink(request)` - Create web link
272
+ - `createTestPlanTestCycleLink(request)` - Link test cycle to test plan
273
+
274
+ ### TestExecution
275
+ - `listTestExecutions(options?)` - List all test executions
276
+ - `listTestExecutionsNextgen(options?)` - List test executions with cursor pagination
277
+ - `getTestExecution(options)` - Get a specific test execution
278
+ - `createTestExecution(request)` - Create a new test execution
279
+ - `updateTestExecution(request)` - Update a test execution
280
+ - `getTestExecutionTestSteps(options)` - Get test steps for execution
281
+ - `putTestExecutionTestSteps(request)` - Update test steps
282
+ - `syncTestExecutionScript(request)` - Sync with test case script
283
+ - `listTestExecutionLinks(testExecutionIdOrKey)` - Get links
284
+ - `createTestExecutionIssueLink(request)` - Create issue link
285
+
286
+ ### Link
287
+ - `deleteLink(options)` - Delete a link (idempotent)
288
+
289
+ ### IssueLink
290
+ - `getIssueLinkTestCases(options)` - Get test cases linked to issue
291
+ - `getIssueLinkTestCycles(options)` - Get test cycles linked to issue
292
+ - `getIssueLinkTestPlans(options)` - Get test plans linked to issue
293
+ - `getIssueLinkExecutions(options)` - Get test executions linked to issue
294
+
295
+ ### Automation
296
+ - `createCustomExecutions(request)` - Upload custom format results
297
+ - `createCucumberExecutions(request)` - Upload Cucumber results
298
+ - `createJUnitExecutions(request)` - Upload JUnit XML results
299
+ - `retrieveBDDTestCases(options)` - Retrieve BDD feature files
300
+
301
+ ## Authentication
302
+
303
+ ### Using ScriptRunner Connect API Connection (Recommended)
304
+
305
+ When using in ScriptRunner Connect, configure an API Connection in the web UI and use it:
306
+
307
+ ```typescript
308
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
309
+ import ZephyrApiConnection from '../api/zephyr';
310
+
311
+ const Zephyr = createZephyrApi(ZephyrApiConnection, 'us');
312
+ ```
313
+
314
+ ### Using OAuth Token
315
+
316
+ For local testing or when using OAuth tokens directly:
317
+
318
+ ```typescript
319
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
320
+
321
+ const Zephyr = createZephyrApi('your-oauth-token', 'us');
322
+ ```
323
+
324
+ ## Region Support
325
+
326
+ The API supports both US and EU regions:
327
+
328
+ ```typescript
329
+ // US region (default)
330
+ const ZephyrUS = createZephyrApi(apiConnection, 'us');
331
+
332
+ // EU region
333
+ const ZephyrEU = createZephyrApi(apiConnection, 'eu');
334
+ ```
335
+
336
+ ## Custom Fields
337
+
338
+ Custom fields are supported as flexible key-value pairs:
339
+
340
+ ```typescript
341
+ const customFields = {
342
+ 'Build Number': 20,
343
+ 'Release Date': '2024-01-15',
344
+ 'Pre-Condition(s)': 'User should have logged in.<br>User should have navigated to the panel.',
345
+ 'Implemented': false,
346
+ 'Category': ['Performance', 'Regression'],
347
+ 'Tester': 'user-account-id-here'
348
+ };
349
+
350
+ await Zephyr.TestCase.createTestCase({
351
+ body: {
352
+ projectKey: 'PROJ',
353
+ name: 'Test Case',
354
+ customFields: customFields
355
+ }
356
+ });
357
+ ```
358
+
359
+ **Note**:
360
+ - Multi-line text fields support HTML with `<br>` tags
361
+ - Dates should be in format `yyyy-MM-dd`
362
+ - Users should have values of Jira User Account IDs
363
+ - Custom field types are defined in your Zephyr project configuration
364
+
365
+ ## Error Handling
366
+
367
+ 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.
368
+
369
+ ### Error Types
370
+
371
+ ```typescript
372
+ import {
373
+ BadRequestError,
374
+ UnauthorizedError,
375
+ ForbiddenError,
376
+ NotFoundError,
377
+ TooManyRequestsError,
378
+ ServerError,
379
+ HttpError,
380
+ UnexpectedError
381
+ } from '@rbaileysr/zephyr-managed-api';
382
+
383
+ try {
384
+ const testCase = await Zephyr.TestCase.getTestCase({ testCaseKey: 'INVALID-T1' });
385
+ } catch (error) {
386
+ if (error instanceof NotFoundError) {
387
+ console.log('Test case not found');
388
+ } else if (error instanceof BadRequestError) {
389
+ console.log('Invalid request');
390
+ } else if (error instanceof TooManyRequestsError) {
391
+ console.log('Rate limited - this should have been retried automatically');
392
+ } else if (error instanceof HttpError) {
393
+ console.log(`HTTP error: ${error.message}`);
394
+ }
395
+ }
396
+ ```
397
+
398
+ ### Automatic Rate Limiting Handling
399
+
400
+ All API methods automatically handle rate limiting (HTTP 429) with:
401
+
402
+ - **Exponential Backoff**: Starts at 1 second, doubles with each retry
403
+ - **Retry-After Header Support**: Respects `Retry-After` header when present
404
+ - **Configurable Retries**: Defaults to 5 retries, max delay of 60 seconds
405
+ - **Transparent Operation**: Retries happen automatically - no code changes needed
406
+
407
+ **Default Retry Configuration:**
408
+ - Maximum retries: 5
409
+ - Initial delay: 1 second
410
+ - Maximum delay: 60 seconds
411
+ - Backoff multiplier: 2x
412
+
413
+ **Example:**
414
+ ```typescript
415
+ // This call will automatically retry on 429 errors
416
+ // You don't need to handle rate limiting manually
417
+ const testCases = await Zephyr.TestCase.listTestCases({ projectKey: 'PROJ' });
418
+ ```
419
+
420
+ If rate limiting occurs:
421
+ 1. The API waits (using Retry-After header if present, otherwise exponential backoff)
422
+ 2. Retries the request automatically
423
+ 3. Repeats up to 5 times
424
+ 4. Only throws `TooManyRequestsError` if all retries are exhausted
425
+
426
+ ### Error Strategy Support
427
+
428
+ For advanced error handling, you can provide an `errorStrategy` parameter to customize how errors are handled:
429
+
430
+ ```typescript
431
+ import { retry, ErrorStrategyBuilder } from '@rbaileysr/zephyr-managed-api';
432
+
433
+ // Return null instead of throwing on 404
434
+ const testCase = await Zephyr.TestCase.getTestCase(
435
+ { testCaseKey: 'PROJ-T1' },
436
+ {
437
+ handleHttp404Error: () => ({ type: 'return', value: null })
438
+ }
439
+ );
440
+
441
+ // Using ErrorStrategyBuilder for cleaner syntax
442
+ const errorStrategy = new ErrorStrategyBuilder<TestCase | null>()
443
+ .http404Error(() => ({ type: 'return', value: null }))
444
+ .retryOnRateLimiting(10) // Retry up to 10 times on rate limiting
445
+ .http500Error(() => retry(5000)) // Retry server errors with 5s delay
446
+ .build();
447
+
448
+ const testCase2 = await Zephyr.TestCase.getTestCase(
449
+ { testCaseKey: 'PROJ-T2' },
450
+ errorStrategy
451
+ );
452
+ ```
453
+
454
+ **Available Error Strategy Handlers:**
455
+ - `handleHttp400Error` - Handle 400 Bad Request
456
+ - `handleHttp401Error` - Handle 401 Unauthorized
457
+ - `handleHttp403Error` - Handle 403 Forbidden
458
+ - `handleHttp404Error` - Handle 404 Not Found
459
+ - `handleHttp429Error` - Handle 429 Too Many Requests (receives retryCount)
460
+ - `handleHttp500Error` - Handle 500+ Server Errors
461
+ - `handleHttpError` - Handle any HTTP error (fallback)
462
+
463
+ **Error Strategy Actions:**
464
+ - `retry(delay)` - Retry the request after the specified delay (milliseconds)
465
+ - `continuePropagation()` - Let the error propagate normally (default)
466
+ - `{ type: 'return', value: T }` - Return a specific value instead of throwing
467
+
468
+ ### Error Type Reference
469
+
470
+ | Error Type | HTTP Status | Description |
471
+ |------------|-------------|-------------|
472
+ | `BadRequestError` | 400 | Invalid request parameters |
473
+ | `UnauthorizedError` | 401 | Authentication required or invalid |
474
+ | `ForbiddenError` | 403 | Insufficient permissions |
475
+ | `NotFoundError` | 404 | Resource not found |
476
+ | `TooManyRequestsError` | 429 | Rate limit exceeded (after retries) |
477
+ | `ServerError` | 500+ | Server-side error |
478
+ | `HttpError` | Other | Generic HTTP error |
479
+ | `UnexpectedError` | N/A | Network or parsing errors |
480
+
481
+ ## Pagination
482
+
483
+ ### Manual Pagination
484
+
485
+ #### Offset-Based Pagination
486
+
487
+ ```typescript
488
+ const testCases = await Zephyr.TestCase.listTestCases({
489
+ projectKey: 'PROJ',
490
+ maxResults: 50,
491
+ startAt: 0
492
+ });
493
+
494
+ // Check if more results available
495
+ if (!testCases.isLast) {
496
+ const nextPage = await Zephyr.TestCase.listTestCases({
497
+ projectKey: 'PROJ',
498
+ maxResults: 50,
499
+ startAt: testCases.startAt + testCases.maxResults
500
+ });
501
+ }
502
+ ```
503
+
504
+ #### Cursor-Based Pagination
505
+
506
+ ```typescript
507
+ const testCases = await Zephyr.TestCase.listTestCasesCursorPaginated({
508
+ projectKey: 'PROJ',
509
+ limit: 100,
510
+ startAtId: 0
511
+ });
512
+
513
+ // Get next page
514
+ if (testCases.nextStartAtId !== null) {
515
+ const nextPage = await Zephyr.TestCase.listTestCasesCursorPaginated({
516
+ projectKey: 'PROJ',
517
+ limit: 100,
518
+ startAtId: testCases.nextStartAtId
519
+ });
520
+ }
521
+ ```
522
+
523
+ ### Automatic Pagination with `getAllPages()`
524
+
525
+ For convenience, use `getAllPages()` to automatically fetch all pages:
526
+
527
+ #### Offset-Based Pagination
528
+
529
+ ```typescript
530
+ import { getAllPages } from '@rbaileysr/zephyr-managed-api';
531
+
532
+ // Automatically fetches all pages
533
+ const allTestCases = await getAllPages(
534
+ (startAt, maxResults) => Zephyr.TestCase.listTestCases({
535
+ projectKey: 'PROJ',
536
+ startAt,
537
+ maxResults
538
+ }),
539
+ { maxResults: 50 } // Optional: page size
540
+ );
541
+
542
+ // allTestCases is an array of all TestCase objects from all pages
543
+ console.log(`Found ${allTestCases.length} test cases`);
544
+ ```
545
+
546
+ #### Cursor-Based Pagination
547
+
548
+ ```typescript
549
+ import { getAllPagesCursor } from '@rbaileysr/zephyr-managed-api';
550
+
551
+ // Automatically fetches all pages
552
+ const allTestCases = await getAllPagesCursor(
553
+ (startAtId, limit) => Zephyr.TestCase.listTestCasesCursorPaginated({
554
+ projectKey: 'PROJ',
555
+ startAtId,
556
+ limit
557
+ }),
558
+ { limit: 100 } // Optional: page size
559
+ );
560
+
561
+ // allTestCases is an array of all TestCase objects from all pages
562
+ console.log(`Found ${allTestCases.length} test cases`);
563
+ ```
564
+
565
+ **Note**: `getAllPages()` and `getAllPagesCursor()` automatically handle pagination and will make multiple API calls as needed. Be mindful of rate limits when fetching large datasets.
566
+
567
+ ## API Documentation
568
+
569
+ All API methods include comprehensive JSDoc comments with:
570
+ - Detailed descriptions of what each endpoint does
571
+ - Parameter documentation with types and requirements
572
+ - Return type documentation
573
+ - Links to official Zephyr API documentation
574
+
575
+ When using the package in ScriptRunner Connect, IntelliSense will display these descriptions and links in the code editor.
576
+
577
+ ## Type Definitions
578
+
579
+ All TypeScript types are exported from the main module:
580
+
581
+ ```typescript
582
+ import type {
583
+ TestCase,
584
+ TestCycle,
585
+ TestExecution,
586
+ TestPlan,
587
+ CustomFields,
588
+ ZephyrApiConnection,
589
+ ErrorStrategy,
590
+ ErrorStrategyBuilder
591
+ } from '@rbaileysr/zephyr-managed-api';
592
+ ```
593
+
594
+ ## All Group
595
+
596
+ For programmatic access to all methods, use the `All` group:
597
+
598
+ ```typescript
599
+ // Access all methods through the All group
600
+ const testCase = await Zephyr.All.getTestCase({ testCaseKey: 'PROJ-T1' });
601
+ const testCycle = await Zephyr.All.createTestCycle({ body: { ... } });
602
+ ```
603
+
604
+ 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.
605
+
606
+ ## License
607
+
608
+ MIT
609
+
610
+ ## Support
611
+
612
+ For issues, questions, or contributions, please refer to the project repository on GitHub.
613
+
614
+ ## Links
615
+
616
+ - **NPM Package**: https://www.npmjs.com/package/@rbaileysr/zephyr-managed-api
617
+ - **Zephyr API Documentation**: https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/
618
+ - **ScriptRunner Connect Documentation**: https://docs.adaptavist.com/src/latest/
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Error Strategy Types and Utilities
3
+ * Provides flexible error handling for API calls
4
+ */
5
+ import type { ApiResponseType } from './utils';
6
+ /**
7
+ * Retry action - indicates the request should be retried after a delay
8
+ */
9
+ export interface RetryAction {
10
+ type: 'retry';
11
+ delay: number;
12
+ }
13
+ /**
14
+ * Continue propagation - let the error propagate normally
15
+ */
16
+ export interface ContinuePropagationAction {
17
+ type: 'continue';
18
+ }
19
+ /**
20
+ * Return value - return a specific value instead of throwing
21
+ */
22
+ export interface ReturnValueAction<T> {
23
+ type: 'return';
24
+ value: T;
25
+ }
26
+ export type ErrorStrategyAction<T> = RetryAction | ContinuePropagationAction | ReturnValueAction<T>;
27
+ /**
28
+ * Create a retry action
29
+ */
30
+ export declare function retry(delay: number): RetryAction;
31
+ /**
32
+ * Continue error propagation (default behavior)
33
+ */
34
+ export declare function continuePropagation(): ContinuePropagationAction;
35
+ /**
36
+ * Error strategy handlers
37
+ */
38
+ export interface ErrorStrategyHandlers<T> {
39
+ handleHttp400Error?: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>;
40
+ handleHttp401Error?: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>;
41
+ handleHttp403Error?: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>;
42
+ handleHttp404Error?: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>;
43
+ handleHttp429Error?: (response: ApiResponseType, retryCount: number) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>;
44
+ handleHttp500Error?: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>;
45
+ handleHttpError?: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>;
46
+ }
47
+ /**
48
+ * Error strategy builder pattern
49
+ */
50
+ export declare class ErrorStrategyBuilder<T = unknown> {
51
+ private handlers;
52
+ http400Error(handler: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>): this;
53
+ http401Error(handler: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>): this;
54
+ http403Error(handler: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>): this;
55
+ http404Error(handler: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>): this;
56
+ http429Error(handler: (response: ApiResponseType, retryCount: number) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>): this;
57
+ http500Error(handler: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>): this;
58
+ httpError(handler: (response: ApiResponseType, errorData: unknown) => ErrorStrategyAction<T> | Promise<ErrorStrategyAction<T>>): this;
59
+ /**
60
+ * Retry on rate limiting with specified max retries
61
+ */
62
+ retryOnRateLimiting(maxRetries: number): this;
63
+ build(): ErrorStrategyHandlers<T>;
64
+ }
65
+ /**
66
+ * Apply error strategy to a response
67
+ */
68
+ export declare function applyErrorStrategy<T>(response: ApiResponseType, errorStrategy: ErrorStrategyHandlers<T> | undefined, retryCount?: number): Promise<ErrorStrategyAction<T>>;
69
+ //# sourceMappingURL=error-strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-strategy.d.ts","sourceRoot":"","sources":["../error-strategy.ts"],"names":[],"mappings":"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"}