@rbaileysr/zephyr-managed-api 1.0.0 → 1.0.2

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 (58) hide show
  1. package/README.md +155 -74
  2. package/dist/README.md +699 -0
  3. package/dist/error-strategy.d.ts +3 -0
  4. package/dist/error-strategy.d.ts.map +1 -1
  5. package/dist/error-strategy.js +3 -0
  6. package/dist/groups/All.d.ts +3 -0
  7. package/dist/groups/All.d.ts.map +1 -1
  8. package/dist/groups/All.js +2 -6
  9. package/dist/groups/Automation.d.ts +3 -0
  10. package/dist/groups/Automation.d.ts.map +1 -1
  11. package/dist/groups/Automation.js +2 -3
  12. package/dist/groups/Environment.d.ts +3 -0
  13. package/dist/groups/Environment.d.ts.map +1 -1
  14. package/dist/groups/Environment.js +2 -3
  15. package/dist/groups/Folder.d.ts +3 -0
  16. package/dist/groups/Folder.d.ts.map +1 -1
  17. package/dist/groups/Folder.js +2 -3
  18. package/dist/groups/IssueLink.d.ts +3 -0
  19. package/dist/groups/IssueLink.d.ts.map +1 -1
  20. package/dist/groups/IssueLink.js +2 -3
  21. package/dist/groups/Link.d.ts +3 -0
  22. package/dist/groups/Link.d.ts.map +1 -1
  23. package/dist/groups/Link.js +2 -3
  24. package/dist/groups/Priority.d.ts +3 -0
  25. package/dist/groups/Priority.d.ts.map +1 -1
  26. package/dist/groups/Priority.js +2 -3
  27. package/dist/groups/Project.d.ts +3 -0
  28. package/dist/groups/Project.d.ts.map +1 -1
  29. package/dist/groups/Project.js +2 -3
  30. package/dist/groups/Status.d.ts +3 -0
  31. package/dist/groups/Status.d.ts.map +1 -1
  32. package/dist/groups/Status.js +2 -3
  33. package/dist/groups/TestCase.d.ts +3 -0
  34. package/dist/groups/TestCase.d.ts.map +1 -1
  35. package/dist/groups/TestCase.js +2 -3
  36. package/dist/groups/TestCycle.d.ts +3 -0
  37. package/dist/groups/TestCycle.d.ts.map +1 -1
  38. package/dist/groups/TestCycle.js +2 -3
  39. package/dist/groups/TestExecution.d.ts +3 -0
  40. package/dist/groups/TestExecution.d.ts.map +1 -1
  41. package/dist/groups/TestExecution.js +2 -3
  42. package/dist/groups/TestPlan.d.ts +3 -0
  43. package/dist/groups/TestPlan.d.ts.map +1 -1
  44. package/dist/groups/TestPlan.js +2 -3
  45. package/dist/index.d.ts +147 -12
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +47 -11
  48. package/dist/package.json +54 -0
  49. package/dist/types.d.ts +3 -0
  50. package/dist/types.d.ts.map +1 -1
  51. package/dist/types.js +3 -0
  52. package/dist/utils-api-call.d.ts +3 -0
  53. package/dist/utils-api-call.d.ts.map +1 -1
  54. package/dist/utils-api-call.js +3 -0
  55. package/dist/utils.d.ts +3 -0
  56. package/dist/utils.d.ts.map +1 -1
  57. package/dist/utils.js +3 -0
  58. package/package.json +4 -4
package/dist/README.md ADDED
@@ -0,0 +1,699 @@
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
+ - **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
24
+
25
+ ## Installation
26
+
27
+ ### NPM Package
28
+
29
+ ```bash
30
+ npm install @rbaileysr/zephyr-managed-api
31
+ ```
32
+
33
+ **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
+
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';
83
+
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
93
+
94
+ ```typescript
95
+ // Named imports (alternative)
96
+ import { createZephyrApi } from '@rbaileysr/zephyr-managed-api';
97
+ import ZephyrApiConnection from '../api/zephyr';
98
+
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
+ ## Authentication
335
+
336
+ ### Using ScriptRunner Connect API Connection (Recommended)
337
+
338
+ When using in ScriptRunner Connect, configure a Generic Connector with the full base URL in the web UI:
339
+
340
+ **For US region:** `https://api.zephyrscale.smartbear.com/v2`
341
+ **For EU region:** `https://eu.api.zephyrscale.smartbear.com/v2`
342
+
343
+ Then use it in your script:
344
+
345
+ ```typescript
346
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
347
+ import ZephyrApiConnection from '../api/zephyr';
348
+
349
+ // Base URL is configured in the Generic Connector
350
+ const api = Zephyr.createZephyrApi(ZephyrApiConnection);
351
+ ```
352
+
353
+ ### Using OAuth Token
354
+
355
+ For local testing or when using OAuth tokens directly, provide the full base URL:
356
+
357
+ ```typescript
358
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
359
+
360
+ // US region
361
+ const api = Zephyr.createZephyrApi(
362
+ 'your-oauth-token',
363
+ 'https://api.zephyrscale.smartbear.com/v2'
364
+ );
365
+
366
+ // EU region
367
+ const apiEU = Zephyr.createZephyrApi(
368
+ 'your-oauth-token',
369
+ 'https://eu.api.zephyrscale.smartbear.com/v2'
370
+ );
371
+ ```
372
+
373
+ ## Custom Fields
374
+
375
+ Custom fields are supported as flexible key-value pairs:
376
+
377
+ ```typescript
378
+ const customFields = {
379
+ 'Build Number': 20,
380
+ 'Release Date': '2024-01-15',
381
+ 'Pre-Condition(s)': 'User should have logged in.<br>User should have navigated to the panel.',
382
+ 'Implemented': false,
383
+ 'Category': ['Performance', 'Regression'],
384
+ 'Tester': 'user-account-id-here'
385
+ };
386
+
387
+ await api.TestCase.createTestCase({
388
+ body: {
389
+ projectKey: 'PROJ',
390
+ name: 'Test Case',
391
+ customFields: customFields
392
+ }
393
+ });
394
+ ```
395
+
396
+ **Note**:
397
+ - Multi-line text fields support HTML with `<br>` tags
398
+ - Dates should be in format `yyyy-MM-dd`
399
+ - Users should have values of Jira User Account IDs
400
+ - Custom field types are defined in your Zephyr project configuration
401
+
402
+ ## Error Handling
403
+
404
+ 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.
405
+
406
+ ### Error Types
407
+
408
+ ```typescript
409
+ // Single import for everything
410
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
411
+ import ZephyrApiConnection from '../api/zephyr';
412
+
413
+ const api = Zephyr.createZephyrApi(ZephyrApiConnection);
414
+
415
+ try {
416
+ const testCase = await api.TestCase.getTestCase({ testCaseKey: 'INVALID-T1' });
417
+ } catch (error) {
418
+ if (error instanceof Zephyr.NotFoundError) {
419
+ console.log('Test case not found');
420
+ } else if (error instanceof Zephyr.BadRequestError) {
421
+ console.log('Invalid request');
422
+ } else if (error instanceof Zephyr.TooManyRequestsError) {
423
+ console.log('Rate limited - this should have been retried automatically');
424
+ } else if (error instanceof Zephyr.HttpError) {
425
+ console.log(`HTTP error: ${error.message}`);
426
+ }
427
+ }
428
+ ```
429
+
430
+ **Alternative - Named Imports:**
431
+ ```typescript
432
+ import {
433
+ createZephyrApi,
434
+ BadRequestError,
435
+ UnauthorizedError,
436
+ ForbiddenError,
437
+ NotFoundError,
438
+ TooManyRequestsError,
439
+ ServerError,
440
+ HttpError,
441
+ UnexpectedError
442
+ } from '@rbaileysr/zephyr-managed-api';
443
+
444
+ // Use named imports as before
445
+ ```
446
+
447
+ ### Automatic Rate Limiting Handling
448
+
449
+ All API methods automatically handle rate limiting (HTTP 429) with:
450
+
451
+ - **Exponential Backoff**: Starts at 1 second, doubles with each retry
452
+ - **Retry-After Header Support**: Respects `Retry-After` header when present
453
+ - **Configurable Retries**: Defaults to 5 retries, max delay of 60 seconds
454
+ - **Transparent Operation**: Retries happen automatically - no code changes needed
455
+
456
+ **Default Retry Configuration:**
457
+ - Maximum retries: 5
458
+ - Initial delay: 1 second
459
+ - Maximum delay: 60 seconds
460
+ - Backoff multiplier: 2x
461
+
462
+ **Example:**
463
+ ```typescript
464
+ // This call will automatically retry on 429 errors
465
+ // You don't need to handle rate limiting manually
466
+ const testCases = await api.TestCase.listTestCases({ projectKey: 'PROJ' });
467
+ ```
468
+
469
+ If rate limiting occurs:
470
+ 1. The API waits (using Retry-After header if present, otherwise exponential backoff)
471
+ 2. Retries the request automatically
472
+ 3. Repeats up to 5 times
473
+ 4. Only throws `TooManyRequestsError` if all retries are exhausted
474
+
475
+ ### Error Strategy Support
476
+
477
+ For advanced error handling, you can provide an `errorStrategy` parameter to customize how errors are handled:
478
+
479
+ ```typescript
480
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
481
+ import ZephyrApiConnection from '../api/zephyr';
482
+
483
+ const api = Zephyr.createZephyrApi(ZephyrApiConnection);
484
+
485
+ // Return null instead of throwing on 404
486
+ const testCase = await api.TestCase.getTestCase(
487
+ { testCaseKey: 'PROJ-T1' },
488
+ {
489
+ handleHttp404Error: () => ({ type: 'return', value: null })
490
+ }
491
+ );
492
+
493
+ // Using ErrorStrategyBuilder for cleaner syntax
494
+ const errorStrategy = new Zephyr.ErrorStrategyBuilder<TestCase | null>()
495
+ .http404Error(() => ({ type: 'return', value: null }))
496
+ .retryOnRateLimiting(10) // Retry up to 10 times on rate limiting
497
+ .http500Error(() => Zephyr.retry(5000)) // Retry server errors with 5s delay
498
+ .build();
499
+
500
+ const testCase2 = await api.TestCase.getTestCase(
501
+ { testCaseKey: 'PROJ-T2' },
502
+ errorStrategy
503
+ );
504
+ ```
505
+
506
+ **Available Error Strategy Handlers:**
507
+ - `handleHttp400Error` - Handle 400 Bad Request
508
+ - `handleHttp401Error` - Handle 401 Unauthorized
509
+ - `handleHttp403Error` - Handle 403 Forbidden
510
+ - `handleHttp404Error` - Handle 404 Not Found
511
+ - `handleHttp429Error` - Handle 429 Too Many Requests (receives retryCount)
512
+ - `handleHttp500Error` - Handle 500+ Server Errors
513
+ - `handleHttpError` - Handle any HTTP error (fallback)
514
+
515
+ **Error Strategy Actions:**
516
+ - `retry(delay)` - Retry the request after the specified delay (milliseconds)
517
+ - `continuePropagation()` - Let the error propagate normally (default)
518
+ - `{ type: 'return', value: T }` - Return a specific value instead of throwing
519
+
520
+ ### Error Type Reference
521
+
522
+ | Error Type | HTTP Status | Description |
523
+ |------------|-------------|-------------|
524
+ | `BadRequestError` | 400 | Invalid request parameters |
525
+ | `UnauthorizedError` | 401 | Authentication required or invalid |
526
+ | `ForbiddenError` | 403 | Insufficient permissions |
527
+ | `NotFoundError` | 404 | Resource not found |
528
+ | `TooManyRequestsError` | 429 | Rate limit exceeded (after retries) |
529
+ | `ServerError` | 500+ | Server-side error |
530
+ | `HttpError` | Other | Generic HTTP error |
531
+ | `UnexpectedError` | N/A | Network or parsing errors |
532
+
533
+ ## Pagination
534
+
535
+ ### Manual Pagination
536
+
537
+ #### Offset-Based Pagination
538
+
539
+ ```typescript
540
+ const testCases = await api.TestCase.listTestCases({
541
+ projectKey: 'PROJ',
542
+ maxResults: 50,
543
+ startAt: 0
544
+ });
545
+
546
+ // Check if more results available
547
+ if (!testCases.isLast) {
548
+ const nextPage = await api.TestCase.listTestCases({
549
+ projectKey: 'PROJ',
550
+ maxResults: 50,
551
+ startAt: testCases.startAt + testCases.maxResults
552
+ });
553
+ }
554
+ ```
555
+
556
+ #### Cursor-Based Pagination
557
+
558
+ ```typescript
559
+ const testCases = await api.TestCase.listTestCasesCursorPaginated({
560
+ projectKey: 'PROJ',
561
+ limit: 100,
562
+ startAtId: 0
563
+ });
564
+
565
+ // Get next page
566
+ if (testCases.nextStartAtId !== null) {
567
+ const nextPage = await api.TestCase.listTestCasesCursorPaginated({
568
+ projectKey: 'PROJ',
569
+ limit: 100,
570
+ startAtId: testCases.nextStartAtId
571
+ });
572
+ }
573
+ ```
574
+
575
+ ### Automatic Pagination with `getAllPages()`
576
+
577
+ For convenience, use `getAllPages()` to automatically fetch all pages:
578
+
579
+ #### Offset-Based Pagination
580
+
581
+ ```typescript
582
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
583
+ import ZephyrApiConnection from '../api/zephyr';
584
+
585
+ const api = Zephyr.createZephyrApi(ZephyrApiConnection);
586
+
587
+ // Automatically fetches all pages
588
+ const allTestCases = await Zephyr.getAllPages(
589
+ (startAt, maxResults) => api.TestCase.listTestCases({
590
+ projectKey: 'PROJ',
591
+ startAt,
592
+ maxResults
593
+ }),
594
+ { maxResults: 50 } // Optional: page size
595
+ );
596
+
597
+ // allTestCases is an array of all TestCase objects from all pages
598
+ console.log(`Found ${allTestCases.length} test cases`);
599
+ ```
600
+
601
+ #### Cursor-Based Pagination
602
+
603
+ ```typescript
604
+ import Zephyr from '@rbaileysr/zephyr-managed-api';
605
+ import ZephyrApiConnection from '../api/zephyr';
606
+
607
+ const api = Zephyr.createZephyrApi(ZephyrApiConnection);
608
+
609
+ // Automatically fetches all pages
610
+ const allTestCases = await Zephyr.getAllPagesCursor(
611
+ (startAtId, limit) => api.TestCase.listTestCasesCursorPaginated({
612
+ projectKey: 'PROJ',
613
+ startAtId,
614
+ limit
615
+ }),
616
+ { limit: 100 } // Optional: page size
617
+ );
618
+
619
+ // allTestCases is an array of all TestCase objects from all pages
620
+ console.log(`Found ${allTestCases.length} test cases`);
621
+ ```
622
+
623
+ **Note**: `getAllPages()` and `getAllPagesCursor()` automatically handle pagination and will make multiple API calls as needed. Be mindful of rate limits when fetching large datasets.
624
+
625
+ ## API Documentation
626
+
627
+ All API methods include comprehensive JSDoc comments with:
628
+ - Detailed descriptions of what each endpoint does
629
+ - Parameter documentation with types and requirements
630
+ - Return type documentation
631
+ - Links to official Zephyr API documentation
632
+
633
+ When using the package in ScriptRunner Connect, IntelliSense will display these descriptions and links in the code editor.
634
+
635
+ ## Type Definitions
636
+
637
+ All TypeScript types are exported from the main module:
638
+
639
+ ```typescript
640
+ import type {
641
+ TestCase,
642
+ TestCycle,
643
+ TestExecution,
644
+ TestPlan,
645
+ CustomFields,
646
+ ZephyrApiConnection,
647
+ ErrorStrategy,
648
+ ErrorStrategyBuilder
649
+ } from '@rbaileysr/zephyr-managed-api';
650
+ ```
651
+
652
+ ## All Group
653
+
654
+ For programmatic access to all methods, use the `All` group:
655
+
656
+ ```typescript
657
+ // Access all methods through the All group
658
+ const testCase = await Zephyr.All.getTestCase({ testCaseKey: 'PROJ-T1' });
659
+ const testCycle = await Zephyr.All.createTestCycle({ body: { ... } });
660
+ ```
661
+
662
+ 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.
663
+
664
+ ## License
665
+
666
+ UNLICENSED - Copyright Adaptavist 2025 (c) All rights reserved
667
+
668
+ ## Support
669
+
670
+ For issues, questions, or contributions, please refer to the project repository on GitHub.
671
+
672
+ ## Links
673
+
674
+ - **NPM Package**: https://www.npmjs.com/package/@rbaileysr/zephyr-managed-api
675
+ - **Zephyr API Documentation**: https://support.smartbear.com/zephyr-scale-cloud/api-docs/v2/
676
+ - **ScriptRunner Connect Documentation**: https://docs.adaptavist.com/src/latest/
677
+
678
+ ## Changelog
679
+
680
+ ### 1.0.1
681
+
682
+ - **Added**: Comprehensive JSDoc comments with API endpoint descriptions and links to official documentation
683
+ - **Added**: Single import option via default export for convenient usage
684
+ - **Changed**: Removed `region` parameter from `createZephyrApi` - base URL now configured in Generic Connector
685
+ - **Improved**: Error handling to support both `BadRequestError` and `NotFoundError` in test examples
686
+ - **Improved**: Type safety and IntelliSense support throughout the API
687
+
688
+ ### 1.0.0
689
+
690
+ - **Initial Release**: Complete Managed API wrapper for Zephyr Cloud REST API v2
691
+ - **Added**: Full support for all Zephyr API endpoints (Test Cases, Test Cycles, Test Plans, Test Executions, etc.)
692
+ - **Added**: Type-safe TypeScript definitions for all API operations
693
+ - **Added**: Hierarchical API structure matching ScriptRunner Connect conventions
694
+ - **Added**: Automatic rate limiting retry with exponential backoff
695
+ - **Added**: Support for both API Connection and OAuth token authentication
696
+ - **Added**: Pagination helpers (`getAllPages`, `getAllPagesCursor`)
697
+ - **Added**: Error strategy builder for advanced error handling
698
+ - **Added**: Comprehensive error types compatible with Commons Core
699
+
@@ -1,3 +1,6 @@
1
+ /*!
2
+ * Copyright Adaptavist 2025 (c) All rights reserved
3
+ */
1
4
  /**
2
5
  * Error Strategy Types and Utilities
3
6
  * Provides flexible error handling for API calls