@rbaileysr/zephyr-managed-api 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +280 -0
- package/dist/README.md +280 -0
- package/dist/groups/Private.d.ts +256 -0
- package/dist/groups/Private.d.ts.map +1 -0
- package/dist/groups/Private.js +743 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/package.json +2 -10
- package/dist/types.d.ts +132 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -10
package/README.md
CHANGED
|
@@ -331,6 +331,25 @@ The Managed API is organized into the following groups:
|
|
|
331
331
|
- `createJUnitExecutions(request)` - Upload JUnit XML results
|
|
332
332
|
- `retrieveBDDTestCases(options)` - Retrieve BDD feature files
|
|
333
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
|
+
|
|
334
353
|
## Authentication
|
|
335
354
|
|
|
336
355
|
### Using ScriptRunner Connect API Connection (Recommended)
|
|
@@ -370,6 +389,253 @@ const apiEU = Zephyr.createZephyrApi(
|
|
|
370
389
|
);
|
|
371
390
|
```
|
|
372
391
|
|
|
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.
|
|
403
|
+
|
|
404
|
+
### Get Context JWT
|
|
405
|
+
|
|
406
|
+
The Context JWT is a short-lived token (15 minutes) required for all private API calls:
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import Zephyr from '@rbaileysr/zephyr-managed-api';
|
|
410
|
+
import ZephyrApiConnection from '../api/zephyr';
|
|
411
|
+
|
|
412
|
+
const api = Zephyr.createZephyrApi(ZephyrApiConnection);
|
|
413
|
+
|
|
414
|
+
// 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
|
+
);
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Create Custom Fields
|
|
423
|
+
|
|
424
|
+
Create custom fields for test cases, test plans, test runs, or test steps:
|
|
425
|
+
|
|
426
|
+
```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
|
|
433
|
+
{
|
|
434
|
+
projectId: 10017,
|
|
435
|
+
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
|
|
437
|
+
required: false,
|
|
438
|
+
index: 4,
|
|
439
|
+
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
|
+
archived: false
|
|
464
|
+
}
|
|
465
|
+
);
|
|
466
|
+
```
|
|
467
|
+
|
|
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.
|
|
488
|
+
|
|
489
|
+
```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',
|
|
495
|
+
{
|
|
496
|
+
testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
|
|
497
|
+
projectId: 10017 // Numeric project ID
|
|
498
|
+
}
|
|
499
|
+
);
|
|
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
|
+
```
|
|
526
|
+
|
|
527
|
+
### Get Test Case Attachments
|
|
528
|
+
|
|
529
|
+
Retrieve all attachment details for a test case, including signed S3 URLs for downloading.
|
|
530
|
+
|
|
531
|
+
```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.
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
const fileBlob = await api.Private.downloadAttachment(
|
|
567
|
+
'user@example.com',
|
|
568
|
+
'jira-api-token',
|
|
569
|
+
'https://your-instance.atlassian.net',
|
|
570
|
+
{
|
|
571
|
+
testCaseKey: 'PROJ-T1',
|
|
572
|
+
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
|
|
604
|
+
fileName: 'test-file.txt',
|
|
605
|
+
userAccountId: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
|
|
606
|
+
}
|
|
607
|
+
);
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
**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
|
|
616
|
+
|
|
617
|
+
Private API methods use the same error types as the public API:
|
|
618
|
+
|
|
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
|
+
```
|
|
638
|
+
|
|
373
639
|
## Custom Fields
|
|
374
640
|
|
|
375
641
|
Custom fields are supported as flexible key-value pairs:
|
|
@@ -677,6 +943,20 @@ For issues, questions, or contributions, please refer to the project repository
|
|
|
677
943
|
|
|
678
944
|
## Changelog
|
|
679
945
|
|
|
946
|
+
### 1.1.0
|
|
947
|
+
|
|
948
|
+
- **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)
|
|
952
|
+
- `createTestCaseComment()` - Create comments on test cases
|
|
953
|
+
- `getTestCaseAttachments()` - Get all attachment details for a test case
|
|
954
|
+
- `downloadAttachment()` - Download attachment files into memory with automatic fresh URL retrieval
|
|
955
|
+
- `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
|
+
|
|
680
960
|
### 1.0.1
|
|
681
961
|
|
|
682
962
|
- **Added**: Comprehensive JSDoc comments with API endpoint descriptions and links to official documentation
|
package/dist/README.md
CHANGED
|
@@ -331,6 +331,25 @@ The Managed API is organized into the following groups:
|
|
|
331
331
|
- `createJUnitExecutions(request)` - Upload JUnit XML results
|
|
332
332
|
- `retrieveBDDTestCases(options)` - Retrieve BDD feature files
|
|
333
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
|
+
|
|
334
353
|
## Authentication
|
|
335
354
|
|
|
336
355
|
### Using ScriptRunner Connect API Connection (Recommended)
|
|
@@ -370,6 +389,253 @@ const apiEU = Zephyr.createZephyrApi(
|
|
|
370
389
|
);
|
|
371
390
|
```
|
|
372
391
|
|
|
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.
|
|
403
|
+
|
|
404
|
+
### Get Context JWT
|
|
405
|
+
|
|
406
|
+
The Context JWT is a short-lived token (15 minutes) required for all private API calls:
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
import Zephyr from '@rbaileysr/zephyr-managed-api';
|
|
410
|
+
import ZephyrApiConnection from '../api/zephyr';
|
|
411
|
+
|
|
412
|
+
const api = Zephyr.createZephyrApi(ZephyrApiConnection);
|
|
413
|
+
|
|
414
|
+
// 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
|
+
);
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Create Custom Fields
|
|
423
|
+
|
|
424
|
+
Create custom fields for test cases, test plans, test runs, or test steps:
|
|
425
|
+
|
|
426
|
+
```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
|
|
433
|
+
{
|
|
434
|
+
projectId: 10017,
|
|
435
|
+
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
|
|
437
|
+
required: false,
|
|
438
|
+
index: 4,
|
|
439
|
+
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
|
+
archived: false
|
|
464
|
+
}
|
|
465
|
+
);
|
|
466
|
+
```
|
|
467
|
+
|
|
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.
|
|
488
|
+
|
|
489
|
+
```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',
|
|
495
|
+
{
|
|
496
|
+
testCaseKey: 'PROJ-T1', // Uses key, looks up ID automatically
|
|
497
|
+
projectId: 10017 // Numeric project ID
|
|
498
|
+
}
|
|
499
|
+
);
|
|
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
|
+
```
|
|
526
|
+
|
|
527
|
+
### Get Test Case Attachments
|
|
528
|
+
|
|
529
|
+
Retrieve all attachment details for a test case, including signed S3 URLs for downloading.
|
|
530
|
+
|
|
531
|
+
```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.
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
const fileBlob = await api.Private.downloadAttachment(
|
|
567
|
+
'user@example.com',
|
|
568
|
+
'jira-api-token',
|
|
569
|
+
'https://your-instance.atlassian.net',
|
|
570
|
+
{
|
|
571
|
+
testCaseKey: 'PROJ-T1',
|
|
572
|
+
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
|
|
604
|
+
fileName: 'test-file.txt',
|
|
605
|
+
userAccountId: '5d6fdc98dc6e480dbc021aae' // Atlassian account ID
|
|
606
|
+
}
|
|
607
|
+
);
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
**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
|
|
616
|
+
|
|
617
|
+
Private API methods use the same error types as the public API:
|
|
618
|
+
|
|
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
|
+
```
|
|
638
|
+
|
|
373
639
|
## Custom Fields
|
|
374
640
|
|
|
375
641
|
Custom fields are supported as flexible key-value pairs:
|
|
@@ -677,6 +943,20 @@ For issues, questions, or contributions, please refer to the project repository
|
|
|
677
943
|
|
|
678
944
|
## Changelog
|
|
679
945
|
|
|
946
|
+
### 1.1.0
|
|
947
|
+
|
|
948
|
+
- **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)
|
|
952
|
+
- `createTestCaseComment()` - Create comments on test cases
|
|
953
|
+
- `getTestCaseAttachments()` - Get all attachment details for a test case
|
|
954
|
+
- `downloadAttachment()` - Download attachment files into memory with automatic fresh URL retrieval
|
|
955
|
+
- `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
|
+
|
|
680
960
|
### 1.0.1
|
|
681
961
|
|
|
682
962
|
- **Added**: Comprehensive JSDoc comments with API endpoint descriptions and links to official documentation
|