@rbaileysr/zephyr-managed-api 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -30
- package/dist/README.md +70 -30
- package/dist/groups/Private/PrivateAttachments.d.ts +2 -0
- package/dist/groups/Private/PrivateAttachments.d.ts.map +1 -1
- package/dist/groups/Private/PrivateAttachments.js +13 -4
- package/dist/groups/Private/PrivateComments.d.ts +1 -0
- package/dist/groups/Private/PrivateComments.d.ts.map +1 -1
- package/dist/groups/Private/PrivateComments.js +11 -4
- package/dist/groups/Private/PrivateDataSets.d.ts +2 -3
- package/dist/groups/Private/PrivateDataSets.d.ts.map +1 -1
- package/dist/groups/Private/PrivateDataSets.js +11 -5
- package/dist/groups/Private/PrivateIterations.d.ts.map +1 -1
- package/dist/groups/Private/PrivateIterations.js +8 -1
- package/dist/groups/Private/PrivateLabels.d.ts.map +1 -1
- package/dist/groups/Private/PrivateLabels.js +8 -1
- package/dist/groups/Private/PrivateVersionControl.d.ts +108 -0
- package/dist/groups/Private/PrivateVersionControl.d.ts.map +1 -0
- package/dist/groups/Private/PrivateVersionControl.js +454 -0
- package/dist/groups/Private.d.ts +5 -0
- package/dist/groups/Private.d.ts.map +1 -1
- package/dist/groups/Private.js +2 -0
- package/dist/package.json +1 -1
- package/dist/types.d.ts +70 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright Adaptavist 2025 (c) All rights reserved
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Private API Version Control sub-group
|
|
6
|
+
* Handles version-specific operations for test case links, test script, and test steps
|
|
7
|
+
*
|
|
8
|
+
* ⚠️ WARNING: These methods use private APIs that are not officially supported.
|
|
9
|
+
*/
|
|
10
|
+
import type { PrivateApiCredentials, GetTestCaseIssueLinksRequest, GetTestCaseWebLinksRequest, GetTestCaseTestScriptRequest, GetTestCaseTestStepsRequest, IssueLinkList, WebLinkList, TestScript, TestStepsList } from '../../types';
|
|
11
|
+
import { PrivateBase } from './PrivateBase';
|
|
12
|
+
import type { ZephyrApiConnection } from '../../index';
|
|
13
|
+
export declare class PrivateVersionControl extends PrivateBase {
|
|
14
|
+
constructor(apiConnection?: ZephyrApiConnection);
|
|
15
|
+
/**
|
|
16
|
+
* Get issue links for a test case using private API (with version support)
|
|
17
|
+
*
|
|
18
|
+
* Retrieves all issue links associated with a test case, optionally for a specific version.
|
|
19
|
+
* The response format matches the public API `getTestCaseLinks().issues` format.
|
|
20
|
+
*
|
|
21
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
22
|
+
* The endpoint may change or be removed at any time without notice.
|
|
23
|
+
*
|
|
24
|
+
* @param credentials - Private API credentials
|
|
25
|
+
* @param request - Get issue links request
|
|
26
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1'). The numeric ID will be looked up automatically if Zephyr Connector is available.
|
|
27
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
28
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
29
|
+
* @returns Array of issue links matching the public API format
|
|
30
|
+
* @throws {BadRequestError} If the request is invalid
|
|
31
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
32
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
33
|
+
* @throws {NotFoundError} If the test case is not found
|
|
34
|
+
* @throws {ServerError} If the server returns an error
|
|
35
|
+
* @throws {UnexpectedError} If test case ID cannot be looked up from key and Zephyr Connector is not available
|
|
36
|
+
*/
|
|
37
|
+
getTestCaseIssueLinks(credentials: PrivateApiCredentials, request: GetTestCaseIssueLinksRequest): Promise<IssueLinkList>;
|
|
38
|
+
/**
|
|
39
|
+
* Get web links for a test case using private API (with version support)
|
|
40
|
+
*
|
|
41
|
+
* Retrieves all web links associated with a test case, optionally for a specific version.
|
|
42
|
+
* The response format matches the public API `getTestCaseLinks().webLinks` format.
|
|
43
|
+
*
|
|
44
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
45
|
+
* The endpoint may change or be removed at any time without notice.
|
|
46
|
+
*
|
|
47
|
+
* @param credentials - Private API credentials
|
|
48
|
+
* @param request - Get web links request
|
|
49
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1'). The numeric ID will be looked up automatically if Zephyr Connector is available.
|
|
50
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
51
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
52
|
+
* @returns Array of web links matching the public API format
|
|
53
|
+
* @throws {BadRequestError} If the request is invalid
|
|
54
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
55
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
56
|
+
* @throws {NotFoundError} If the test case is not found
|
|
57
|
+
* @throws {ServerError} If the server returns an error
|
|
58
|
+
* @throws {UnexpectedError} If test case ID cannot be looked up from key and Zephyr Connector is not available
|
|
59
|
+
*/
|
|
60
|
+
getTestCaseWebLinks(credentials: PrivateApiCredentials, request: GetTestCaseWebLinksRequest): Promise<WebLinkList>;
|
|
61
|
+
/**
|
|
62
|
+
* Get test script for a test case using private API (with version support)
|
|
63
|
+
*
|
|
64
|
+
* Retrieves the test script associated with a test case, optionally for a specific version.
|
|
65
|
+
* The response format matches the public API `getTestCaseTestScript()` format.
|
|
66
|
+
*
|
|
67
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
68
|
+
* The endpoint may change or be removed at any time without notice.
|
|
69
|
+
*
|
|
70
|
+
* @param credentials - Private API credentials
|
|
71
|
+
* @param request - Get test script request
|
|
72
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1')
|
|
73
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
74
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
75
|
+
* @returns Test script matching the public API format, or null if no test script exists
|
|
76
|
+
* @throws {BadRequestError} If the request is invalid
|
|
77
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
78
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
79
|
+
* @throws {NotFoundError} If the test case is not found
|
|
80
|
+
* @throws {ServerError} If the server returns an error
|
|
81
|
+
* @throws {UnexpectedError} If test case cannot be retrieved
|
|
82
|
+
*/
|
|
83
|
+
getTestCaseTestScript(credentials: PrivateApiCredentials, request: GetTestCaseTestScriptRequest): Promise<TestScript | null>;
|
|
84
|
+
/**
|
|
85
|
+
* Get test steps for a test case using private API (with version support)
|
|
86
|
+
*
|
|
87
|
+
* Retrieves the test steps associated with a test case, optionally for a specific version.
|
|
88
|
+
* The response format matches the public API `getTestCaseTestSteps()` format.
|
|
89
|
+
*
|
|
90
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
91
|
+
* The endpoint may change or be removed at any time without notice.
|
|
92
|
+
*
|
|
93
|
+
* @param credentials - Private API credentials
|
|
94
|
+
* @param request - Get test steps request
|
|
95
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1')
|
|
96
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
97
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
98
|
+
* @returns Test steps list matching the public API format
|
|
99
|
+
* @throws {BadRequestError} If the request is invalid
|
|
100
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
101
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
102
|
+
* @throws {NotFoundError} If the test case is not found
|
|
103
|
+
* @throws {ServerError} If the server returns an error
|
|
104
|
+
* @throws {UnexpectedError} If test case cannot be retrieved
|
|
105
|
+
*/
|
|
106
|
+
getTestCaseTestSteps(credentials: PrivateApiCredentials, request: GetTestCaseTestStepsRequest): Promise<TestStepsList>;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=PrivateVersionControl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrivateVersionControl.d.ts","sourceRoot":"","sources":["../../../groups/Private/PrivateVersionControl.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AAEH,OAAO,KAAK,EACX,qBAAqB,EACrB,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,EAC3B,aAAa,EACb,WAAW,EACX,UAAU,EACV,aAAa,EAKb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAS5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAqEvD,qBAAa,qBAAsB,SAAQ,WAAW;gBACzC,aAAa,CAAC,EAAE,mBAAmB;IAI/C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,qBAAqB,CAC1B,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,aAAa,CAAC;IA2GzB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,mBAAmB,CACxB,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,WAAW,CAAC;IA2GvB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,qBAAqB,CAC1B,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAgH7B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,oBAAoB,CACzB,WAAW,EAAE,qBAAqB,EAClC,OAAO,EAAE,2BAA2B,GAClC,OAAO,CAAC,aAAa,CAAC;CAgIzB"}
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright Adaptavist 2025 (c) All rights reserved
|
|
3
|
+
*/
|
|
4
|
+
import { PrivateBase } from './PrivateBase';
|
|
5
|
+
import { BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, ServerError, UnexpectedError, } from '../../utils';
|
|
6
|
+
export class PrivateVersionControl extends PrivateBase {
|
|
7
|
+
constructor(apiConnection) {
|
|
8
|
+
super(apiConnection);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get issue links for a test case using private API (with version support)
|
|
12
|
+
*
|
|
13
|
+
* Retrieves all issue links associated with a test case, optionally for a specific version.
|
|
14
|
+
* The response format matches the public API `getTestCaseLinks().issues` format.
|
|
15
|
+
*
|
|
16
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
17
|
+
* The endpoint may change or be removed at any time without notice.
|
|
18
|
+
*
|
|
19
|
+
* @param credentials - Private API credentials
|
|
20
|
+
* @param request - Get issue links request
|
|
21
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1'). The numeric ID will be looked up automatically if Zephyr Connector is available.
|
|
22
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
23
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
24
|
+
* @returns Array of issue links matching the public API format
|
|
25
|
+
* @throws {BadRequestError} If the request is invalid
|
|
26
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
27
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
28
|
+
* @throws {NotFoundError} If the test case is not found
|
|
29
|
+
* @throws {ServerError} If the server returns an error
|
|
30
|
+
* @throws {UnexpectedError} If test case ID cannot be looked up from key and Zephyr Connector is not available
|
|
31
|
+
*/
|
|
32
|
+
async getTestCaseIssueLinks(credentials, request) {
|
|
33
|
+
// Get test case ID from key if we have API connection
|
|
34
|
+
let testCaseId;
|
|
35
|
+
if (this.testCaseGroup) {
|
|
36
|
+
try {
|
|
37
|
+
// If version is specified, get the versioned test case; otherwise get the current version
|
|
38
|
+
const testCase = request.version !== undefined && request.version > 0
|
|
39
|
+
? await this.testCaseGroup.getTestCaseVersion({
|
|
40
|
+
testCaseKey: request.testCaseKey,
|
|
41
|
+
version: request.version,
|
|
42
|
+
})
|
|
43
|
+
: await this.testCaseGroup.getTestCase({ testCaseKey: request.testCaseKey });
|
|
44
|
+
if (!testCase) {
|
|
45
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
46
|
+
}
|
|
47
|
+
testCaseId = testCase.id;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error instanceof NotFoundError) {
|
|
51
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
52
|
+
}
|
|
53
|
+
throw new UnexpectedError(`Failed to look up test case ID from key '${request.testCaseKey}'. Ensure Zephyr Connector is configured.`, error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new UnexpectedError('Cannot look up test case ID from key. This method requires Zephyr Connector to be configured. Use createZephyrApi() with an API Connection.');
|
|
58
|
+
}
|
|
59
|
+
// Get Context JWT
|
|
60
|
+
const contextJwt = await this.getContextJwt(credentials);
|
|
61
|
+
const fields = 'id,issueId,url,urlDescription,type(id,index,name,i18nKey,systemKey),testCaseId,testRunId,testPlanId';
|
|
62
|
+
const url = `${this.privateApiBaseUrl}/testcase/${testCaseId}/tracelinks/issue?fields=${encodeURIComponent(fields)}`;
|
|
63
|
+
const headers = {
|
|
64
|
+
accept: 'application/json',
|
|
65
|
+
authorization: `JWT ${contextJwt}`,
|
|
66
|
+
'jira-project-id': String(request.projectId),
|
|
67
|
+
};
|
|
68
|
+
try {
|
|
69
|
+
const response = await fetch(url, {
|
|
70
|
+
method: 'GET',
|
|
71
|
+
headers,
|
|
72
|
+
});
|
|
73
|
+
if (!response.ok) {
|
|
74
|
+
if (response.status === 400) {
|
|
75
|
+
throw new BadRequestError('Invalid request parameters for getting issue links.');
|
|
76
|
+
}
|
|
77
|
+
if (response.status === 401) {
|
|
78
|
+
throw new UnauthorizedError('Failed to authenticate. Please check your credentials.');
|
|
79
|
+
}
|
|
80
|
+
if (response.status === 403) {
|
|
81
|
+
throw new ForbiddenError('Insufficient permissions to get issue links.');
|
|
82
|
+
}
|
|
83
|
+
if (response.status === 404) {
|
|
84
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
85
|
+
}
|
|
86
|
+
throw new ServerError(`Failed to get test case issue links. Status: ${response.status}`, response.status, response.statusText);
|
|
87
|
+
}
|
|
88
|
+
const privateLinks = (await response.json());
|
|
89
|
+
// Transform to public API format
|
|
90
|
+
const issueLinks = privateLinks.map((link) => {
|
|
91
|
+
// Build self URL (approximate format based on public API pattern)
|
|
92
|
+
const self = `/testcases/${request.testCaseKey}/links/issues/${link.id}`;
|
|
93
|
+
return {
|
|
94
|
+
id: link.id,
|
|
95
|
+
self,
|
|
96
|
+
issueId: Number(link.issueId),
|
|
97
|
+
target: `/issues/${link.issueId}`,
|
|
98
|
+
type: link.type.systemKey,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
return issueLinks;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error instanceof BadRequestError ||
|
|
105
|
+
error instanceof UnauthorizedError ||
|
|
106
|
+
error instanceof ForbiddenError ||
|
|
107
|
+
error instanceof NotFoundError ||
|
|
108
|
+
error instanceof ServerError ||
|
|
109
|
+
error instanceof UnexpectedError) {
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
throw new UnexpectedError('Unexpected error while getting test case issue links', error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get web links for a test case using private API (with version support)
|
|
117
|
+
*
|
|
118
|
+
* Retrieves all web links associated with a test case, optionally for a specific version.
|
|
119
|
+
* The response format matches the public API `getTestCaseLinks().webLinks` format.
|
|
120
|
+
*
|
|
121
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
122
|
+
* The endpoint may change or be removed at any time without notice.
|
|
123
|
+
*
|
|
124
|
+
* @param credentials - Private API credentials
|
|
125
|
+
* @param request - Get web links request
|
|
126
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1'). The numeric ID will be looked up automatically if Zephyr Connector is available.
|
|
127
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
128
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
129
|
+
* @returns Array of web links matching the public API format
|
|
130
|
+
* @throws {BadRequestError} If the request is invalid
|
|
131
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
132
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
133
|
+
* @throws {NotFoundError} If the test case is not found
|
|
134
|
+
* @throws {ServerError} If the server returns an error
|
|
135
|
+
* @throws {UnexpectedError} If test case ID cannot be looked up from key and Zephyr Connector is not available
|
|
136
|
+
*/
|
|
137
|
+
async getTestCaseWebLinks(credentials, request) {
|
|
138
|
+
// Get test case ID from key if we have API connection
|
|
139
|
+
let testCaseId;
|
|
140
|
+
if (this.testCaseGroup) {
|
|
141
|
+
try {
|
|
142
|
+
// If version is specified, get the versioned test case; otherwise get the current version
|
|
143
|
+
const testCase = request.version !== undefined && request.version > 0
|
|
144
|
+
? await this.testCaseGroup.getTestCaseVersion({
|
|
145
|
+
testCaseKey: request.testCaseKey,
|
|
146
|
+
version: request.version,
|
|
147
|
+
})
|
|
148
|
+
: await this.testCaseGroup.getTestCase({ testCaseKey: request.testCaseKey });
|
|
149
|
+
if (!testCase) {
|
|
150
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
151
|
+
}
|
|
152
|
+
testCaseId = testCase.id;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (error instanceof NotFoundError) {
|
|
156
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
157
|
+
}
|
|
158
|
+
throw new UnexpectedError(`Failed to look up test case ID from key '${request.testCaseKey}'. Ensure Zephyr Connector is configured.`, error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
throw new UnexpectedError('Cannot look up test case ID from key. This method requires Zephyr Connector to be configured. Use createZephyrApi() with an API Connection.');
|
|
163
|
+
}
|
|
164
|
+
// Get Context JWT
|
|
165
|
+
const contextJwt = await this.getContextJwt(credentials);
|
|
166
|
+
const fields = 'id,url,urlDescription,type(id,index,name,i18nKey,systemKey),testCaseId,testRunId,testPlanId';
|
|
167
|
+
const url = `${this.privateApiBaseUrl}/testcase/${testCaseId}/tracelinks/weblink?fields=${encodeURIComponent(fields)}`;
|
|
168
|
+
const headers = {
|
|
169
|
+
accept: 'application/json',
|
|
170
|
+
authorization: `JWT ${contextJwt}`,
|
|
171
|
+
'jira-project-id': String(request.projectId),
|
|
172
|
+
};
|
|
173
|
+
try {
|
|
174
|
+
const response = await fetch(url, {
|
|
175
|
+
method: 'GET',
|
|
176
|
+
headers,
|
|
177
|
+
});
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
if (response.status === 400) {
|
|
180
|
+
throw new BadRequestError('Invalid request parameters for getting web links.');
|
|
181
|
+
}
|
|
182
|
+
if (response.status === 401) {
|
|
183
|
+
throw new UnauthorizedError('Failed to authenticate. Please check your credentials.');
|
|
184
|
+
}
|
|
185
|
+
if (response.status === 403) {
|
|
186
|
+
throw new ForbiddenError('Insufficient permissions to get web links.');
|
|
187
|
+
}
|
|
188
|
+
if (response.status === 404) {
|
|
189
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
190
|
+
}
|
|
191
|
+
throw new ServerError(`Failed to get test case web links. Status: ${response.status}`, response.status, response.statusText);
|
|
192
|
+
}
|
|
193
|
+
const privateLinks = (await response.json());
|
|
194
|
+
// Transform to public API format
|
|
195
|
+
const webLinks = privateLinks.map((link) => {
|
|
196
|
+
// Build self URL (approximate format based on public API pattern)
|
|
197
|
+
const self = `/testcases/${request.testCaseKey}/links/weblinks/${link.id}`;
|
|
198
|
+
return {
|
|
199
|
+
id: link.id,
|
|
200
|
+
self,
|
|
201
|
+
url: link.url,
|
|
202
|
+
description: link.urlDescription || undefined,
|
|
203
|
+
type: link.type.systemKey,
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
return webLinks;
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
if (error instanceof BadRequestError ||
|
|
210
|
+
error instanceof UnauthorizedError ||
|
|
211
|
+
error instanceof ForbiddenError ||
|
|
212
|
+
error instanceof NotFoundError ||
|
|
213
|
+
error instanceof ServerError ||
|
|
214
|
+
error instanceof UnexpectedError) {
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
throw new UnexpectedError('Unexpected error while getting test case web links', error);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get test script for a test case using private API (with version support)
|
|
222
|
+
*
|
|
223
|
+
* Retrieves the test script associated with a test case, optionally for a specific version.
|
|
224
|
+
* The response format matches the public API `getTestCaseTestScript()` format.
|
|
225
|
+
*
|
|
226
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
227
|
+
* The endpoint may change or be removed at any time without notice.
|
|
228
|
+
*
|
|
229
|
+
* @param credentials - Private API credentials
|
|
230
|
+
* @param request - Get test script request
|
|
231
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1')
|
|
232
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
233
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
234
|
+
* @returns Test script matching the public API format, or null if no test script exists
|
|
235
|
+
* @throws {BadRequestError} If the request is invalid
|
|
236
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
237
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
238
|
+
* @throws {NotFoundError} If the test case is not found
|
|
239
|
+
* @throws {ServerError} If the server returns an error
|
|
240
|
+
* @throws {UnexpectedError} If test case cannot be retrieved
|
|
241
|
+
*/
|
|
242
|
+
async getTestCaseTestScript(credentials, request) {
|
|
243
|
+
// Get test case ID from key if we have API connection (for version support)
|
|
244
|
+
let testCaseId = request.testCaseKey;
|
|
245
|
+
if (this.testCaseGroup) {
|
|
246
|
+
try {
|
|
247
|
+
// If version is specified, get the versioned test case; otherwise get the current version
|
|
248
|
+
const testCase = request.version !== undefined && request.version > 0
|
|
249
|
+
? await this.testCaseGroup.getTestCaseVersion({
|
|
250
|
+
testCaseKey: request.testCaseKey,
|
|
251
|
+
version: request.version,
|
|
252
|
+
})
|
|
253
|
+
: await this.testCaseGroup.getTestCase({ testCaseKey: request.testCaseKey });
|
|
254
|
+
if (!testCase) {
|
|
255
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
256
|
+
}
|
|
257
|
+
// Use the ID for the private API call (works with both key and ID)
|
|
258
|
+
testCaseId = testCase.id;
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
if (error instanceof NotFoundError) {
|
|
262
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
263
|
+
}
|
|
264
|
+
throw new UnexpectedError(`Failed to look up test case ID from key '${request.testCaseKey}'. Ensure Zephyr Connector is configured.`, error);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Get Context JWT
|
|
268
|
+
const contextJwt = await this.getContextJwt(credentials);
|
|
269
|
+
// Build fields query to get test script
|
|
270
|
+
const fields = 'testScript(id,text,steps(index,reflectRef,description,text,expectedResult,testData,customFieldValues,attachments,id,stepParameters(id,testCaseParameterId,value),testCase(id,key,name,archived,majorVersion,latestVersion,projectKey,parameters(id,name,defaultValue,index))))';
|
|
271
|
+
const url = `${this.privateApiBaseUrl}/testcase/${testCaseId}?fields=${encodeURIComponent(fields)}`;
|
|
272
|
+
const headers = {
|
|
273
|
+
accept: 'application/json',
|
|
274
|
+
authorization: `JWT ${contextJwt}`,
|
|
275
|
+
'jira-project-id': String(request.projectId),
|
|
276
|
+
};
|
|
277
|
+
try {
|
|
278
|
+
const response = await fetch(url, {
|
|
279
|
+
method: 'GET',
|
|
280
|
+
headers,
|
|
281
|
+
});
|
|
282
|
+
if (!response.ok) {
|
|
283
|
+
if (response.status === 400) {
|
|
284
|
+
throw new BadRequestError('Invalid request parameters for getting test script.');
|
|
285
|
+
}
|
|
286
|
+
if (response.status === 401) {
|
|
287
|
+
throw new UnauthorizedError('Failed to authenticate. Please check your credentials.');
|
|
288
|
+
}
|
|
289
|
+
if (response.status === 403) {
|
|
290
|
+
throw new ForbiddenError('Insufficient permissions to get test script.');
|
|
291
|
+
}
|
|
292
|
+
if (response.status === 404) {
|
|
293
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
294
|
+
}
|
|
295
|
+
throw new ServerError(`Failed to get test case test script. Status: ${response.status}`, response.status, response.statusText);
|
|
296
|
+
}
|
|
297
|
+
const testCase = (await response.json());
|
|
298
|
+
// If no test script exists, return null
|
|
299
|
+
if (!testCase.testScript) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
// If it's a step-by-step script (has steps), it's not a plain/BDD script, return null
|
|
303
|
+
if (testCase.testScript.stepByStepScript) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
// If it has text, it's a plain text script
|
|
307
|
+
if (testCase.testScript.text) {
|
|
308
|
+
return {
|
|
309
|
+
id: testCase.testScript.id,
|
|
310
|
+
type: 'plain',
|
|
311
|
+
text: testCase.testScript.text,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
// No script found
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
if (error instanceof BadRequestError ||
|
|
319
|
+
error instanceof UnauthorizedError ||
|
|
320
|
+
error instanceof ForbiddenError ||
|
|
321
|
+
error instanceof NotFoundError ||
|
|
322
|
+
error instanceof ServerError ||
|
|
323
|
+
error instanceof UnexpectedError) {
|
|
324
|
+
throw error;
|
|
325
|
+
}
|
|
326
|
+
throw new UnexpectedError('Unexpected error while getting test case test script', error);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Get test steps for a test case using private API (with version support)
|
|
331
|
+
*
|
|
332
|
+
* Retrieves the test steps associated with a test case, optionally for a specific version.
|
|
333
|
+
* The response format matches the public API `getTestCaseTestSteps()` format.
|
|
334
|
+
*
|
|
335
|
+
* ⚠️ WARNING: This uses a private Zephyr API endpoint that is not officially supported.
|
|
336
|
+
* The endpoint may change or be removed at any time without notice.
|
|
337
|
+
*
|
|
338
|
+
* @param credentials - Private API credentials
|
|
339
|
+
* @param request - Get test steps request
|
|
340
|
+
* @param request.testCaseKey - Test case key (e.g., 'PROJ-T1')
|
|
341
|
+
* @param request.projectId - Jira project ID (numeric, not the project key)
|
|
342
|
+
* @param request.version - Optional version number (relative to current version, where 1 = current/latest version, 2 = previous version, 3 = version before that, etc.). If not provided, uses the latest version (same as version: 1).
|
|
343
|
+
* @returns Test steps list matching the public API format
|
|
344
|
+
* @throws {BadRequestError} If the request is invalid
|
|
345
|
+
* @throws {UnauthorizedError} If authentication fails
|
|
346
|
+
* @throws {ForbiddenError} If the user doesn't have permission
|
|
347
|
+
* @throws {NotFoundError} If the test case is not found
|
|
348
|
+
* @throws {ServerError} If the server returns an error
|
|
349
|
+
* @throws {UnexpectedError} If test case cannot be retrieved
|
|
350
|
+
*/
|
|
351
|
+
async getTestCaseTestSteps(credentials, request) {
|
|
352
|
+
// Get test case ID from key if we have API connection (for version support)
|
|
353
|
+
let testCaseId = request.testCaseKey;
|
|
354
|
+
if (this.testCaseGroup) {
|
|
355
|
+
try {
|
|
356
|
+
// If version is specified, get the versioned test case; otherwise get the current version
|
|
357
|
+
const testCase = request.version !== undefined && request.version > 0
|
|
358
|
+
? await this.testCaseGroup.getTestCaseVersion({
|
|
359
|
+
testCaseKey: request.testCaseKey,
|
|
360
|
+
version: request.version,
|
|
361
|
+
})
|
|
362
|
+
: await this.testCaseGroup.getTestCase({ testCaseKey: request.testCaseKey });
|
|
363
|
+
if (!testCase) {
|
|
364
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
365
|
+
}
|
|
366
|
+
// Use the ID for the private API call (works with both key and ID)
|
|
367
|
+
testCaseId = testCase.id;
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
if (error instanceof NotFoundError) {
|
|
371
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
372
|
+
}
|
|
373
|
+
throw new UnexpectedError(`Failed to look up test case ID from key '${request.testCaseKey}'. Ensure Zephyr Connector is configured.`, error);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Get Context JWT
|
|
377
|
+
const contextJwt = await this.getContextJwt(credentials);
|
|
378
|
+
// Build fields query to get test steps
|
|
379
|
+
const fields = 'testScript(id,text,steps(index,reflectRef,description,text,expectedResult,testData,customFieldValues,attachments,id,stepParameters(id,testCaseParameterId,value),testCase(id,key,name,archived,majorVersion,latestVersion,projectKey,parameters(id,name,defaultValue,index))))';
|
|
380
|
+
const url = `${this.privateApiBaseUrl}/testcase/${testCaseId}?fields=${encodeURIComponent(fields)}`;
|
|
381
|
+
const headers = {
|
|
382
|
+
accept: 'application/json',
|
|
383
|
+
authorization: `JWT ${contextJwt}`,
|
|
384
|
+
'jira-project-id': String(request.projectId),
|
|
385
|
+
};
|
|
386
|
+
try {
|
|
387
|
+
const response = await fetch(url, {
|
|
388
|
+
method: 'GET',
|
|
389
|
+
headers,
|
|
390
|
+
});
|
|
391
|
+
if (!response.ok) {
|
|
392
|
+
if (response.status === 400) {
|
|
393
|
+
throw new BadRequestError('Invalid request parameters for getting test steps.');
|
|
394
|
+
}
|
|
395
|
+
if (response.status === 401) {
|
|
396
|
+
throw new UnauthorizedError('Failed to authenticate. Please check your credentials.');
|
|
397
|
+
}
|
|
398
|
+
if (response.status === 403) {
|
|
399
|
+
throw new ForbiddenError('Insufficient permissions to get test steps.');
|
|
400
|
+
}
|
|
401
|
+
if (response.status === 404) {
|
|
402
|
+
throw new NotFoundError(`Test case with key '${request.testCaseKey}'${request.version !== undefined && request.version > 0 ? ` version ${request.version}` : ''} not found.`);
|
|
403
|
+
}
|
|
404
|
+
throw new ServerError(`Failed to get test case test steps. Status: ${response.status}`, response.status, response.statusText);
|
|
405
|
+
}
|
|
406
|
+
const testCase = (await response.json());
|
|
407
|
+
// If no test script or no step-by-step script exists, return empty list
|
|
408
|
+
if (!testCase.testScript || !testCase.testScript.stepByStepScript || !testCase.testScript.stepByStepScript.steps) {
|
|
409
|
+
return {
|
|
410
|
+
values: [],
|
|
411
|
+
total: 0,
|
|
412
|
+
maxResults: 0,
|
|
413
|
+
startAt: 0,
|
|
414
|
+
isLast: true,
|
|
415
|
+
next: null,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const privateSteps = testCase.testScript.stepByStepScript.steps;
|
|
419
|
+
// Transform to public API format
|
|
420
|
+
const testSteps = privateSteps.map((step) => {
|
|
421
|
+
const inline = {
|
|
422
|
+
description: step.description || '',
|
|
423
|
+
testData: step.testData || undefined,
|
|
424
|
+
expectedResult: step.expectedResult || '',
|
|
425
|
+
reflectRef: step.reflectRef || undefined,
|
|
426
|
+
// Note: customFieldValues transformation would require more complex logic
|
|
427
|
+
// For now, we'll skip it as it's not in the public API TestStepInline type
|
|
428
|
+
};
|
|
429
|
+
return {
|
|
430
|
+
inline,
|
|
431
|
+
};
|
|
432
|
+
});
|
|
433
|
+
return {
|
|
434
|
+
values: testSteps,
|
|
435
|
+
total: testSteps.length,
|
|
436
|
+
maxResults: testSteps.length,
|
|
437
|
+
startAt: 0,
|
|
438
|
+
isLast: true,
|
|
439
|
+
next: null,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
if (error instanceof BadRequestError ||
|
|
444
|
+
error instanceof UnauthorizedError ||
|
|
445
|
+
error instanceof ForbiddenError ||
|
|
446
|
+
error instanceof NotFoundError ||
|
|
447
|
+
error instanceof ServerError ||
|
|
448
|
+
error instanceof UnexpectedError) {
|
|
449
|
+
throw error;
|
|
450
|
+
}
|
|
451
|
+
throw new UnexpectedError('Unexpected error while getting test case test steps', error);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
package/dist/groups/Private.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { PrivateConfig } from './Private/PrivateConfig';
|
|
|
8
8
|
import { PrivateVersions } from './Private/PrivateVersions';
|
|
9
9
|
import { PrivateAttachments } from './Private/PrivateAttachments';
|
|
10
10
|
import { PrivateAuthentication } from './Private/PrivateAuthentication';
|
|
11
|
+
import { PrivateVersionControl } from './Private/PrivateVersionControl';
|
|
11
12
|
/**
|
|
12
13
|
* Private API group for accessing Zephyr's private/unofficial endpoints
|
|
13
14
|
*
|
|
@@ -35,6 +36,10 @@ export declare class PrivateGroup extends PrivateBase {
|
|
|
35
36
|
* Attachments sub-group - Get, download, and create attachments
|
|
36
37
|
*/
|
|
37
38
|
readonly Attachments: PrivateAttachments;
|
|
39
|
+
/**
|
|
40
|
+
* Version Control sub-group - Get version-specific data (links, test script, test steps)
|
|
41
|
+
*/
|
|
42
|
+
readonly VersionControl: PrivateVersionControl;
|
|
38
43
|
constructor(apiConnection?: ZephyrApiConnection);
|
|
39
44
|
}
|
|
40
45
|
//# sourceMappingURL=Private.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Private.d.ts","sourceRoot":"","sources":["../../groups/Private.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyDH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AASxE;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,WAAW;IAC5C;;OAEG;IACH,SAAgB,cAAc,EAAE,qBAAqB,CAAC;IAEtD;;OAEG;IACH,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAE1C;;OAEG;IACH,SAAgB,MAAM,EAAE,aAAa,CAAC;IAEtC;;OAEG;IACH,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAE1C;;OAEG;IACH,SAAgB,WAAW,EAAE,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Private.d.ts","sourceRoot":"","sources":["../../groups/Private.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyDH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AASxE;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,WAAW;IAC5C;;OAEG;IACH,SAAgB,cAAc,EAAE,qBAAqB,CAAC;IAEtD;;OAEG;IACH,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAE1C;;OAEG;IACH,SAAgB,MAAM,EAAE,aAAa,CAAC;IAEtC;;OAEG;IACH,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAE1C;;OAEG;IACH,SAAgB,WAAW,EAAE,kBAAkB,CAAC;IAEhD;;OAEG;IACH,SAAgB,cAAc,EAAE,qBAAqB,CAAC;gBAE1C,aAAa,CAAC,EAAE,mBAAmB;CAU/C"}
|
package/dist/groups/Private.js
CHANGED
|
@@ -7,6 +7,7 @@ import { PrivateConfig } from './Private/PrivateConfig';
|
|
|
7
7
|
import { PrivateVersions } from './Private/PrivateVersions';
|
|
8
8
|
import { PrivateAttachments } from './Private/PrivateAttachments';
|
|
9
9
|
import { PrivateAuthentication } from './Private/PrivateAuthentication';
|
|
10
|
+
import { PrivateVersionControl } from './Private/PrivateVersionControl';
|
|
10
11
|
/**
|
|
11
12
|
* Private API group for accessing Zephyr's private/unofficial endpoints
|
|
12
13
|
*
|
|
@@ -21,5 +22,6 @@ export class PrivateGroup extends PrivateBase {
|
|
|
21
22
|
this.Config = new PrivateConfig(apiConnection);
|
|
22
23
|
this.Versions = new PrivateVersions(apiConnection);
|
|
23
24
|
this.Attachments = new PrivateAttachments(apiConnection);
|
|
25
|
+
this.VersionControl = new PrivateVersionControl(apiConnection);
|
|
24
26
|
}
|
|
25
27
|
}
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rbaileysr/zephyr-managed-api",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Managed API wrapper for Zephyr Cloud REST API v2 - Comprehensive type-safe access to all Zephyr API endpoints for ScriptRunner Connect",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|