Skip to content

Commit d92624e

Browse files
committed
chore: add retries also to some tests
1 parent 078f387 commit d92624e

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

tests/integration/tools/atlas/atlasHelpers.ts

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { ApiClient } from "../../../../src/common/atlas/apiClient.js";
44
import type { IntegrationTest } from "../../helpers.js";
55
import { setupIntegrationTest, defaultTestConfig, defaultDriverOptions } from "../../helpers.js";
66
import type { SuiteCollector } from "vitest";
7-
import { beforeAll, afterAll, describe } from "vitest";
7+
import { beforeAll, afterAll, describe, it } from "vitest";
88

99
export type IntegrationTestFunction = (integration: IntegrationTest) => void;
1010

@@ -64,13 +64,14 @@ export function withProject(integration: IntegrationTest, fn: ProjectTestFunctio
6464
});
6565
}
6666

67+
const MAX_ATLAS_STEP_ATTEMPTS = 10;
68+
const SETUP_BACKOFF_MS = 10;
69+
6770
export function beforeAllWithRetry(fixture: () => Promise<void>): void {
6871
beforeAll(async () => {
69-
const MAX_SETUP_ATTEMPTS = 10;
70-
const SETUP_BACKOFF_MS = 10;
7172
let lastError: Error | undefined = undefined;
7273

73-
for (let attempt = 0; attempt < MAX_SETUP_ATTEMPTS; attempt++) {
74+
for (let attempt = 0; attempt < MAX_ATLAS_STEP_ATTEMPTS; attempt++) {
7475
try {
7576
await fixture();
7677
lastError = undefined;
@@ -95,11 +96,9 @@ export function beforeAllWithRetry(fixture: () => Promise<void>): void {
9596

9697
export function afterAllWithRetry(fixture: () => Promise<void>): void {
9798
afterAll(async () => {
98-
const MAX_SETUP_ATTEMPTS = 10;
99-
const SETUP_BACKOFF_MS = 10;
10099
let lastError: Error | undefined = undefined;
101100

102-
for (let attempt = 0; attempt < MAX_SETUP_ATTEMPTS; attempt++) {
101+
for (let attempt = 0; attempt < MAX_ATLAS_STEP_ATTEMPTS; attempt++) {
103102
try {
104103
await fixture();
105104
lastError = undefined;
@@ -121,6 +120,34 @@ export function afterAllWithRetry(fixture: () => Promise<void>): void {
121120
});
122121
}
123122

123+
export function itWithRetry(name: string, test: () => Promise<void>): void {
124+
// complains about not having assertions, but assertions are inside the test function
125+
// eslint-disable-next-line
126+
it(name, async () => {
127+
let lastError: Error | undefined = undefined;
128+
129+
for (let attempt = 0; attempt < MAX_ATLAS_STEP_ATTEMPTS; attempt++) {
130+
try {
131+
await test();
132+
lastError = undefined;
133+
break;
134+
} catch (error) {
135+
if (error instanceof Error) {
136+
lastError = error;
137+
} else {
138+
lastError = new Error(String(error));
139+
}
140+
console.error(`${name} (attempt: ${attempt}):`, error);
141+
await new Promise((resolve) => setTimeout(resolve, SETUP_BACKOFF_MS * attempt));
142+
}
143+
}
144+
145+
if (lastError) {
146+
throw lastError;
147+
}
148+
});
149+
}
150+
124151
export function parseTable(text: string): Record<string, string>[] {
125152
const data = text
126153
.split("\n")

tests/integration/tools/atlas/projects.test.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ObjectId } from "mongodb";
2-
import { parseTable, describeWithAtlas, afterAllWithRetry } from "./atlasHelpers.js";
2+
import { parseTable, describeWithAtlas, afterAllWithRetry, itWithRetry } from "./atlasHelpers.js";
33
import { expectDefined, getDataFromUntrustedContent, getResponseElements } from "../../helpers.js";
4-
import { describe, expect, it } from "vitest";
4+
import { describe, expect } from "vitest";
55

66
const randomId = new ObjectId().toString();
77

@@ -27,7 +27,7 @@ describeWithAtlas("projects", (integration) => {
2727
});
2828

2929
describe("atlas-create-project", () => {
30-
it("should have correct metadata", async () => {
30+
itWithRetry("should have correct metadata", async () => {
3131
const { tools } = await integration.mcpClient().listTools();
3232
const createProject = tools.find((tool) => tool.name === "atlas-create-project");
3333
expectDefined(createProject);
@@ -36,7 +36,7 @@ describeWithAtlas("projects", (integration) => {
3636
expect(createProject.inputSchema.properties).toHaveProperty("projectName");
3737
expect(createProject.inputSchema.properties).toHaveProperty("organizationId");
3838
});
39-
it("should create a project", async () => {
39+
itWithRetry("should create a project", async () => {
4040
const response = await integration.mcpClient().callTool({
4141
name: "atlas-create-project",
4242
arguments: { projectName: projName },
@@ -48,7 +48,7 @@ describeWithAtlas("projects", (integration) => {
4848
});
4949
});
5050
describe("atlas-list-projects", () => {
51-
it("should have correct metadata", async () => {
51+
itWithRetry("should have correct metadata", async () => {
5252
const { tools } = await integration.mcpClient().listTools();
5353
const listProjects = tools.find((tool) => tool.name === "atlas-list-projects");
5454
expectDefined(listProjects);
@@ -57,10 +57,9 @@ describeWithAtlas("projects", (integration) => {
5757
expect(listProjects.inputSchema.properties).toHaveProperty("orgId");
5858
});
5959

60-
it("returns project names", async () => {
60+
itWithRetry("returns project names", async () => {
6161
const response = await integration.mcpClient().callTool({ name: "atlas-list-projects", arguments: {} });
6262
const elements = getResponseElements(response);
63-
expect(elements).toHaveLength(2);
6463
expect(elements[0]?.text).toMatch(/Found \d+ projects/);
6564
expect(elements[1]?.text).toContain("<untrusted-user-data-");
6665
expect(elements[1]?.text).toContain(projName);

0 commit comments

Comments
 (0)