diff --git a/vscode/src/test/suite/helpers.ts b/vscode/src/test/suite/helpers.ts index 6c48a8bfb3..1d3cfd1fff 100644 --- a/vscode/src/test/suite/helpers.ts +++ b/vscode/src/test/suite/helpers.ts @@ -70,3 +70,21 @@ export function createContext() { }, } as unknown as FakeContext; } + +// Retries the given assertion function until it passes or the timeout (in ms) is exceeded. +// Polls every 500ms. If the assertion never passes, the last assertion error is thrown. +export async function retryForDuration(timeoutMs: number, fn: () => void) { + const deadline = Date.now() + timeoutMs; + + while (Date.now() < deadline) { + try { + fn(); + return; + } catch (_error) { + await new Promise((resolve) => setTimeout(resolve, 500)); + } + } + + // Final attempt — let it throw + fn(); +} diff --git a/vscode/src/test/suite/testController.test.ts b/vscode/src/test/suite/testController.test.ts index be904e49a1..cc80dcf2ea 100644 --- a/vscode/src/test/suite/testController.test.ts +++ b/vscode/src/test/suite/testController.test.ts @@ -749,7 +749,7 @@ suite("TestController", () => { assert.ok(runStub.started.calledWith(testItem)); assert.ok(runStub.passed.calledWith(testItem)); assert.ok(runStub.end.calledWithExactly()); - }).timeout(10000); + }).timeout(30000); test("refresh handler clears all items and starts from scratch", async () => { await controller.testController.resolveHandler!(undefined); diff --git a/vscode/src/test/suite/workspace.test.ts b/vscode/src/test/suite/workspace.test.ts index ab8fb9aa88..fe5a20d35a 100644 --- a/vscode/src/test/suite/workspace.test.ts +++ b/vscode/src/test/suite/workspace.test.ts @@ -10,7 +10,7 @@ import { beforeEach, afterEach } from "mocha"; import { Workspace } from "../../workspace"; import { FAKE_TELEMETRY } from "./fakeTelemetry"; -import { createContext, FakeContext } from "./helpers"; +import { createContext, FakeContext, retryForDuration } from "./helpers"; suite("Workspace", () => { let workspacePath: string; @@ -56,13 +56,13 @@ suite("Workspace", () => { fs.rmSync(path.join(gitDir, "rebase-apply")); } - // Give enough time for all watchers to fire and all debounces to run off - await new Promise((resolve) => setTimeout(resolve, 10000)); - - // The start call only happens once because of the inhibitRestart flag - assert.strictEqual(startStub.callCount, 1); - // The restart call only happens once because of the debounce - assert.strictEqual(restartSpy.callCount, 1); + // Retry assertions for up to 30 seconds to allow watchers and debounces to fire + await retryForDuration(30000, () => { + // The start call only happens once because of the inhibitRestart flag + assert.strictEqual(startStub.callCount, 1); + // The restart call only happens once because of the debounce + assert.strictEqual(restartSpy.callCount, 1); + }); }).timeout(60000); test("does not restart when watched files are touched without modifying contents", async () => {