targetprocess-mcp-server 2.2.3 → 2.2.4
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 +1 -0
- package/build/index.js +36 -49
- package/build/tp.js +50 -59
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ Features
|
|
|
46
46
|
- `get_not_covered_user_stories_in_feature` — Get user stories in a feature not yet covered by tests, includes `covered` field based on "Test Automation" custom field (id)
|
|
47
47
|
|
|
48
48
|
Cards — Read
|
|
49
|
+
- `get_card_status` — Get EntityState, TeamState, and assigned teams for a card (id, optional resourceType: UserStory | Bug | Feature, default: UserStory)
|
|
49
50
|
- `get_bug_content` — Fetch full content of a bug by ID (id)
|
|
50
51
|
- `get_user_story_content` — Fetch full content of a user story by ID (id)
|
|
51
52
|
- `get_bug_comments` — Get comments on a bug (id, optional results)
|
package/build/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { z } from "zod";
|
|
|
4
4
|
import { JSDOM } from "jsdom";
|
|
5
5
|
import { TpClient } from "./tp.js";
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { config } from "./config.js";
|
|
7
8
|
const server = new McpServer({
|
|
8
9
|
name: "tp",
|
|
9
10
|
version: "1.0.0"
|
|
@@ -374,6 +375,7 @@ server.registerTool('search_tp_cards', {
|
|
|
374
375
|
title: item.Name,
|
|
375
376
|
id: item.Id,
|
|
376
377
|
description: descriptionText,
|
|
378
|
+
url: `${config.tp.url}/entity/${item.Id}`,
|
|
377
379
|
};
|
|
378
380
|
});
|
|
379
381
|
return {
|
|
@@ -598,11 +600,13 @@ server.registerTool('create_bug_based_on_card', {
|
|
|
598
600
|
title: 'Create a new bug card based on provided card id',
|
|
599
601
|
description: `Create a new bug card based on provided card id that summarizes the problem in concise, descriptive manner answering questions What? Where? When?, and content explaining what happened in detail.
|
|
600
602
|
NOTE: this tool requires a user story or bug card as a reference (i.e. card ID).
|
|
601
|
-
CRITICAL WORKFLOW: Before calling this tool, you MUST follow these steps:
|
|
603
|
+
CRITICAL WORKFLOW: Before calling this tool, you MUST follow these steps:
|
|
602
604
|
1) IF you already have user story or bug card content, proceed to step 3 skipping step 2;
|
|
603
605
|
2) ELSE call "get_user_story_content" tool or "get_bug_content" tool to get user story or bug card content;
|
|
604
606
|
3) format the new bug inside html <div> tags with Issue Description, Steps to Reproduce, Expected Behavior, Actual Behavior sections (note: section titles should be wrapped in <h3> tags, e.g. <h3>Issue Description</h3>);
|
|
605
|
-
4)
|
|
607
|
+
4) IF the user specified a team by name (not ID), call "get_teams" to find the matching team and use its ID as teamId;
|
|
608
|
+
5) IF the user specified a project by name (not ID), call "get_projects" to find the matching project and use its ID as projectId;
|
|
609
|
+
6) add a comment to the card with created bug Id and its Title`,
|
|
606
610
|
inputSchema: {
|
|
607
611
|
title: z.string()
|
|
608
612
|
.describe('Bug card title that summarizes the problem in concise, descriptive, and actionable manner, enabling a developer to understand the issue without opening the report'),
|
|
@@ -635,10 +639,10 @@ server.registerTool('create_bug_based_on_card', {
|
|
|
635
639
|
.describe('Where the bug was found, defaults to "Manual QA"'),
|
|
636
640
|
projectId: z.string()
|
|
637
641
|
.optional()
|
|
638
|
-
.describe('Optional Project ID — defaults to TP_PROJECT_ID from config'),
|
|
642
|
+
.describe('Optional Project ID — if user gave a project name, resolve it via "get_projects" first; defaults to TP_PROJECT_ID from config'),
|
|
639
643
|
teamId: z.string()
|
|
640
644
|
.optional()
|
|
641
|
-
.describe('Optional Team ID — defaults to TP_TEAM_ID from config'),
|
|
645
|
+
.describe('Optional Team ID — if user gave a team name, resolve it via "get_teams" first; defaults to TP_TEAM_ID from config'),
|
|
642
646
|
},
|
|
643
647
|
}, async ({ title, card, bugContent, origin, projectId, teamId }) => {
|
|
644
648
|
const bugResponse = await tp.createBug({ title, card, bugContent, origin, projectId, teamId });
|
|
@@ -662,7 +666,9 @@ server.registerTool('create_bug', {
|
|
|
662
666
|
description: `Create a new bug card that summarizes the problem in concise, descriptive manner answering questions "What? Where? When?" and content explaining what happened in detail.
|
|
663
667
|
NOTE: this tool does not require a user story or bug card reference.
|
|
664
668
|
CRITICAL WORKFLOW: Before calling this tool, you MUST follow these steps:
|
|
665
|
-
1) format the new bug inside html <div> tags with Issue Description, Steps to Reproduce, Expected Behavior, Actual Behavior sections (note: section titles should be wrapped in <h3> tags, e.g. <h3>Issue Description</h3>)
|
|
669
|
+
1) format the new bug inside html <div> tags with Issue Description, Steps to Reproduce, Expected Behavior, Actual Behavior sections (note: section titles should be wrapped in <h3> tags, e.g. <h3>Issue Description</h3>, step to reproduce should be wrapped in <ol>);
|
|
670
|
+
2) IF the user specified a team by name (not ID), call "get_teams" to find the matching team and use its ID as teamId;
|
|
671
|
+
3) IF the user specified a project by name (not ID), call "get_projects" to find the matching project and use its ID as projectId;`,
|
|
666
672
|
inputSchema: {
|
|
667
673
|
title: z.string()
|
|
668
674
|
.describe('Bug card title that summarizes the problem in concise, descriptive, and actionable manner, enabling a developer to understand the issue without opening the report'),
|
|
@@ -684,10 +690,10 @@ server.registerTool('create_bug', {
|
|
|
684
690
|
.describe('Where the bug was found, defaults to "Manual QA"'),
|
|
685
691
|
projectId: z.string()
|
|
686
692
|
.optional()
|
|
687
|
-
.describe('Optional Project ID — defaults to TP_PROJECT_ID from config'),
|
|
693
|
+
.describe('Optional Project ID — if user gave a project name, resolve it via "get_projects" first; defaults to TP_PROJECT_ID from config'),
|
|
688
694
|
teamId: z.string()
|
|
689
695
|
.optional()
|
|
690
|
-
.describe('Optional Team ID — defaults to TP_TEAM_ID from config'),
|
|
696
|
+
.describe('Optional Team ID — if user gave a team name, resolve it via "get_teams" first; defaults to TP_TEAM_ID from config'),
|
|
691
697
|
},
|
|
692
698
|
}, async ({ title, bugContent, origin, projectId, teamId }) => {
|
|
693
699
|
const bugResponse = await tp.createBugOnly({ title, bugContent, origin, projectId, teamId });
|
|
@@ -1238,63 +1244,44 @@ server.registerTool('add_test_cases_to_test_plan', {
|
|
|
1238
1244
|
}]
|
|
1239
1245
|
};
|
|
1240
1246
|
});
|
|
1241
|
-
server.registerTool('
|
|
1242
|
-
title: '
|
|
1243
|
-
description:
|
|
1244
|
-
1) fileContent + fileName — provide base64-encoded file content and a filename (use this when the file was uploaded directly into the chat)
|
|
1245
|
-
WORKFLOW for chat-uploaded files: run \`base64 <path>\` via Bash to get the encoded content, then call this tool with fileContent + fileName.`,
|
|
1247
|
+
server.registerTool('get_card_status', {
|
|
1248
|
+
title: 'Get card status',
|
|
1249
|
+
description: 'Get the EntityState, TeamState, and assigned teams for a TP card (UserStory, Bug, or Feature) by ID',
|
|
1246
1250
|
inputSchema: {
|
|
1247
|
-
|
|
1251
|
+
id: z.string()
|
|
1248
1252
|
.min(5)
|
|
1249
1253
|
.max(6)
|
|
1250
|
-
.describe('TP
|
|
1251
|
-
|
|
1252
|
-
.
|
|
1253
|
-
.describe('Absolute path to a local file (mode 1). Mutually exclusive with fileContent/fileName.'),
|
|
1254
|
-
fileContent: z.string()
|
|
1255
|
-
.optional()
|
|
1256
|
-
.describe('Base64-encoded file content (mode 2). Must be paired with fileName.'),
|
|
1257
|
-
fileName: z.string()
|
|
1254
|
+
.describe('TP card ID (e.g. 146055)'),
|
|
1255
|
+
resourceType: z.enum(['UserStory', 'Bug', 'Feature'])
|
|
1256
|
+
.default('UserStory')
|
|
1258
1257
|
.optional()
|
|
1259
|
-
.describe('
|
|
1258
|
+
.describe('Type of the TP card — UserStory, Bug, or Feature (default: UserStory)'),
|
|
1260
1259
|
},
|
|
1261
|
-
}, async ({
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
return {
|
|
1265
|
-
content: [{
|
|
1266
|
-
type: 'text',
|
|
1267
|
-
text: 'Provide either filePath, or both fileContent and fileName.'
|
|
1268
|
-
}]
|
|
1269
|
-
};
|
|
1270
|
-
}
|
|
1271
|
-
const source = filePath
|
|
1272
|
-
? { filePath }
|
|
1273
|
-
: { fileContent: fileContent, fileName: fileName };
|
|
1274
|
-
const result = await tp.addAttachedFile(generalId, source);
|
|
1275
|
-
if (!result) {
|
|
1276
|
-
return {
|
|
1277
|
-
content: [{
|
|
1278
|
-
type: 'text',
|
|
1279
|
-
text: `Failed to attach file to card id: ${generalId}`
|
|
1280
|
-
}]
|
|
1281
|
-
};
|
|
1282
|
-
}
|
|
1260
|
+
}, async ({ id, resourceType = 'UserStory' }) => {
|
|
1261
|
+
const response = await tp.getCardStatus(id, resourceType);
|
|
1262
|
+
if (!response) {
|
|
1283
1263
|
return {
|
|
1284
1264
|
content: [{
|
|
1285
1265
|
type: 'text',
|
|
1286
|
-
text:
|
|
1287
|
-
}]
|
|
1266
|
+
text: `Failed to get card status for ${resourceType} id: ${id}`
|
|
1267
|
+
}],
|
|
1288
1268
|
};
|
|
1289
1269
|
}
|
|
1290
|
-
|
|
1270
|
+
const items = response.items || [];
|
|
1271
|
+
if (items.length === 0) {
|
|
1291
1272
|
return {
|
|
1292
1273
|
content: [{
|
|
1293
1274
|
type: 'text',
|
|
1294
|
-
text: `
|
|
1295
|
-
}]
|
|
1275
|
+
text: `No status data found for ${resourceType} id: ${id}`,
|
|
1276
|
+
}],
|
|
1296
1277
|
};
|
|
1297
1278
|
}
|
|
1279
|
+
return {
|
|
1280
|
+
content: [{
|
|
1281
|
+
type: 'text',
|
|
1282
|
+
text: JSON.stringify(items[0])
|
|
1283
|
+
}],
|
|
1284
|
+
};
|
|
1298
1285
|
});
|
|
1299
1286
|
async function main() {
|
|
1300
1287
|
const transport = new StdioServerTransport();
|
package/build/tp.js
CHANGED
|
@@ -15,8 +15,8 @@ export class TpClient {
|
|
|
15
15
|
}
|
|
16
16
|
params(params) {
|
|
17
17
|
let _url = this.baseUrl + (params.apiVersion || this.v1);
|
|
18
|
-
for (const
|
|
19
|
-
_url +=
|
|
18
|
+
for (const segment of params.pathParam) {
|
|
19
|
+
_url += `/${segment}`;
|
|
20
20
|
}
|
|
21
21
|
let _urlParams = [];
|
|
22
22
|
for (const [key, value] of Object.entries(params.param)) {
|
|
@@ -83,21 +83,21 @@ export class TpClient {
|
|
|
83
83
|
}
|
|
84
84
|
async getUserStory(userStoryId) {
|
|
85
85
|
const response = await this.get({
|
|
86
|
-
pathParam:
|
|
86
|
+
pathParam: ["userStories", userStoryId],
|
|
87
87
|
param: { "format": "json" },
|
|
88
88
|
});
|
|
89
89
|
return response;
|
|
90
90
|
}
|
|
91
91
|
async getBug(bugId) {
|
|
92
92
|
const response = await this.get({
|
|
93
|
-
pathParam:
|
|
93
|
+
pathParam: ["bugs", bugId],
|
|
94
94
|
param: { "format": "json" }
|
|
95
95
|
});
|
|
96
96
|
return response;
|
|
97
97
|
}
|
|
98
98
|
async getFeature(featureId) {
|
|
99
99
|
const response = await this.get({
|
|
100
|
-
pathParam:
|
|
100
|
+
pathParam: ["features", featureId],
|
|
101
101
|
param: { "format": "json" }
|
|
102
102
|
});
|
|
103
103
|
return response;
|
|
@@ -126,7 +126,7 @@ export class TpClient {
|
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
128
|
return this.post({
|
|
129
|
-
pathParam:
|
|
129
|
+
pathParam: ["bugs"],
|
|
130
130
|
param: { "format": "json" },
|
|
131
131
|
}, bug);
|
|
132
132
|
}
|
|
@@ -149,7 +149,7 @@ export class TpClient {
|
|
|
149
149
|
"Description": bugContent,
|
|
150
150
|
};
|
|
151
151
|
return this.post({
|
|
152
|
-
pathParam:
|
|
152
|
+
pathParam: ["bugs"],
|
|
153
153
|
param: { "format": "json" },
|
|
154
154
|
}, bug);
|
|
155
155
|
}
|
|
@@ -166,7 +166,7 @@ export class TpClient {
|
|
|
166
166
|
if (releaseId)
|
|
167
167
|
userStory["Release"] = { "Id": releaseId };
|
|
168
168
|
return this.post({
|
|
169
|
-
pathParam:
|
|
169
|
+
pathParam: ["UserStories"],
|
|
170
170
|
param: { "format": "json" },
|
|
171
171
|
}, userStory);
|
|
172
172
|
}
|
|
@@ -183,7 +183,7 @@ export class TpClient {
|
|
|
183
183
|
if (releaseId)
|
|
184
184
|
feature["Release"] = { "Id": releaseId };
|
|
185
185
|
return this.post({
|
|
186
|
-
pathParam:
|
|
186
|
+
pathParam: ["Features"],
|
|
187
187
|
param: { "format": "json" },
|
|
188
188
|
}, feature);
|
|
189
189
|
}
|
|
@@ -209,7 +209,7 @@ export class TpClient {
|
|
|
209
209
|
"Description": bugContent,
|
|
210
210
|
};
|
|
211
211
|
return this.post({
|
|
212
|
-
pathParam:
|
|
212
|
+
pathParam: ["bugs"],
|
|
213
213
|
param: { "format": "json" },
|
|
214
214
|
}, bug);
|
|
215
215
|
}
|
|
@@ -223,7 +223,7 @@ export class TpClient {
|
|
|
223
223
|
}],
|
|
224
224
|
};
|
|
225
225
|
return this.post({
|
|
226
|
-
pathParam:
|
|
226
|
+
pathParam: ["testCases"],
|
|
227
227
|
param: { "format": "json" },
|
|
228
228
|
}, testCase);
|
|
229
229
|
}
|
|
@@ -260,7 +260,7 @@ export class TpClient {
|
|
|
260
260
|
if (options?.endDate)
|
|
261
261
|
testPlan["EndDate"] = options.endDate;
|
|
262
262
|
return this.post({
|
|
263
|
-
pathParam:
|
|
263
|
+
pathParam: ["testPlans"],
|
|
264
264
|
param: { "format": "json" },
|
|
265
265
|
}, testPlan);
|
|
266
266
|
}
|
|
@@ -275,7 +275,7 @@ export class TpClient {
|
|
|
275
275
|
},
|
|
276
276
|
};
|
|
277
277
|
return this.post({
|
|
278
|
-
pathParam:
|
|
278
|
+
pathParam: ["comments"],
|
|
279
279
|
param: { "format": "json" },
|
|
280
280
|
}, commentData);
|
|
281
281
|
}
|
|
@@ -286,16 +286,13 @@ export class TpClient {
|
|
|
286
286
|
"TestCase": { "Id": testCaseId },
|
|
287
287
|
};
|
|
288
288
|
return this.post({
|
|
289
|
-
pathParam:
|
|
289
|
+
pathParam: ["testSteps"],
|
|
290
290
|
param: { "format": "json" },
|
|
291
291
|
}, testStepData);
|
|
292
292
|
}
|
|
293
293
|
async getBugComments(bugId, results = 25) {
|
|
294
294
|
const response = await this.get({
|
|
295
|
-
pathParam:
|
|
296
|
-
"Bugs": bugId,
|
|
297
|
-
"Comments": "",
|
|
298
|
-
},
|
|
295
|
+
pathParam: ["Bugs", bugId, "Comments"],
|
|
299
296
|
param: {
|
|
300
297
|
"format": "json",
|
|
301
298
|
"take": results,
|
|
@@ -305,10 +302,7 @@ export class TpClient {
|
|
|
305
302
|
}
|
|
306
303
|
async getUserStoryComments(userStoryId, results = 25) {
|
|
307
304
|
const response = await this.get({
|
|
308
|
-
pathParam:
|
|
309
|
-
"UserStories": userStoryId,
|
|
310
|
-
"Comments": "",
|
|
311
|
-
},
|
|
305
|
+
pathParam: ["UserStories", userStoryId, "Comments"],
|
|
312
306
|
param: {
|
|
313
307
|
"format": "json",
|
|
314
308
|
"take": results,
|
|
@@ -318,7 +312,7 @@ export class TpClient {
|
|
|
318
312
|
}
|
|
319
313
|
async searchContainsNameText({ text, entityType }) {
|
|
320
314
|
return this.get({
|
|
321
|
-
pathParam:
|
|
315
|
+
pathParam: [entityType],
|
|
322
316
|
param: {
|
|
323
317
|
"format": "json",
|
|
324
318
|
"take": "25",
|
|
@@ -329,7 +323,7 @@ export class TpClient {
|
|
|
329
323
|
}
|
|
330
324
|
async searchContainsDescriptionText({ text, entityType }) {
|
|
331
325
|
return this.get({
|
|
332
|
-
pathParam:
|
|
326
|
+
pathParam: [entityType],
|
|
333
327
|
param: {
|
|
334
328
|
"where": `Description contains '${text}' and EntityState.Name eq 'Done'`,
|
|
335
329
|
"format": "json",
|
|
@@ -339,7 +333,7 @@ export class TpClient {
|
|
|
339
333
|
}
|
|
340
334
|
async getCurrentReleases() {
|
|
341
335
|
return this.get({
|
|
342
|
-
pathParam:
|
|
336
|
+
pathParam: ["Releases"],
|
|
343
337
|
param: {
|
|
344
338
|
"format": "json",
|
|
345
339
|
"where": `IsCurrent eq 'true'`,
|
|
@@ -349,7 +343,7 @@ export class TpClient {
|
|
|
349
343
|
async getReleaseUserStories({ name, results = 50, withDescription = false }) {
|
|
350
344
|
const includeFilter = withDescription ? "[Name, Description, Id]" : "[Name, Id]";
|
|
351
345
|
return this.get({
|
|
352
|
-
pathParam:
|
|
346
|
+
pathParam: ["UserStories"],
|
|
353
347
|
param: {
|
|
354
348
|
"format": "json",
|
|
355
349
|
"take": results,
|
|
@@ -361,11 +355,11 @@ export class TpClient {
|
|
|
361
355
|
async getReleaseOpenUserStories({ name, results = 100, withDescription = false }) {
|
|
362
356
|
const includeFilter = withDescription ? "[Name, Description, Id]" : "[Name, Id]";
|
|
363
357
|
return this.get({
|
|
364
|
-
pathParam:
|
|
358
|
+
pathParam: ["UserStories"],
|
|
365
359
|
param: {
|
|
366
360
|
"format": "json",
|
|
367
361
|
"take": results,
|
|
368
|
-
"where": `Release.Name eq '${name}' and EntityState.Name ne 'Closed' and EntityState.Name ne 'Done' and EntityState.Name ne 'Passed Dev01
|
|
362
|
+
"where": `Release.Name eq '${name}' and EntityState.Name ne 'Closed' and EntityState.Name ne 'Done' and EntityState.Name ne 'Passed Dev01 QA' and EntityState.Name ne 'Ready to Deploy to prod'`,
|
|
369
363
|
"include": includeFilter,
|
|
370
364
|
}
|
|
371
365
|
});
|
|
@@ -373,11 +367,11 @@ export class TpClient {
|
|
|
373
367
|
async getReleaseOpenBugs({ name, results = 200, withDescription = false }) {
|
|
374
368
|
const includeFilter = withDescription ? "[Name, Description, Id]" : "[Name, Id]";
|
|
375
369
|
return this.get({
|
|
376
|
-
pathParam:
|
|
370
|
+
pathParam: ["Bugs"],
|
|
377
371
|
param: {
|
|
378
372
|
"format": "json",
|
|
379
373
|
"take": results,
|
|
380
|
-
"where": `Release.Name eq '${name}' and EntityState.Name ne 'Closed' and EntityState.Name ne 'Done' and EntityState.Name ne 'Passed Dev01
|
|
374
|
+
"where": `Release.Name eq '${name}' and EntityState.Name ne 'Closed' and EntityState.Name ne 'Done' and EntityState.Name ne 'Passed Dev01 QA' and EntityState.Name ne 'Ready to Deploy to prod'`,
|
|
381
375
|
"include": includeFilter,
|
|
382
376
|
}
|
|
383
377
|
});
|
|
@@ -385,7 +379,7 @@ export class TpClient {
|
|
|
385
379
|
async getReleaseBugs({ name, results = 100, withDescription = false }) {
|
|
386
380
|
const includeFilter = withDescription ? "[Name, Description, Id]" : "[Name, Id]";
|
|
387
381
|
return this.get({
|
|
388
|
-
pathParam:
|
|
382
|
+
pathParam: ["Bugs"],
|
|
389
383
|
param: {
|
|
390
384
|
"format": "json",
|
|
391
385
|
"take": results,
|
|
@@ -397,7 +391,7 @@ export class TpClient {
|
|
|
397
391
|
async getReleaseFeatures({ name, results = 50, withDescription = false }) {
|
|
398
392
|
const includeFilter = withDescription ? "[Name, Description, Id]" : "[Name, Id]";
|
|
399
393
|
return this.get({
|
|
400
|
-
pathParam:
|
|
394
|
+
pathParam: ["Features"],
|
|
401
395
|
param: {
|
|
402
396
|
"format": "json",
|
|
403
397
|
"take": results,
|
|
@@ -408,7 +402,7 @@ export class TpClient {
|
|
|
408
402
|
}
|
|
409
403
|
async getFeatureUserStories(featureId) {
|
|
410
404
|
return this.get({
|
|
411
|
-
pathParam:
|
|
405
|
+
pathParam: ["features"],
|
|
412
406
|
param: {
|
|
413
407
|
"format": "json",
|
|
414
408
|
"where": `(id==${featureId})`,
|
|
@@ -419,7 +413,7 @@ export class TpClient {
|
|
|
419
413
|
}
|
|
420
414
|
async getUserStoriesIdsByFeatureId(featureId) {
|
|
421
415
|
return this.get({
|
|
422
|
-
pathParam:
|
|
416
|
+
pathParam: ["userstories"],
|
|
423
417
|
param: {
|
|
424
418
|
"format": "json",
|
|
425
419
|
"where": `(Feature.Id==${featureId})`,
|
|
@@ -430,7 +424,7 @@ export class TpClient {
|
|
|
430
424
|
}
|
|
431
425
|
async getUserStoryTestPlan(userStoryId) {
|
|
432
426
|
return this.get({
|
|
433
|
-
pathParam:
|
|
427
|
+
pathParam: ["userStories", userStoryId],
|
|
434
428
|
param: {
|
|
435
429
|
"format": "json",
|
|
436
430
|
"select": `{id,storyName:name,linkedtestplan}`,
|
|
@@ -439,18 +433,9 @@ export class TpClient {
|
|
|
439
433
|
});
|
|
440
434
|
}
|
|
441
435
|
async getCardTestPlan(cardId, resourceType = 'UserStory') {
|
|
442
|
-
|
|
443
|
-
if (resourceType === 'UserStory') {
|
|
444
|
-
requestPath = "userStories";
|
|
445
|
-
}
|
|
446
|
-
else if (resourceType === 'Bug') {
|
|
447
|
-
requestPath = "bugs";
|
|
448
|
-
}
|
|
449
|
-
else if (resourceType === 'Feature') {
|
|
450
|
-
requestPath = "features";
|
|
451
|
-
}
|
|
436
|
+
const pathMap = { UserStory: "userStories", Bug: "bugs", Feature: "features" };
|
|
452
437
|
return this.get({
|
|
453
|
-
pathParam:
|
|
438
|
+
pathParam: [pathMap[resourceType], cardId],
|
|
454
439
|
param: {
|
|
455
440
|
"format": "json",
|
|
456
441
|
"select": `{id,linkedtestplan}`,
|
|
@@ -459,38 +444,44 @@ export class TpClient {
|
|
|
459
444
|
}
|
|
460
445
|
async getTestPlanTestCases(testPlanId) {
|
|
461
446
|
return this.get({
|
|
462
|
-
pathParam:
|
|
463
|
-
"testPlans": testPlanId,
|
|
464
|
-
"testcases": "",
|
|
465
|
-
},
|
|
447
|
+
pathParam: ["testPlans", testPlanId, "testcases"],
|
|
466
448
|
param: { "format": "json" },
|
|
467
449
|
});
|
|
468
450
|
}
|
|
469
451
|
async getTestCaseSteps(testCaseId) {
|
|
470
452
|
return this.get({
|
|
471
|
-
pathParam:
|
|
472
|
-
|
|
473
|
-
"teststeps": "",
|
|
474
|
-
},
|
|
475
|
-
param: { "format": "json", },
|
|
453
|
+
pathParam: ["testCases", testCaseId, "teststeps"],
|
|
454
|
+
param: { "format": "json" },
|
|
476
455
|
});
|
|
477
456
|
}
|
|
478
457
|
async getProjects() {
|
|
479
458
|
return this.get({
|
|
480
|
-
pathParam:
|
|
459
|
+
pathParam: ["Projects"],
|
|
481
460
|
param: { "format": "json" },
|
|
482
461
|
});
|
|
483
462
|
}
|
|
484
463
|
async getTeams() {
|
|
485
464
|
return this.get({
|
|
486
|
-
pathParam:
|
|
465
|
+
pathParam: ["Teams"],
|
|
487
466
|
param: { "format": "json" },
|
|
488
467
|
});
|
|
489
468
|
}
|
|
469
|
+
async getCardStatus(cardId, resourceType = 'UserStory') {
|
|
470
|
+
const pathMap = { UserStory: 'userStory', Bug: 'bug', Feature: 'feature' };
|
|
471
|
+
return this.get({
|
|
472
|
+
pathParam: [pathMap[resourceType]],
|
|
473
|
+
param: {
|
|
474
|
+
"select": `{Project:{Project.Id},EntityState:{EntityState.Id,EntityState.Name,EntityState.NextStates,EntityState.Workflow.Id as WorkflowId},TeamState:{ResponsibleTeam.Id,Team:{ResponsibleTeam.Team.Id,ResponsibleTeam.Team.Name},EntityState:{ResponsibleTeam.EntityState.Id,ResponsibleTeam.EntityState.Name,ResponsibleTeam.EntityState.Workflow.Id as WorkflowId}},AssignedTeams.Select({TeamAssignmentId:Id,Id:Team.Id,Name:Team.Name}) as Teams}`,
|
|
475
|
+
"where": `(id=${cardId})`,
|
|
476
|
+
"take": "1",
|
|
477
|
+
},
|
|
478
|
+
apiVersion: this.v2
|
|
479
|
+
});
|
|
480
|
+
}
|
|
490
481
|
async getContext() {
|
|
491
482
|
return this.get({
|
|
492
|
-
pathParam:
|
|
493
|
-
param: { "format": "json"
|
|
483
|
+
pathParam: ["Context"],
|
|
484
|
+
param: { "format": "json" }
|
|
494
485
|
});
|
|
495
486
|
}
|
|
496
487
|
async addAttachedFile(generalId, source) {
|