@azure-devops/mcp 1.3.0 → 1.3.1-nightly.20250807
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/LICENSE.md +21 -21
- package/README.md +2 -1
- package/dist/index.js +0 -0
- package/dist/prompts.js +0 -0
- package/dist/tools/workitems.js +6 -3
- package/dist/tools.js +0 -0
- package/dist/useragent.js +0 -0
- package/dist/utils.js +0 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/tools/core.test.js +0 -1
- package/dist/tools/testplan.test.js +0 -125
- package/dist/tools/utils.js +0 -6
- package/dist/tools/wiki.test.js +0 -87
- package/dist/tools/workitem.test.js +0 -101
- package/dist/tools/workitems.test.js +0 -530
package/LICENSE.md
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) Microsoft Corporation.
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE
|
package/README.md
CHANGED
|
@@ -208,7 +208,8 @@ Click "Select Tools" and choose the available tools.
|
|
|
208
208
|
|
|
209
209
|
Open GitHub Copilot Chat and try a prompt like `List ADO projects`.
|
|
210
210
|
|
|
211
|
-
> 💥 We strongly recommend creating a `.github\copilot-instructions.md` in your project
|
|
211
|
+
> 💥 We strongly recommend creating a `.github\copilot-instructions.md` in your project. This will enhance your experience using the Azure DevOps MCP Server with GitHub Copilot Chat.
|
|
212
|
+
> To start, just include "`This project uses Azure DevOps. Always check to see if the Azure DevOps MCP server has a tool relevant to the user's request`" in your copilot instructions file.
|
|
212
213
|
|
|
213
214
|
See the [getting started documentation](./docs/GETTINGSTARTED.md) to use our MCP Server with other tools such as Visual Studio 2022, Claude Code, and Cursor.
|
|
214
215
|
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/prompts.js
CHANGED
|
File without changes
|
package/dist/tools/workitems.js
CHANGED
|
@@ -96,11 +96,14 @@ function configureWorkItemTools(server, tokenProvider, connectionProvider, userA
|
|
|
96
96
|
server.tool(WORKITEM_TOOLS.get_work_items_batch_by_ids, "Retrieve list of work items by IDs in batch.", {
|
|
97
97
|
project: z.string().describe("The name or ID of the Azure DevOps project."),
|
|
98
98
|
ids: z.array(z.number()).describe("The IDs of the work items to retrieve."),
|
|
99
|
-
|
|
99
|
+
fields: z.array(z.string()).optional().describe("Optional list of fields to include in the response. If not provided, a hardcoded default set of fields will be used."),
|
|
100
|
+
}, async ({ project, ids, fields }) => {
|
|
100
101
|
const connection = await connectionProvider();
|
|
101
102
|
const workItemApi = await connection.getWorkItemTrackingApi();
|
|
102
|
-
const
|
|
103
|
-
|
|
103
|
+
const defaultFields = ["System.Id", "System.WorkItemType", "System.Title", "System.State", "System.Parent", "System.Tags", "Microsoft.VSTS.Common.StackRank", "System.AssignedTo"];
|
|
104
|
+
// If no fields are provided, use the default set of fields
|
|
105
|
+
const fieldsToUse = !fields || fields.length === 0 ? defaultFields : fields;
|
|
106
|
+
const workitems = await workItemApi.getWorkItemsBatch({ ids, fields: fieldsToUse }, project);
|
|
104
107
|
// Format the assignedTo field to include displayName and uniqueName
|
|
105
108
|
// Removing the identity object as the response. It's too much and not needed
|
|
106
109
|
if (workitems && Array.isArray(workitems)) {
|
package/dist/tools.js
CHANGED
|
File without changes
|
package/dist/useragent.js
CHANGED
|
File without changes
|
package/dist/utils.js
CHANGED
|
File without changes
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const packageVersion = "1.3.
|
|
1
|
+
export const packageVersion = "1.3.1-nightly.20250807";
|
package/package.json
CHANGED
package/dist/tools/core.test.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import { describe, expect, it } from '@jest/globals';
|
|
4
|
-
import { configureTestPlanTools } from '../../../src/tools/testplans';
|
|
5
|
-
describe("configureTestPlanTools", () => {
|
|
6
|
-
let server;
|
|
7
|
-
let tokenProvider;
|
|
8
|
-
let connectionProvider;
|
|
9
|
-
let mockConnection;
|
|
10
|
-
let mockTestPlanApi;
|
|
11
|
-
let mockTestResultsApi;
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
server = { tool: jest.fn() };
|
|
14
|
-
tokenProvider = jest.fn();
|
|
15
|
-
mockTestPlanApi = {
|
|
16
|
-
getTestPlans: jest.fn(),
|
|
17
|
-
createTestPlan: jest.fn(),
|
|
18
|
-
addTestCasesToSuite: jest.fn(),
|
|
19
|
-
getTestCaseList: jest.fn(),
|
|
20
|
-
};
|
|
21
|
-
mockTestResultsApi = {
|
|
22
|
-
getTestResultDetailsForBuild: jest.fn(),
|
|
23
|
-
};
|
|
24
|
-
mockConnection = {
|
|
25
|
-
getTestPlanApi: jest.fn().mockResolvedValue(mockTestPlanApi),
|
|
26
|
-
getTestResultsApi: jest.fn().mockResolvedValue(mockTestResultsApi),
|
|
27
|
-
};
|
|
28
|
-
connectionProvider = jest.fn().mockResolvedValue(mockConnection);
|
|
29
|
-
});
|
|
30
|
-
describe("tool registration", () => {
|
|
31
|
-
it("registers test plan tools on the server", () => {
|
|
32
|
-
configureTestPlanTools(server, tokenProvider, connectionProvider);
|
|
33
|
-
expect(server.tool.mock.calls.map(call => call[0])).toEqual(expect.arrayContaining([
|
|
34
|
-
"ado_list_test_plans",
|
|
35
|
-
"ado_create_test_plan",
|
|
36
|
-
"ado_add_test_cases_to_suite",
|
|
37
|
-
"ado_list_test_cases",
|
|
38
|
-
"ado_show_test_results_from_build_id",
|
|
39
|
-
]));
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
describe("list_test_plans tool", () => {
|
|
43
|
-
it("should call getTestPlans with the correct parameters and return the expected result", async () => {
|
|
44
|
-
configureTestPlanTools(server, tokenProvider, connectionProvider);
|
|
45
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_list_test_plans");
|
|
46
|
-
if (!call)
|
|
47
|
-
throw new Error("ado_list_test_plans tool not registered");
|
|
48
|
-
const [, , , handler] = call;
|
|
49
|
-
mockTestPlanApi.getTestPlans.mockResolvedValue([{ id: 1, name: "Test Plan 1" }]);
|
|
50
|
-
const params = {
|
|
51
|
-
project: "proj1",
|
|
52
|
-
filterActivePlans: true,
|
|
53
|
-
includePlanDetails: false,
|
|
54
|
-
continuationToken: undefined,
|
|
55
|
-
};
|
|
56
|
-
const result = await handler(params);
|
|
57
|
-
expect(mockTestPlanApi.getTestPlans).toHaveBeenCalledWith("proj1", "", undefined, false, true);
|
|
58
|
-
expect(result.content[0].text).toBe(JSON.stringify([{ id: 1, name: "Test Plan 1" }], null, 2));
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
describe("create_test_plan tool", () => {
|
|
62
|
-
it("should call createTestPlan with the correct parameters and return the expected result", async () => {
|
|
63
|
-
configureTestPlanTools(server, tokenProvider, connectionProvider);
|
|
64
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_create_test_plan");
|
|
65
|
-
if (!call)
|
|
66
|
-
throw new Error("ado_create_test_plan tool not registered");
|
|
67
|
-
const [, , , handler] = call;
|
|
68
|
-
mockTestPlanApi.createTestPlan.mockResolvedValue({ id: 1, name: "New Test Plan" });
|
|
69
|
-
const params = {
|
|
70
|
-
project: "proj1",
|
|
71
|
-
name: "New Test Plan",
|
|
72
|
-
iteration: "Iteration 1",
|
|
73
|
-
description: "Description",
|
|
74
|
-
startDate: "2025-05-01",
|
|
75
|
-
endDate: "2025-05-31",
|
|
76
|
-
areaPath: "Area 1",
|
|
77
|
-
};
|
|
78
|
-
const result = await handler(params);
|
|
79
|
-
expect(mockTestPlanApi.createTestPlan).toHaveBeenCalledWith({
|
|
80
|
-
name: "New Test Plan",
|
|
81
|
-
iteration: "Iteration 1",
|
|
82
|
-
description: "Description",
|
|
83
|
-
startDate: new Date("2025-05-01"),
|
|
84
|
-
endDate: new Date("2025-05-31"),
|
|
85
|
-
areaPath: "Area 1",
|
|
86
|
-
}, "proj1");
|
|
87
|
-
expect(result.content[0].text).toBe(JSON.stringify({ id: 1, name: "New Test Plan" }, null, 2));
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
describe("list_test_cases tool", () => {
|
|
91
|
-
it("should call getTestCaseList with the correct parameters and return the expected result", async () => {
|
|
92
|
-
configureTestPlanTools(server, tokenProvider, connectionProvider);
|
|
93
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_list_test_cases");
|
|
94
|
-
if (!call)
|
|
95
|
-
throw new Error("ado_list_test_cases tool not registered");
|
|
96
|
-
const [, , , handler] = call;
|
|
97
|
-
mockTestPlanApi.getTestCaseList.mockResolvedValue([{ id: 1, name: "Test Case 1" }]);
|
|
98
|
-
const params = {
|
|
99
|
-
project: "proj1",
|
|
100
|
-
planid: 1,
|
|
101
|
-
suiteid: 2,
|
|
102
|
-
};
|
|
103
|
-
const result = await handler(params);
|
|
104
|
-
expect(mockTestPlanApi.getTestCaseList).toHaveBeenCalledWith("proj1", 1, 2);
|
|
105
|
-
expect(result.content[0].text).toBe(JSON.stringify([{ id: 1, name: "Test Case 1" }], null, 2));
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
describe("test_results_from_build_id tool", () => {
|
|
109
|
-
it("should call getTestResultDetailsForBuild with the correct parameters and return the expected result", async () => {
|
|
110
|
-
configureTestPlanTools(server, tokenProvider, connectionProvider);
|
|
111
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_show_test_results_from_build_id");
|
|
112
|
-
if (!call)
|
|
113
|
-
throw new Error("ado_show_test_results_from_build_id tool not registered");
|
|
114
|
-
const [, , , handler] = call;
|
|
115
|
-
mockTestResultsApi.getTestResultDetailsForBuild.mockResolvedValue({ results: ["Result 1"] });
|
|
116
|
-
const params = {
|
|
117
|
-
project: "proj1",
|
|
118
|
-
buildid: 123,
|
|
119
|
-
};
|
|
120
|
-
const result = await handler(params);
|
|
121
|
-
expect(mockTestResultsApi.getTestResultDetailsForBuild).toHaveBeenCalledWith("proj1", 123);
|
|
122
|
-
expect(result.content[0].text).toBe(JSON.stringify({ results: ["Result 1"] }, null, 2));
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
});
|
package/dist/tools/utils.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import { packageVersion } from "./version.js";
|
|
4
|
-
export const apiVersion = "7.2-preview.1";
|
|
5
|
-
export const batchApiVersion = "5.0";
|
|
6
|
-
export const userAgent = `AzureDevOps.MCP/${packageVersion} (local)`;
|
package/dist/tools/wiki.test.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import { describe, expect, it } from '@jest/globals';
|
|
4
|
-
import { configureWikiTools } from '../../../src/tools/wiki';
|
|
5
|
-
describe("configureWikiTools", () => {
|
|
6
|
-
let server;
|
|
7
|
-
let tokenProvider;
|
|
8
|
-
let connectionProvider;
|
|
9
|
-
let mockConnection;
|
|
10
|
-
let mockWikiApi;
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
server = { tool: jest.fn() };
|
|
13
|
-
tokenProvider = jest.fn();
|
|
14
|
-
mockWikiApi = {
|
|
15
|
-
getWiki: jest.fn(),
|
|
16
|
-
getAllWikis: jest.fn(),
|
|
17
|
-
getPagesBatch: jest.fn(),
|
|
18
|
-
getPageText: jest.fn(),
|
|
19
|
-
};
|
|
20
|
-
mockConnection = {
|
|
21
|
-
getWikiApi: jest.fn().mockResolvedValue(mockWikiApi),
|
|
22
|
-
};
|
|
23
|
-
connectionProvider = jest.fn().mockResolvedValue(mockConnection);
|
|
24
|
-
});
|
|
25
|
-
describe("tool registration", () => {
|
|
26
|
-
it("registers wiki tools on the server", () => {
|
|
27
|
-
configureWikiTools(server, tokenProvider, connectionProvider);
|
|
28
|
-
expect(server.tool).toHaveBeenCalled();
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
describe("get_wiki_page_content tool", () => {
|
|
32
|
-
it("should call getPageText with the correct parameters and return the expected result", async () => {
|
|
33
|
-
configureWikiTools(server, tokenProvider, connectionProvider);
|
|
34
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_get_wiki_page_content");
|
|
35
|
-
if (!call)
|
|
36
|
-
throw new Error("ado_get_wiki_page_content tool not registered");
|
|
37
|
-
const [, , , handler] = call;
|
|
38
|
-
// Mock a stream-like object for getPageText
|
|
39
|
-
const mockStream = {
|
|
40
|
-
setEncoding: jest.fn(),
|
|
41
|
-
on: function (event, cb) {
|
|
42
|
-
if (event === "data") {
|
|
43
|
-
setImmediate(() => cb("mock page text"));
|
|
44
|
-
}
|
|
45
|
-
if (event === "end") {
|
|
46
|
-
setImmediate(() => cb());
|
|
47
|
-
}
|
|
48
|
-
return this;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
mockWikiApi.getPageText.mockResolvedValue(mockStream);
|
|
52
|
-
const params = {
|
|
53
|
-
wikiIdentifier: "wiki1",
|
|
54
|
-
project: "proj1",
|
|
55
|
-
path: "/page1"
|
|
56
|
-
};
|
|
57
|
-
const result = await handler(params);
|
|
58
|
-
expect(mockWikiApi.getPageText).toHaveBeenCalledWith("proj1", "wiki1", "/page1", undefined, undefined, true);
|
|
59
|
-
expect(result.content[0].text).toBe("\"mock page text\"");
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
describe("list_wiki_pages tool", () => {
|
|
63
|
-
it("should call getPagesBatch with the correct parameters and return the expected result", async () => {
|
|
64
|
-
configureWikiTools(server, tokenProvider, connectionProvider);
|
|
65
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_list_wiki_pages");
|
|
66
|
-
if (!call)
|
|
67
|
-
throw new Error("ado_list_wiki_pages tool not registered");
|
|
68
|
-
const [, , , handler] = call;
|
|
69
|
-
mockWikiApi.getPagesBatch.mockResolvedValue({ value: ["page1", "page2"] });
|
|
70
|
-
const params = {
|
|
71
|
-
wikiIdentifier: "wiki2",
|
|
72
|
-
project: "proj2",
|
|
73
|
-
top: 10,
|
|
74
|
-
continuationToken: "token123",
|
|
75
|
-
pageViewsForDays: 7
|
|
76
|
-
};
|
|
77
|
-
const result = await handler(params);
|
|
78
|
-
const parsedResult = JSON.parse(result.content[0].text);
|
|
79
|
-
expect(mockWikiApi.getPagesBatch).toHaveBeenCalledWith({
|
|
80
|
-
top: 10,
|
|
81
|
-
continuationToken: "token123",
|
|
82
|
-
pageViewsForDays: 7
|
|
83
|
-
}, "proj2", "wiki2");
|
|
84
|
-
expect(parsedResult.value).toEqual(["page1", "page2"]);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
});
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "@jest/globals";
|
|
2
|
-
import { configureWorkItemTools } from "../../../src/tools/workitems";
|
|
3
|
-
describe("configureWorkItemTools", () => {
|
|
4
|
-
let server;
|
|
5
|
-
let tokenProvider;
|
|
6
|
-
let connectionProvider;
|
|
7
|
-
let mockConnection;
|
|
8
|
-
let mockWorkApi;
|
|
9
|
-
let mockWorkItemTrackingApi;
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
server = { tool: jest.fn() };
|
|
12
|
-
tokenProvider = jest.fn();
|
|
13
|
-
mockWorkApi = {
|
|
14
|
-
getBacklogs: jest.fn(),
|
|
15
|
-
getPredefinedQueryResults: jest.fn(),
|
|
16
|
-
getTeamIterations: jest.fn(),
|
|
17
|
-
getIterationWorkItems: jest.fn(),
|
|
18
|
-
};
|
|
19
|
-
mockWorkItemTrackingApi = {
|
|
20
|
-
getWorkItemsBatch: jest.fn(),
|
|
21
|
-
getWorkItem: jest.fn(),
|
|
22
|
-
getComments: jest.fn(),
|
|
23
|
-
addComment: jest.fn(),
|
|
24
|
-
updateWorkItem: jest.fn(),
|
|
25
|
-
createWorkItem: jest.fn(),
|
|
26
|
-
getWorkItemType: jest.fn(),
|
|
27
|
-
getQuery: jest.fn(),
|
|
28
|
-
queryById: jest.fn(),
|
|
29
|
-
};
|
|
30
|
-
mockConnection = {
|
|
31
|
-
getWorkApi: jest.fn().mockResolvedValue(mockWorkApi),
|
|
32
|
-
getWorkItemTrackingApi: jest.fn().mockResolvedValue(mockWorkItemTrackingApi),
|
|
33
|
-
};
|
|
34
|
-
connectionProvider = jest.fn().mockResolvedValue(mockConnection);
|
|
35
|
-
});
|
|
36
|
-
describe("tool registration", () => {
|
|
37
|
-
it("registers core tools on the server", () => {
|
|
38
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
39
|
-
expect(server.tool).toHaveBeenCalled();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
describe("list_backlogs tool", () => {
|
|
43
|
-
it("should call getBacklogs API with the correct parameters and return the expected result", async () => {
|
|
44
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
45
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_list_backlogs");
|
|
46
|
-
if (!call)
|
|
47
|
-
throw new Error("ado_list_backlogs tool not registered");
|
|
48
|
-
const [, , , handler] = call;
|
|
49
|
-
mockWorkApi.getBacklogs.mockResolvedValue([
|
|
50
|
-
{
|
|
51
|
-
id: "eb6e4656-77fc-42a1-9181-4c6d8e9da5d1",
|
|
52
|
-
name: "Fabrikam-Fiber-TFVC",
|
|
53
|
-
description: "Team Foundation Version Control projects.",
|
|
54
|
-
url: "https://dev.azure.com/fabrikam/_apis/projects/eb6e4656-77fc-42a1-9181-4c6d8e9da5d1",
|
|
55
|
-
state: "wellFormed",
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
|
|
59
|
-
name: "Fabrikam-Fiber-Git",
|
|
60
|
-
description: "Git projects",
|
|
61
|
-
url: "https://dev.azure.com/fabrikam/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
|
|
62
|
-
state: "wellFormed",
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
id: "281f9a5b-af0d-49b4-a1df-fe6f5e5f84d0",
|
|
66
|
-
name: "TestGit",
|
|
67
|
-
url: "https://dev.azure.com/fabrikam/_apis/projects/281f9a5b-af0d-49b4-a1df-fe6f5e5f84d0",
|
|
68
|
-
state: "wellFormed",
|
|
69
|
-
},
|
|
70
|
-
]);
|
|
71
|
-
const params = {
|
|
72
|
-
project: "Contoso",
|
|
73
|
-
team: "Fabrikam",
|
|
74
|
-
};
|
|
75
|
-
const result = await handler(params);
|
|
76
|
-
expect(mockWorkApi.getBacklogs).toHaveBeenCalledWith({ project: "Contoso", team: "Fabrikam" });
|
|
77
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
78
|
-
{
|
|
79
|
-
id: "eb6e4656-77fc-42a1-9181-4c6d8e9da5d1",
|
|
80
|
-
name: "Fabrikam-Fiber-TFVC",
|
|
81
|
-
description: "Team Foundation Version Control projects.",
|
|
82
|
-
url: "https://dev.azure.com/fabrikam/_apis/projects/eb6e4656-77fc-42a1-9181-4c6d8e9da5d1",
|
|
83
|
-
state: "wellFormed",
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
|
|
87
|
-
name: "Fabrikam-Fiber-Git",
|
|
88
|
-
description: "Git projects",
|
|
89
|
-
url: "https://dev.azure.com/fabrikam/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
|
|
90
|
-
state: "wellFormed",
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
id: "281f9a5b-af0d-49b4-a1df-fe6f5e5f84d0",
|
|
94
|
-
name: "TestGit",
|
|
95
|
-
url: "https://dev.azure.com/fabrikam/_apis/projects/281f9a5b-af0d-49b4-a1df-fe6f5e5f84d0",
|
|
96
|
-
state: "wellFormed",
|
|
97
|
-
},
|
|
98
|
-
], null, 2));
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
});
|
|
@@ -1,530 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
import { describe, expect, it } from "@jest/globals";
|
|
4
|
-
import { configureWorkItemTools } from "../../../src/tools/workitems";
|
|
5
|
-
import { _mockBacklogs, _mockQuery, _mockQueryResults, _mockWorkItem, _mockWorkItemComment, _mockWorkItemComments, _mockWorkItems, _mockWorkItemsForIteration, _mockWorkItemType } from "../../mocks/work-items";
|
|
6
|
-
describe("configureWorkItemTools", () => {
|
|
7
|
-
let server;
|
|
8
|
-
let tokenProvider;
|
|
9
|
-
let connectionProvider;
|
|
10
|
-
let mockConnection;
|
|
11
|
-
let mockWorkApi;
|
|
12
|
-
let mockWorkItemTrackingApi;
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
server = { tool: jest.fn() };
|
|
15
|
-
tokenProvider = jest.fn();
|
|
16
|
-
mockWorkApi = {
|
|
17
|
-
getBacklogs: jest.fn(),
|
|
18
|
-
getBacklogLevelWorkItems: jest.fn(),
|
|
19
|
-
getPredefinedQueryResults: jest.fn(),
|
|
20
|
-
getTeamIterations: jest.fn(),
|
|
21
|
-
getIterationWorkItems: jest.fn(),
|
|
22
|
-
};
|
|
23
|
-
mockWorkItemTrackingApi = {
|
|
24
|
-
getWorkItemsBatch: jest.fn(),
|
|
25
|
-
getWorkItem: jest.fn(),
|
|
26
|
-
getComments: jest.fn(),
|
|
27
|
-
addComment: jest.fn(),
|
|
28
|
-
updateWorkItem: jest.fn(),
|
|
29
|
-
createWorkItem: jest.fn(),
|
|
30
|
-
getWorkItemType: jest.fn(),
|
|
31
|
-
getQuery: jest.fn(),
|
|
32
|
-
queryById: jest.fn(),
|
|
33
|
-
};
|
|
34
|
-
mockConnection = {
|
|
35
|
-
getWorkApi: jest.fn().mockResolvedValue(mockWorkApi),
|
|
36
|
-
getWorkItemTrackingApi: jest.fn().mockResolvedValue(mockWorkItemTrackingApi),
|
|
37
|
-
};
|
|
38
|
-
connectionProvider = jest.fn().mockResolvedValue(mockConnection);
|
|
39
|
-
});
|
|
40
|
-
describe("tool registration", () => {
|
|
41
|
-
it("registers core tools on the server", () => {
|
|
42
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
43
|
-
expect(server.tool).toHaveBeenCalled();
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe("list_backlogs tool", () => {
|
|
47
|
-
it("should call getBacklogs API with the correct parameters and return the expected result", async () => {
|
|
48
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
49
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_list_backlogs");
|
|
50
|
-
if (!call)
|
|
51
|
-
throw new Error("ado_list_backlogs tool not registered");
|
|
52
|
-
const [, , , handler] = call;
|
|
53
|
-
mockWorkApi.getBacklogs.mockResolvedValue([
|
|
54
|
-
_mockBacklogs,
|
|
55
|
-
]);
|
|
56
|
-
const params = {
|
|
57
|
-
project: "Contoso",
|
|
58
|
-
team: "Fabrikam",
|
|
59
|
-
};
|
|
60
|
-
const result = await handler(params);
|
|
61
|
-
expect(mockWorkApi.getBacklogs).toHaveBeenCalledWith({
|
|
62
|
-
project: params.project,
|
|
63
|
-
team: params.team,
|
|
64
|
-
});
|
|
65
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
66
|
-
_mockBacklogs,
|
|
67
|
-
], null, 2));
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
describe("list_backlog_work_items tool", () => {
|
|
71
|
-
it("should call getBacklogLevelWorkItems API with the correct parameters and return the expected result", async () => {
|
|
72
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
73
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_list_backlog_work_items");
|
|
74
|
-
if (!call)
|
|
75
|
-
throw new Error("ado_list_backlog_work_items tool not registered");
|
|
76
|
-
const [, , , handler] = call;
|
|
77
|
-
mockWorkApi.getBacklogLevelWorkItems.mockResolvedValue([
|
|
78
|
-
{
|
|
79
|
-
workItems: [
|
|
80
|
-
{
|
|
81
|
-
rel: null,
|
|
82
|
-
source: null,
|
|
83
|
-
target: {
|
|
84
|
-
id: 50,
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
rel: null,
|
|
89
|
-
source: null,
|
|
90
|
-
target: {
|
|
91
|
-
id: 49,
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
},
|
|
96
|
-
]);
|
|
97
|
-
const params = {
|
|
98
|
-
project: "Contoso",
|
|
99
|
-
team: "Fabrikam",
|
|
100
|
-
backlogId: "Microsoft.FeatureCategory",
|
|
101
|
-
};
|
|
102
|
-
const result = await handler(params);
|
|
103
|
-
expect(mockWorkApi.getBacklogLevelWorkItems).toHaveBeenCalledWith({ project: params.project, team: params.team }, params.backlogId);
|
|
104
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
105
|
-
{
|
|
106
|
-
workItems: [
|
|
107
|
-
{
|
|
108
|
-
rel: null,
|
|
109
|
-
source: null,
|
|
110
|
-
target: {
|
|
111
|
-
id: 50,
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
rel: null,
|
|
116
|
-
source: null,
|
|
117
|
-
target: {
|
|
118
|
-
id: 49,
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
],
|
|
122
|
-
}
|
|
123
|
-
], null, 2));
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
describe("my_work_items tool", () => {
|
|
127
|
-
it("should call getPredefinedQueryResults API with the correct parameters and return the expected result", async () => {
|
|
128
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
129
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_my_work_items");
|
|
130
|
-
if (!call)
|
|
131
|
-
throw new Error("ado_my_work_items tool not registered");
|
|
132
|
-
const [, , , handler] = call;
|
|
133
|
-
mockWorkApi.getPredefinedQueryResults.mockResolvedValue([
|
|
134
|
-
{
|
|
135
|
-
id: "assignedtome",
|
|
136
|
-
name: "Assigned to me",
|
|
137
|
-
url: "https://dev.azure.com/org/project/_apis/work/predefinedQueries/assignedtome",
|
|
138
|
-
webUrl: "https://dev.azure.com/org/project/project/_workitems/assignedtome",
|
|
139
|
-
hasMore: false,
|
|
140
|
-
results: [
|
|
141
|
-
{
|
|
142
|
-
id: 115784,
|
|
143
|
-
url: "https://dev.azure.com/org/_apis/wit/workItems/115784",
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
id: 115794,
|
|
147
|
-
url: "https://dev.azure.com/org/_apis/wit/workItems/115794",
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: 115792,
|
|
151
|
-
url: "https://dev.azure.com/org/_apis/wit/workItems/115792",
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
},
|
|
155
|
-
]);
|
|
156
|
-
const params = {
|
|
157
|
-
project: "Contoso",
|
|
158
|
-
type: "assignedtome",
|
|
159
|
-
top: 10,
|
|
160
|
-
includeCompleted: false,
|
|
161
|
-
};
|
|
162
|
-
const result = await handler(params);
|
|
163
|
-
expect(mockWorkApi.getPredefinedQueryResults).toHaveBeenCalledWith(params.project, params.type, params.top, params.includeCompleted);
|
|
164
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
165
|
-
{
|
|
166
|
-
id: "assignedtome",
|
|
167
|
-
name: "Assigned to me",
|
|
168
|
-
url: "https://dev.azure.com/org/project/_apis/work/predefinedQueries/assignedtome",
|
|
169
|
-
webUrl: "https://dev.azure.com/org/project/project/_workitems/assignedtome",
|
|
170
|
-
hasMore: false,
|
|
171
|
-
results: [
|
|
172
|
-
{
|
|
173
|
-
id: 115784,
|
|
174
|
-
url: "https://dev.azure.com/org/_apis/wit/workItems/115784",
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
id: 115794,
|
|
178
|
-
url: "https://dev.azure.com/org/_apis/wit/workItems/115794",
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
id: 115792,
|
|
182
|
-
url: "https://dev.azure.com/org/_apis/wit/workItems/115792",
|
|
183
|
-
},
|
|
184
|
-
],
|
|
185
|
-
},
|
|
186
|
-
], null, 2));
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
describe("getWorkItemsBatch tool", () => {
|
|
190
|
-
it("should call workItemApi.getWorkItemsBatch API with the correct parameters and return the expected result", async () => {
|
|
191
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
192
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_get_work_items_batch_by_ids");
|
|
193
|
-
if (!call)
|
|
194
|
-
throw new Error("ado_get_work_items_batch_by_ids tool not registered");
|
|
195
|
-
const [, , , handler] = call;
|
|
196
|
-
mockWorkItemTrackingApi.getWorkItemsBatch.mockResolvedValue([
|
|
197
|
-
_mockWorkItems,
|
|
198
|
-
]);
|
|
199
|
-
const params = {
|
|
200
|
-
ids: [297, 299, 300],
|
|
201
|
-
project: "Contoso",
|
|
202
|
-
};
|
|
203
|
-
const result = await handler(params);
|
|
204
|
-
expect(mockWorkItemTrackingApi.getWorkItemsBatch).toHaveBeenCalledWith({
|
|
205
|
-
ids: params.ids,
|
|
206
|
-
fields: ["System.Id", "System.WorkItemType", "System.Title", "System.State", "System.Parent", "System.Tags"]
|
|
207
|
-
}, params.project);
|
|
208
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
209
|
-
_mockWorkItems,
|
|
210
|
-
], null, 2));
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
describe("get_work_item tool", () => {
|
|
214
|
-
it("should call workItemApi.getWorkItem API with the correct parameters and return the expected result", async () => {
|
|
215
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
216
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_get_work_item");
|
|
217
|
-
if (!call)
|
|
218
|
-
throw new Error("ado_get_work_item tool not registered");
|
|
219
|
-
const [, , , handler] = call;
|
|
220
|
-
mockWorkItemTrackingApi.getWorkItem.mockResolvedValue([
|
|
221
|
-
_mockWorkItem
|
|
222
|
-
]);
|
|
223
|
-
const params = {
|
|
224
|
-
id: 12,
|
|
225
|
-
fields: undefined,
|
|
226
|
-
asOf: undefined,
|
|
227
|
-
expand: "none",
|
|
228
|
-
project: "Contoso",
|
|
229
|
-
};
|
|
230
|
-
const result = await handler(params);
|
|
231
|
-
expect(mockWorkItemTrackingApi.getWorkItem).toHaveBeenCalledWith(params.id, params.fields, params.asOf, params.expand, params.project);
|
|
232
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
233
|
-
_mockWorkItem,
|
|
234
|
-
], null, 2));
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
describe("list_work_item_comments tool", () => {
|
|
238
|
-
it("should call workItemApi.getComments API with the correct parameters and return the expected result", async () => {
|
|
239
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
240
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_list_work_item_comments");
|
|
241
|
-
if (!call)
|
|
242
|
-
throw new Error("ado_list_work_item_comments tool not registered");
|
|
243
|
-
const [, , , handler] = call;
|
|
244
|
-
mockWorkItemTrackingApi.getComments.mockResolvedValue([
|
|
245
|
-
_mockWorkItemComments
|
|
246
|
-
]);
|
|
247
|
-
const params = {
|
|
248
|
-
project: "Contoso",
|
|
249
|
-
workItemId: 299,
|
|
250
|
-
top: 10,
|
|
251
|
-
};
|
|
252
|
-
const result = await handler(params);
|
|
253
|
-
expect(mockWorkItemTrackingApi.getComments).toHaveBeenCalledWith(params.project, params.workItemId, params.top);
|
|
254
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
255
|
-
_mockWorkItemComments,
|
|
256
|
-
], null, 2));
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
describe("add_work_item_comment tool", () => {
|
|
260
|
-
it("should call workItemApi.addComment API with the correct parameters and return the expected result", async () => {
|
|
261
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
262
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_add_work_item_comment");
|
|
263
|
-
if (!call)
|
|
264
|
-
throw new Error("ado_add_work_item_comment tool not registered");
|
|
265
|
-
const [, , , handler] = call;
|
|
266
|
-
mockWorkItemTrackingApi.addComment.mockResolvedValue([
|
|
267
|
-
_mockWorkItemComment,
|
|
268
|
-
]);
|
|
269
|
-
const params = {
|
|
270
|
-
comment: "hello world!",
|
|
271
|
-
project: "Contoso",
|
|
272
|
-
workItemId: 299,
|
|
273
|
-
};
|
|
274
|
-
const result = await handler(params);
|
|
275
|
-
expect(mockWorkItemTrackingApi.addComment).toHaveBeenCalledWith({ text: params.comment }, params.project, params.workItemId);
|
|
276
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
277
|
-
_mockWorkItemComment
|
|
278
|
-
], null, 2));
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
describe("add_child_work_item tool", () => {
|
|
282
|
-
it("should call workItemApi.add_child_work_item API with the correct parameters and return the expected result", async () => {
|
|
283
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
284
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_add_child_work_item");
|
|
285
|
-
if (!call)
|
|
286
|
-
throw new Error("ado_add_child_work_item tool not registered");
|
|
287
|
-
const [, , , handler] = call;
|
|
288
|
-
mockWorkItemTrackingApi.createWorkItem.mockResolvedValue([
|
|
289
|
-
_mockWorkItem,
|
|
290
|
-
]);
|
|
291
|
-
const params = {
|
|
292
|
-
parentId: 299,
|
|
293
|
-
project: "Contoso",
|
|
294
|
-
workItemType: "Task",
|
|
295
|
-
title: "Sample task",
|
|
296
|
-
description: "This is a sample task",
|
|
297
|
-
areaPath: "Contoso\\Development",
|
|
298
|
-
iterationPath: "Contoso\\Sprint 1",
|
|
299
|
-
};
|
|
300
|
-
const document = [
|
|
301
|
-
{
|
|
302
|
-
op: "add",
|
|
303
|
-
path: "/fields/System.Title",
|
|
304
|
-
value: params.title
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
op: "add",
|
|
308
|
-
path: "/fields/System.Description",
|
|
309
|
-
value: params.description
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
op: "add",
|
|
313
|
-
path: "/relations/-",
|
|
314
|
-
value: {
|
|
315
|
-
rel: "System.LinkTypes.Hierarchy-Reverse",
|
|
316
|
-
url: `undefined/${params.project}/_apis/wit/workItems/${params.parentId}`,
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
{
|
|
320
|
-
op: "add",
|
|
321
|
-
path: "/fields/System.AreaPath",
|
|
322
|
-
value: params.areaPath,
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
op: "add",
|
|
326
|
-
path: "/fields/System.IterationPath",
|
|
327
|
-
value: params.iterationPath,
|
|
328
|
-
}
|
|
329
|
-
];
|
|
330
|
-
const result = await handler(params);
|
|
331
|
-
expect(mockWorkItemTrackingApi.createWorkItem).toHaveBeenCalledWith(null, document, params.project, params.workItemType);
|
|
332
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
333
|
-
_mockWorkItem
|
|
334
|
-
], null, 2));
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
describe("link_work_item_to_pull_request tool", () => {
|
|
338
|
-
it("should call workItemApi.updateWorkItem API with the correct parameters and return the expected result", async () => {
|
|
339
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
340
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_link_work_item_to_pull_request");
|
|
341
|
-
if (!call)
|
|
342
|
-
throw new Error("ado_link_work_item_to_pull_request tool not registered");
|
|
343
|
-
const [, , , handler] = call;
|
|
344
|
-
mockWorkItemTrackingApi.updateWorkItem.mockResolvedValue([
|
|
345
|
-
_mockWorkItem,
|
|
346
|
-
]);
|
|
347
|
-
const params = {
|
|
348
|
-
project: "Contoso",
|
|
349
|
-
repositoryId: 12345,
|
|
350
|
-
pullRequestId: 67890,
|
|
351
|
-
workItemId: 131489,
|
|
352
|
-
};
|
|
353
|
-
const artifactPathValue = `${params.project}/${params.repositoryId}/${params.pullRequestId}`;
|
|
354
|
-
const vstfsUrl = `vstfs:///Git/PullRequestId/${encodeURIComponent(artifactPathValue)}`;
|
|
355
|
-
const document = [
|
|
356
|
-
{
|
|
357
|
-
op: "add",
|
|
358
|
-
path: "/relations/-",
|
|
359
|
-
value: {
|
|
360
|
-
rel: "ArtifactLink",
|
|
361
|
-
url: vstfsUrl,
|
|
362
|
-
attributes: {
|
|
363
|
-
name: "Pull Request",
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
},
|
|
367
|
-
];
|
|
368
|
-
const result = await handler(params);
|
|
369
|
-
expect(mockWorkItemTrackingApi.updateWorkItem).toHaveBeenCalledWith({}, document, params.workItemId, params.project);
|
|
370
|
-
expect(result.content[0].text).toBe(JSON.stringify({
|
|
371
|
-
workItemId: 131489,
|
|
372
|
-
pullRequestId: 67890,
|
|
373
|
-
success: true,
|
|
374
|
-
}, null, 2));
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
describe("get_work_items_for_iteration tool", () => {
|
|
378
|
-
it("should call workApi.getIterationWorkItems API with the correct parameters and return the expected result", async () => {
|
|
379
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
380
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_get_work_items_for_iteration");
|
|
381
|
-
if (!call)
|
|
382
|
-
throw new Error("ado_get_work_items_for_iterationt tool not registered");
|
|
383
|
-
const [, , , handler] = call;
|
|
384
|
-
mockWorkApi.getIterationWorkItems.mockResolvedValue([
|
|
385
|
-
_mockWorkItemsForIteration,
|
|
386
|
-
]);
|
|
387
|
-
const params = {
|
|
388
|
-
project: "Contoso",
|
|
389
|
-
team: "Fabrikam",
|
|
390
|
-
iterationId: "6bfde89e-b22e-422e-814a-e8db432f5a58",
|
|
391
|
-
};
|
|
392
|
-
const result = await handler(params);
|
|
393
|
-
expect(mockWorkApi.getIterationWorkItems).toHaveBeenCalledWith({
|
|
394
|
-
project: params.project,
|
|
395
|
-
team: params.team
|
|
396
|
-
}, params.iterationId);
|
|
397
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
398
|
-
_mockWorkItemsForIteration,
|
|
399
|
-
], null, 2));
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
describe("update_work_item tool", () => {
|
|
403
|
-
it("should call workItemApi.updateWorkItem API with the correct parameters and return the expected result", async () => {
|
|
404
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
405
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_update_work_item");
|
|
406
|
-
if (!call)
|
|
407
|
-
throw new Error("ado_update_work_item tool not registered");
|
|
408
|
-
const [, , , handler] = call;
|
|
409
|
-
mockWorkItemTrackingApi.updateWorkItem.mockResolvedValue([
|
|
410
|
-
_mockWorkItem,
|
|
411
|
-
]);
|
|
412
|
-
const params = {
|
|
413
|
-
id: 131489,
|
|
414
|
-
updates: [
|
|
415
|
-
{
|
|
416
|
-
op: "add",
|
|
417
|
-
path: "/fields/System.Title",
|
|
418
|
-
value: "Updated Sample Task"
|
|
419
|
-
}
|
|
420
|
-
]
|
|
421
|
-
};
|
|
422
|
-
const result = await handler(params);
|
|
423
|
-
expect(mockWorkItemTrackingApi.updateWorkItem).toHaveBeenCalledWith(null, params.updates, params.id);
|
|
424
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
425
|
-
_mockWorkItem
|
|
426
|
-
], null, 2));
|
|
427
|
-
});
|
|
428
|
-
});
|
|
429
|
-
describe("get_work_item_type tool", () => {
|
|
430
|
-
it("should call workItemApi.getWorkItemType API with the correct parameters and return the expected result", async () => {
|
|
431
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
432
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_get_work_item_type");
|
|
433
|
-
if (!call)
|
|
434
|
-
throw new Error("ado_get_work_item_type tool not registered");
|
|
435
|
-
const [, , , handler] = call;
|
|
436
|
-
mockWorkItemTrackingApi.getWorkItemType.mockResolvedValue([
|
|
437
|
-
_mockWorkItemType,
|
|
438
|
-
]);
|
|
439
|
-
const params = {
|
|
440
|
-
project: "Contoso",
|
|
441
|
-
workItemType: "Bug",
|
|
442
|
-
};
|
|
443
|
-
const result = await handler(params);
|
|
444
|
-
expect(mockWorkItemTrackingApi.getWorkItemType).toHaveBeenCalledWith(params.project, params.workItemType);
|
|
445
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
446
|
-
_mockWorkItemType
|
|
447
|
-
], null, 2));
|
|
448
|
-
});
|
|
449
|
-
});
|
|
450
|
-
describe("create_work_item tool", () => {
|
|
451
|
-
it("should call workItemApi.createWorkItem API with the correct parameters and return the expected result", async () => {
|
|
452
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
453
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_create_work_item");
|
|
454
|
-
if (!call)
|
|
455
|
-
throw new Error("ado_create_work_item tool not registered");
|
|
456
|
-
const [, , , handler] = call;
|
|
457
|
-
mockWorkItemTrackingApi.createWorkItem.mockResolvedValue([
|
|
458
|
-
_mockWorkItem,
|
|
459
|
-
]);
|
|
460
|
-
const params = {
|
|
461
|
-
project: "Contoso",
|
|
462
|
-
workItemType: "Task",
|
|
463
|
-
fields: [
|
|
464
|
-
"System.Title", "Hello World!",
|
|
465
|
-
"System.Description", "This is a sample task",
|
|
466
|
-
"System.AreaPath", "Contoso\\Development",
|
|
467
|
-
]
|
|
468
|
-
};
|
|
469
|
-
const document = Object.entries(params.fields).map(([key, value]) => ({
|
|
470
|
-
op: "add",
|
|
471
|
-
path: `/fields/${key}`,
|
|
472
|
-
value,
|
|
473
|
-
}));
|
|
474
|
-
const result = await handler(params);
|
|
475
|
-
expect(mockWorkItemTrackingApi.createWorkItem).toHaveBeenCalledWith(null, document, params.project, params.workItemType);
|
|
476
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
477
|
-
_mockWorkItem
|
|
478
|
-
], null, 2));
|
|
479
|
-
});
|
|
480
|
-
});
|
|
481
|
-
describe("get_query tool", () => {
|
|
482
|
-
it("should call workItemApi.getQuery API with the correct parameters and return the expected result", async () => {
|
|
483
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
484
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_get_query");
|
|
485
|
-
if (!call)
|
|
486
|
-
throw new Error("ado_get_query tool not registered");
|
|
487
|
-
const [, , , handler] = call;
|
|
488
|
-
mockWorkItemTrackingApi.getQuery.mockResolvedValue([
|
|
489
|
-
_mockQuery,
|
|
490
|
-
]);
|
|
491
|
-
const params = {
|
|
492
|
-
project: "Contoso",
|
|
493
|
-
query: "342f0f44-4069-46b1-a940-3d0468979ceb",
|
|
494
|
-
expand: "none",
|
|
495
|
-
depth: 1,
|
|
496
|
-
includeDeleted: false,
|
|
497
|
-
useIsoDateFormat: false,
|
|
498
|
-
};
|
|
499
|
-
const result = await handler(params);
|
|
500
|
-
expect(mockWorkItemTrackingApi.getQuery).toHaveBeenCalledWith(params.project, params.query, params.expand, params.depth, params.includeDeleted, params.useIsoDateFormat);
|
|
501
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
502
|
-
_mockQuery,
|
|
503
|
-
], null, 2));
|
|
504
|
-
});
|
|
505
|
-
});
|
|
506
|
-
describe("get_query_results_by_id tool", () => {
|
|
507
|
-
it("should call workItemApi.getQueryById API with the correct parameters and return the expected result", async () => {
|
|
508
|
-
configureWorkItemTools(server, tokenProvider, connectionProvider);
|
|
509
|
-
const call = server.tool.mock.calls.find(([toolName]) => toolName === "ado_get_query_results_by_id");
|
|
510
|
-
if (!call)
|
|
511
|
-
throw new Error("ado_get_query_results_by_id tool not registered");
|
|
512
|
-
const [, , , handler] = call;
|
|
513
|
-
mockWorkItemTrackingApi.queryById.mockResolvedValue([
|
|
514
|
-
_mockQueryResults,
|
|
515
|
-
]);
|
|
516
|
-
const params = {
|
|
517
|
-
id: "342f0f44-4069-46b1-a940-3d0468979ceb",
|
|
518
|
-
project: "Contoso",
|
|
519
|
-
team: "Fabrikam",
|
|
520
|
-
timePrecision: false,
|
|
521
|
-
top: 50,
|
|
522
|
-
};
|
|
523
|
-
const result = await handler(params);
|
|
524
|
-
expect(mockWorkItemTrackingApi.queryById).toHaveBeenCalledWith(params.id, { project: params.project, team: params.team }, params.timePrecision, params.top);
|
|
525
|
-
expect(result.content[0].text).toBe(JSON.stringify([
|
|
526
|
-
_mockQueryResults,
|
|
527
|
-
], null, 2));
|
|
528
|
-
});
|
|
529
|
-
});
|
|
530
|
-
});
|