Skip to content

chore: migrate core (autocomplete) tests to vitest #6063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, test } from "vitest";
import { PYTHON_TEST_CASES, TYPESCRIPT_TEST_CASES } from "./testCases";
import { testRootPathContext } from "./testUtils";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { jest } from "@jest/globals";
import fs from "fs";
import path from "path";
import { expect, vi } from "vitest";

import Parser from "web-tree-sitter";
import { Position } from "../../../..";
Expand Down Expand Up @@ -36,7 +36,7 @@ export async function testRootPathContext(
const importDefinitionsService = new ImportDefinitionsService(ide);
const service = new RootPathContextService(importDefinitionsService, ide);

const getSnippetsMock = jest
const getSnippetsMock = vi
// @ts-ignore
.spyOn(service, "getSnippets")
// @ts-ignore
Expand All @@ -46,7 +46,7 @@ export async function testRootPathContext(

// Copy the folder to the test directory
const folderPath = path.join(
__dirname,
process.cwd(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vitest gets the actual __dirname where the file resides while for jest __dirname is equivalent process.cwd()

for example, in this case, __dirname for vitest would be /users/myuser/continue/core/autocomplete/context/root-path-context/test and for jest it would be /users/myuser/continue/core

Hence used process.cwd()

"autocomplete",
"context",
"root-path-context",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, expect, it } from "vitest";
import { stopAtStartOf, stopAtStopTokens } from "./charStream";

async function* createMockStream(chunks: string[]): AsyncGenerator<string> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { jest } from "@jest/globals";
import { beforeEach, describe, expect, it, Mock, vi } from "vitest";

import * as lineStream from "./lineStream";

// eslint-disable-next-line max-lines-per-function
describe("lineStream", () => {
let mockFullStop: jest.Mock;
let mockFullStop: Mock;

async function getLineGenerator(lines: any) {
return (async function* () {
Expand All @@ -25,7 +25,7 @@ describe("lineStream", () => {
}

beforeEach(() => {
mockFullStop = jest.fn();
mockFullStop = vi.fn();
});

describe("noTopLevelKeywordsMidline", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { setUpTestDir, tearDownTestDir } from "../../../test/testDir";
import { afterAll, beforeAll, beforeEach, describe, it } from "vitest";
import {
addToTestDir,
setUpTestDir,
tearDownTestDir,
} from "../../../test/testDir";

import { TEST_CASES_WITH_DIFF, TEST_CASES_WITHOUT_DIFF } from "./testCases";
import {
Expand All @@ -18,6 +23,7 @@ describe("Autocomplete filtering tests", () => {
beforeAll(async () => {
tearDownTestDir();
setUpTestDir();
addToTestDir([".continueignore"]);
});

afterAll(async () => {
Expand Down
1 change: 1 addition & 0 deletions core/autocomplete/filtering/test/util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { expect } from "vitest";
import MockLLM from "../../../llm/llms/Mock";
import { testConfigHandler, testIde } from "../../../test/fixtures";
import { joinPathsToUri } from "../../../util/uri";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { jest } from "@jest/globals";
import {
afterEach,
beforeEach,
describe,
expect,
Mock,
test,
vi,
} from "vitest";
import { GeneratorReuseManager } from "./GeneratorReuseManager";

function createMockGenerator(
Expand All @@ -14,7 +22,7 @@ function createMockGenerator(
}
}
};
const newGenerator = jest
const newGenerator = vi
.fn<() => AsyncGenerator<string>>()
.mockReturnValue(mockGenerator());

Expand All @@ -23,15 +31,15 @@ function createMockGenerator(

describe("GeneratorReuseManager", () => {
let reuseManager: GeneratorReuseManager;
let onErrorMock: jest.Mock;
let onErrorMock: Mock;

beforeEach(() => {
onErrorMock = jest.fn();
onErrorMock = vi.fn();
reuseManager = new GeneratorReuseManager(onErrorMock);
});

afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});

test("creates new generator when there is no current generator", async () => {
Expand Down Expand Up @@ -169,7 +177,7 @@ describe("GeneratorReuseManager", () => {
const mockGenerator = async function* () {
throw error;
};
const newGenerator = jest
const newGenerator = vi
.fn<() => AsyncGenerator<string>>()
.mockReturnValue(mockGenerator());

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { jest } from "@jest/globals";
import { describe, expect, it, vi } from "vitest";

import { ListenableGenerator } from "./ListenableGenerator";

Expand All @@ -16,7 +16,7 @@ describe("ListenableGenerator", () => {
it("should yield values from the source generator via tee()", async () => {
const values = [1, 2, 3];
const source = asyncGenerator(values);
const onError = jest.fn();
const onError = vi.fn();

const lg = new ListenableGenerator<number>(
source,
Expand All @@ -36,15 +36,15 @@ describe("ListenableGenerator", () => {
it("should allow listeners to receive values", async () => {
const values = [1, 2, 3];
const source = asyncGenerator(values, 10); // Introduce delay to simulate async behavior
const onError = jest.fn();
const onError = vi.fn();

const lg = new ListenableGenerator<number>(
source,
onError,
new AbortController(),
);

const listener = jest.fn();
const listener = vi.fn();

// Add listener after some delay to simulate late subscription
setTimeout(() => {
Expand All @@ -64,23 +64,23 @@ describe("ListenableGenerator", () => {
it("should buffer values for listeners added after some values have been yielded", async () => {
const values = [1, 2, 3];
const source = asyncGenerator(values, 10);
const onError = jest.fn();
const onError = vi.fn();

const lg = new ListenableGenerator<number>(
source,
onError,
new AbortController(),
);

const initialListener = jest.fn();
const initialListener = vi.fn();

lg.listen(initialListener);

// Wait for the first value to be yielded
await new Promise((resolve) => setTimeout(resolve, 15));

// Add a second listener
const newListener = jest.fn();
const newListener = vi.fn();
lg.listen(newListener);

// Wait for generator to finish
Expand All @@ -98,7 +98,7 @@ describe("ListenableGenerator", () => {
it("should handle cancellation", async () => {
const values = [1, 2, 3, 4, 5];
const source = asyncGenerator(values, 10);
const onError = jest.fn();
const onError = vi.fn();

const lg = new ListenableGenerator<number>(
source,
Expand Down Expand Up @@ -131,7 +131,7 @@ describe("ListenableGenerator", () => {
}

const source = errorGenerator();
const onError = jest.fn();
const onError = vi.fn();

const lg = new ListenableGenerator<number>(
source,
Expand All @@ -152,15 +152,15 @@ describe("ListenableGenerator", () => {
it("should notify listeners when the generator ends", async () => {
const values = [1, 2, 3];
const source = asyncGenerator(values);
const onError = jest.fn();
const onError = vi.fn();

const lg = new ListenableGenerator<number>(
source,
onError,
new AbortController(),
);

const listener = jest.fn();
const listener = vi.fn();
lg.listen(listener);

// Wait for the generator to finish
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { jest } from "@jest/globals";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { stopAfterMaxProcessingTime } from "./utils";

describe("stopAfterMaxProcessingTime", () => {
beforeEach(() => {
jest.useFakeTimers();
vi.useFakeTimers();
});

afterEach(() => {
jest.useRealTimers();
vi.useRealTimers();
});

async function* createMockStream(chunks: string[]): AsyncGenerator<string> {
Expand All @@ -28,7 +28,7 @@ describe("stopAfterMaxProcessingTime", () => {

it("should yield all chunks when maxTimeMs is not reached", async () => {
const mockStream = createMockStream(["Hello", " world", "!"]);
const fullStop = jest.fn();
const fullStop = vi.fn();
const result = stopAfterMaxProcessingTime(mockStream, 1000, fullStop);

const output = await streamToString(result);
Expand All @@ -37,11 +37,11 @@ describe("stopAfterMaxProcessingTime", () => {
expect(fullStop).not.toHaveBeenCalled();
});

it.only("should stop processing after max time is reached", async () => {
it("should stop processing after max time is reached", async () => {
// Mock implementation of Date.now
let currentTime = 0;
const originalDateNow = Date.now;
Date.now = jest.fn(() => currentTime);
Date.now = vi.fn(() => currentTime);

// Create a generator that we can control
async function* controlledGenerator(): AsyncGenerator<string> {
Expand All @@ -54,7 +54,7 @@ describe("stopAfterMaxProcessingTime", () => {
}
}

const fullStop = jest.fn();
const fullStop = vi.fn();
const maxTimeMs = 500;

const transformedGenerator = stopAfterMaxProcessingTime(
Expand Down Expand Up @@ -84,10 +84,10 @@ describe("stopAfterMaxProcessingTime", () => {
it("should check time only periodically based on checkInterval", async () => {
const chunks = Array(100).fill("x");
const mockStream = createMockStream(chunks);
const fullStop = jest.fn();
const fullStop = vi.fn();

// Spy on Date.now to count how many times it's called
const dateSpy = jest.spyOn(Date, "now");
const dateSpy = vi.spyOn(Date, "now");

// Stream should complete normally (not hitting the timeout)
await streamToString(
Expand All @@ -105,7 +105,7 @@ describe("stopAfterMaxProcessingTime", () => {

it("should handle empty stream gracefully", async () => {
const mockStream = createMockStream([]);
const fullStop = jest.fn();
const fullStop = vi.fn();
const result = stopAfterMaxProcessingTime(mockStream, 1000, fullStop);

const output = await streamToString(result);
Expand All @@ -117,7 +117,7 @@ describe("stopAfterMaxProcessingTime", () => {
it("should pass through all chunks if there's no timeout", async () => {
const chunks = Array(100).fill("test chunk");
const mockStream = createMockStream(chunks);
const fullStop = jest.fn();
const fullStop = vi.fn();

// Use undefined as timeout to simulate no timeout
const result = stopAfterMaxProcessingTime(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { beforeEach, expect, test, vi } from "vitest";
import { GitDiffCache } from "./gitDiffCache";

beforeEach(() => {
Expand All @@ -7,7 +8,7 @@ beforeEach(() => {

test("GitDiffCache returns cached results within cache time", async () => {
const mockDiff = ["file1.ts", "file2.ts"];
const getDiffFn = jest.fn().mockResolvedValue(mockDiff);
const getDiffFn = vi.fn().mockResolvedValue(mockDiff);
const cache = GitDiffCache.getInstance(getDiffFn, 1); // 1 second cache

const result1 = await cache.get();
Expand All @@ -20,7 +21,7 @@ test("GitDiffCache returns cached results within cache time", async () => {

test("GitDiffCache refreshes cache after expiration", async () => {
const mockDiff = ["file1.ts"];
const getDiffFn = jest.fn().mockResolvedValue(mockDiff);
const getDiffFn = vi.fn().mockResolvedValue(mockDiff);
const cache = GitDiffCache.getInstance(getDiffFn, 0.1); // 100ms cache

const result1 = await cache.get();
Expand All @@ -31,7 +32,7 @@ test("GitDiffCache refreshes cache after expiration", async () => {
});

test("GitDiffCache returns empty array on error", async () => {
const getDiffFn = jest.fn().mockRejectedValue(new Error("Git error"));
const getDiffFn = vi.fn().mockRejectedValue(new Error("Git error"));
const cache = GitDiffCache.getInstance(getDiffFn);

const result = await cache.get();
Expand All @@ -41,7 +42,7 @@ test("GitDiffCache returns empty array on error", async () => {
test("GitDiffCache reuses pending request", async () => {
const mockDiff = ["file1.ts"];
let resolvePromise: (value: string[]) => void;
const getDiffFn = jest.fn().mockImplementation(() => {
const getDiffFn = vi.fn().mockImplementation(() => {
return new Promise((resolve) => {
resolvePromise = resolve;
});
Expand All @@ -63,7 +64,7 @@ test("GitDiffCache reuses pending request", async () => {

test("GitDiffCache invalidate clears cache", async () => {
const mockDiff = ["file1.ts"];
const getDiffFn = jest.fn().mockResolvedValue(mockDiff);
const getDiffFn = vi.fn().mockResolvedValue(mockDiff);
const cache = GitDiffCache.getInstance(getDiffFn);

await cache.get();
Expand All @@ -74,8 +75,8 @@ test("GitDiffCache invalidate clears cache", async () => {
});

test("GitDiffCache maintains singleton instance", () => {
const getDiffFn1 = jest.fn();
const getDiffFn2 = jest.fn();
const getDiffFn1 = vi.fn();
const getDiffFn2 = vi.fn();

const instance1 = GitDiffCache.getInstance(getDiffFn1);
const instance2 = GitDiffCache.getInstance(getDiffFn2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*
*/

import { describe, expect, test } from "vitest";
import {
AutocompleteCodeSnippet,
AutocompleteDiffSnippet,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, expect, it } from "vitest";
import {
processTestCase,
type CompletionTestCase,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, expect, it } from "vitest";
import { processTestCase } from "./completionTestUtils";
import { processSingleLineCompletion } from "./processSingleLineCompletion";

Expand Down
1 change: 0 additions & 1 deletion core/config/yaml/LocalPlatformClient.vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ describe("LocalPlatformClient", () => {
expect(
(resolvedFQSNs[0] as SecretResult & { value: unknown })?.value,
).toBe(secretValue);
console.log("debug1 resolved fqsn", resolvedFQSNs);
});
});

Expand Down
Loading
Loading