Skip to content

Commit 3cbcf3b

Browse files
Julian De LucaJulian De Luca
authored andcommitted
fix: replace require() with jest.mock in core test
1 parent 1ca26b3 commit 3cbcf3b

File tree

6 files changed

+74
-41
lines changed

6 files changed

+74
-41
lines changed

src/shared/connection.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ import { packageVersion } from "../version.js";
99
* connection to that org; otherwise falls back to the default connectionProvider.
1010
*/
1111
export async function getConnection(
12-
organization: string | undefined,
13-
connectionProvider: () => Promise<WebApi>,
14-
tokenProvider: () => Promise<string>,
15-
userAgentProvider: () => string
12+
organization: string | undefined,
13+
connectionProvider: () => Promise<WebApi>,
14+
tokenProvider: () => Promise<string>,
15+
userAgentProvider: () => string
1616
): Promise<WebApi> {
17-
if (!organization) {
18-
return connectionProvider();
19-
}
17+
if (!organization) {
18+
return connectionProvider();
19+
}
2020

21-
const orgUrl = "https://dev.azure.com/" + organization;
22-
const accessToken = await tokenProvider();
23-
const authHandler = getBearerHandler(accessToken);
21+
const orgUrl = "https://dev.azure.com/" + organization;
22+
const accessToken = await tokenProvider();
23+
const authHandler = getBearerHandler(accessToken);
2424

25-
return new WebApi(orgUrl, authHandler, undefined, {
26-
productName: "AzureDevOps.MCP",
27-
productVersion: packageVersion,
28-
userAgent: userAgentProvider(),
29-
});
25+
return new WebApi(orgUrl, authHandler, undefined, {
26+
productName: "AzureDevOps.MCP",
27+
productVersion: packageVersion,
28+
userAgent: userAgentProvider(),
29+
});
3030
}

src/tools/auth.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ async function getCurrentUserDetails(tokenProvider: () => Promise<string>, conne
3232
/**
3333
* Searches for identities using Azure DevOps Identity API
3434
*/
35-
async function searchIdentities(identity: string, tokenProvider: () => Promise<string>, connectionProvider: () => Promise<WebApi>, userAgentProvider: () => string, organization?: string): Promise<IdentitiesResponse> {
35+
async function searchIdentities(
36+
identity: string,
37+
tokenProvider: () => Promise<string>,
38+
connectionProvider: () => Promise<WebApi>,
39+
userAgentProvider: () => string,
40+
organization?: string
41+
): Promise<IdentitiesResponse> {
3642
const token = await tokenProvider();
3743
const connection = await getConnection(organization, connectionProvider, tokenProvider, userAgentProvider);
3844
const orgName = connection.serverUrl.split("/")[3];
@@ -63,7 +69,13 @@ async function searchIdentities(identity: string, tokenProvider: () => Promise<s
6369
/**
6470
* Gets the user ID from email or unique name using Azure DevOps Identity API
6571
*/
66-
async function getUserIdFromEmail(userEmail: string, tokenProvider: () => Promise<string>, connectionProvider: () => Promise<WebApi>, userAgentProvider: () => string, organization?: string): Promise<string> {
72+
async function getUserIdFromEmail(
73+
userEmail: string,
74+
tokenProvider: () => Promise<string>,
75+
connectionProvider: () => Promise<WebApi>,
76+
userAgentProvider: () => string,
77+
organization?: string
78+
): Promise<string> {
6779
const identities = await searchIdentities(userEmail, tokenProvider, connectionProvider, userAgentProvider, organization);
6880

6981
if (!identities || identities.value?.length === 0) {

src/tools/repositories.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,10 @@ function configureRepoTools(server: McpServer, tokenProvider: () => Promise<stri
180180

181181
const forkSource: GitForkRef | undefined = forkSourceRepositoryId
182182
? {
183-
repository: {
184-
id: forkSourceRepositoryId,
185-
},
186-
}
183+
repository: {
184+
id: forkSourceRepositoryId,
185+
},
186+
}
187187
: undefined;
188188

189189
const labelDefinitions: WebApiTagDefinition[] | undefined = labels ? labels.map((label) => ({ name: label })) : undefined;
@@ -355,7 +355,22 @@ function configureRepoTools(server: McpServer, tokenProvider: () => Promise<stri
355355
labels: z.array(z.string()).optional().describe("Array of label names to replace existing labels on the pull request. This will remove all current labels and add the specified ones."),
356356
organization: z.string().optional().describe("Override the default Azure DevOps organization. If not provided, the organization configured at startup (via CLI arg or env var) is used."),
357357
},
358-
async ({ repositoryId, pullRequestId, title, description, isDraft, targetRefName, status, autoComplete, mergeStrategy, deleteSourceBranch, transitionWorkItems, bypassReason, labels, organization }) => {
358+
async ({
359+
repositoryId,
360+
pullRequestId,
361+
title,
362+
description,
363+
isDraft,
364+
targetRefName,
365+
status,
366+
autoComplete,
367+
mergeStrategy,
368+
deleteSourceBranch,
369+
transitionWorkItems,
370+
bypassReason,
371+
labels,
372+
organization,
373+
}) => {
359374
try {
360375
const connection = await getConnection(organization, connectionProvider, tokenProvider, userAgentProvider);
361376
const gitApi = await connection.getGitApi();
@@ -1593,9 +1608,9 @@ function configureRepoTools(server: McpServer, tokenProvider: () => Promise<stri
15931608
commitId: item.commitId,
15941609
contentMetadata: item.contentMetadata
15951610
? {
1596-
contentType: item.contentMetadata.contentType,
1597-
fileName: item.contentMetadata.fileName,
1598-
}
1611+
contentType: item.contentMetadata.contentType,
1612+
fileName: item.contentMetadata.fileName,
1613+
}
15991614
: undefined,
16001615
}));
16011616

src/tools/wiki.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ function configureWikiTools(server: McpServer, tokenProvider: () => Promise<stri
255255
} else if (resp.status === 404) {
256256
return { content: [{ type: "text", text: `Error fetching wiki page content: Page with id ${parsed.pageId} not found` }], isError: true };
257257
}
258-
} catch { }
258+
} catch {}
259259
}
260260
}
261261

src/tools/work.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,10 @@ function configureWorkTools(server: McpServer, tokenProvider: () => Promise<stri
257257
...rest,
258258
teamMember: member.teamMember
259259
? {
260-
displayName: member.teamMember.displayName,
261-
id: member.teamMember.id,
262-
uniqueName: member.teamMember.uniqueName,
263-
}
260+
displayName: member.teamMember.displayName,
261+
id: member.teamMember.id,
262+
uniqueName: member.teamMember.uniqueName,
263+
}
264264
: undefined,
265265
};
266266
}),
@@ -342,10 +342,10 @@ function configureWorkTools(server: McpServer, tokenProvider: () => Promise<stri
342342
const simplifiedResult = {
343343
teamMember: updatedCapacity.teamMember
344344
? {
345-
displayName: updatedCapacity.teamMember.displayName,
346-
id: updatedCapacity.teamMember.id,
347-
uniqueName: updatedCapacity.teamMember.uniqueName,
348-
}
345+
displayName: updatedCapacity.teamMember.displayName,
346+
id: updatedCapacity.teamMember.id,
347+
uniqueName: updatedCapacity.teamMember.uniqueName,
348+
}
349349
: undefined,
350350
activities: updatedCapacity.activities,
351351
daysOff: updatedCapacity.daysOff,

test/src/tools/core.test.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { describe, expect, it } from "@jest/globals";
55
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
66
import { configureCoreTools } from "../../../src/tools/core";
77
import { WebApi } from "azure-devops-node-api";
8+
import { getConnection } from "../../../src/shared/connection";
9+
10+
jest.mock("../../../src/shared/connection");
11+
const mockGetConnection = getConnection as jest.MockedFunction<typeof getConnection>;
812

913
type TokenProviderMock = () => Promise<string>;
1014
type ConnectionProviderMock = () => Promise<WebApi>;
@@ -37,6 +41,14 @@ describe("configureCoreTools", () => {
3741
};
3842

3943
connectionProvider = jest.fn().mockResolvedValue(mockConnection);
44+
45+
// By default, getConnection delegates to connectionProvider
46+
mockGetConnection.mockImplementation(async (organization, connProvider) => {
47+
if (organization) {
48+
return mockConnection as unknown as WebApi;
49+
}
50+
return connProvider();
51+
});
4052
});
4153

4254
describe("tool registration", () => {
@@ -329,10 +341,6 @@ describe("configureCoreTools", () => {
329341
},
330342
]);
331343

332-
const WebApiModule = require("azure-devops-node-api");
333-
const OriginalWebApi = WebApiModule.WebApi;
334-
WebApiModule.WebApi = jest.fn().mockImplementation(() => mockConnection);
335-
336344
const result = await handler({
337345
stateFilter: "wellFormed",
338346
top: undefined,
@@ -341,10 +349,8 @@ describe("configureCoreTools", () => {
341349
organization: "contoso",
342350
});
343351

344-
WebApiModule.WebApi = OriginalWebApi;
345-
352+
expect(mockGetConnection).toHaveBeenCalledWith("contoso", connectionProvider, tokenProvider, userAgentProvider);
346353
expect(connectionProvider).not.toHaveBeenCalled();
347-
expect(tokenProvider).toHaveBeenCalled();
348354
expect(result.content[0].text).toContain("CrossOrgProject");
349355
});
350356
});

0 commit comments

Comments
 (0)