@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.
@@ -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
+ }
@@ -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;gBAEpC,aAAa,CAAC,EAAE,mBAAmB;CAS/C"}
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"}
@@ -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.1",
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",