Skip to content
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
2 changes: 1 addition & 1 deletion examples/with-typescript-esm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"esbuild-register": "^3.4.2",
"tinybench": "^4.0.1",
"typescript": "^5.1.3",
"vitest": "^3.2.4"
"vitest": "^4.0.18"
}
}
13 changes: 13 additions & 0 deletions examples/with-vitest-v3/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "with-vitest-v3",
"private": true,
"type": "module",
"scripts": {
"bench-vitest": "vitest bench --run"
},
"devDependencies": {
"@codspeed/vitest-plugin": "workspace:*",
"typescript": "^5.1.3",
"vitest": "^3.2.4"
}
}
20 changes: 20 additions & 0 deletions examples/with-vitest-v3/src/fibonacci.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { bench, describe } from "vitest";
import { iterativeFibonacci, recursiveFibonacci } from "./fibonacci";

describe("fibonacci", () => {
bench("recursive fibo 15", () => {
recursiveFibonacci(15);
});

bench("recursive fibo 20", () => {
recursiveFibonacci(20);
});

bench("iterative fibo 15", () => {
iterativeFibonacci(15);
});

bench("iterative fibo 20", () => {
iterativeFibonacci(20);
});
});
17 changes: 17 additions & 0 deletions examples/with-vitest-v3/src/fibonacci.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export function recursiveFibonacci(n: number): number {
if (n < 2) {
return n;
}
return recursiveFibonacci(n - 1) + recursiveFibonacci(n - 2);
}

export function iterativeFibonacci(n: number): number {
let a = 0;
let b = 1;
for (let i = 0; i < n; i++) {
const temp = a + b;
a = b;
b = temp;
}
return a;
}
13 changes: 13 additions & 0 deletions examples/with-vitest-v3/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"lib": ["es2023"],
"module": "ESNext",
"verbatimModuleSyntax": true,
"target": "es2022",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "Node"
}
}
6 changes: 6 additions & 0 deletions examples/with-vitest-v3/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import codspeedPlugin from "@codspeed/vitest-plugin";
import { defineConfig } from "vitest/config";

export default defineConfig({
plugins: [codspeedPlugin()],
});
4 changes: 2 additions & 2 deletions packages/vitest-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
"peerDependencies": {
"tinybench": ">=2.9.0",
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",
"vitest": "^3.2"
"vitest": "^3.2 || ^4"
},
"devDependencies": {
"@total-typescript/shoehorn": "^0.1.1",
"execa": "^8.0.1",
"tinybench": "^2.9.0",
"vite": "^7.0.0",
"vitest": "^3.2.4"
"vitest": "^4.0.18"
}
}
67 changes: 65 additions & 2 deletions packages/vitest-plugin/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ const coreMocks = vi.hoisted(() => {
};
});

const fsMocks = vi.hoisted(() => {
let mockVersion = "4.0.18"; // default to v4
return {
readFileSync: vi.fn((path: string) => {
if (path.includes("vitest/package.json")) {
return JSON.stringify({ version: mockVersion });
}
throw new Error(`File not found: ${path}`);
}),
setMockVersion: (version: string) => {
mockVersion = version;
},
};
});

const resolvedCodSpeedPlugin = codspeedPlugin();
const applyPluginFunction = resolvedCodSpeedPlugin.apply;
if (typeof applyPluginFunction !== "function")
Expand All @@ -20,6 +35,12 @@ vi.mock("@codspeed/core", async (importOriginal) => {
return { ...mod, ...coreMocks };
});

vi.mock("fs", () => {
return {
readFileSync: fsMocks.readFileSync,
};
});

console.warn = vi.fn();

describe("codSpeedPlugin", () => {
Expand Down Expand Up @@ -79,12 +100,51 @@ describe("codSpeedPlugin", () => {
});
});

it("should apply the codspeed config", async () => {
it("should apply the codspeed config for v4", () => {
const config = resolvedCodSpeedPlugin.config;
if (typeof config !== "function")
throw new Error("config is not a function");

expect(config.call({} as never, {}, fromPartial({}))).toStrictEqual({
const result = config.call({} as never, {}, fromPartial({}));

expect(result).toStrictEqual({
test: {
globalSetup: [
expect.stringContaining("packages/vitest-plugin/src/globalSetup.ts"),
],
pool: "forks",
execArgv: [
"--interpreted-frames-native-stack",
"--allow-natives-syntax",
"--hash-seed=1",
"--random-seed=1",
"--no-opt",
"--predictable",
"--predictable-gc-schedule",
"--expose-gc",
"--no-concurrent-sweeping",
"--max-old-space-size=4096",
],
runner: expect.stringContaining(
"packages/vitest-plugin/src/simulation.ts"
),
},
});
});

it("should apply the codspeed config for v3 with poolOptions", () => {
// Set mock version to v3
fsMocks.setMockVersion("3.2.0");

// Create a new plugin instance to pick up the mocked version
const v3Plugin = codspeedPlugin();
const config = v3Plugin.config;
if (typeof config !== "function")
throw new Error("config is not a function");

const result = config.call({} as never, {}, fromPartial({}));

expect(result).toStrictEqual({
test: {
globalSetup: [
expect.stringContaining("packages/vitest-plugin/src/globalSetup.ts"),
Expand All @@ -111,5 +171,8 @@ describe("codSpeedPlugin", () => {
),
},
});

// Reset mock version back to v4
fsMocks.setMockVersion("4.0.18");
});
});
36 changes: 31 additions & 5 deletions packages/vitest-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
SetupInstrumentsRequestBody,
SetupInstrumentsResponse,
} from "@codspeed/core";
import { readFileSync } from "fs";
import { createRequire } from "module";
import { join } from "path";
import { Plugin } from "vite";
import { type ViteUserConfig } from "vitest/config";
Expand All @@ -20,6 +22,19 @@ function getCodSpeedFileFromName(name: string) {
return join(__dirname, `${name}.${fileExtension}`);
}

function getVitestMajorVersion(): number | null {
try {
// Resolve vitest from the project's perspective (cwd), not from the plugin's location
// This ensures we detect the vitest version the user has installed
const require = createRequire(join(process.cwd(), "package.json"));
const vitestPkgPath = require.resolve("vitest/package.json");
const vitestPkg = JSON.parse(readFileSync(vitestPkgPath, "utf-8"));
return parseInt(vitestPkg.version.split(".")[0], 10);
} catch {
return null;
}
}

function getRunnerFile(): string | undefined {
const codspeedRunnerMode = getCodspeedRunnerMode();
if (codspeedRunnerMode === "disabled") {
Expand Down Expand Up @@ -48,15 +63,26 @@ export default function codspeedPlugin(): Plugin {
config(): ViteUserConfig {
const runnerFile = getRunnerFile();
const runnerMode = getCodspeedRunnerMode();
const v8Flags = getV8Flags();
const vitestMajorVersion = getVitestMajorVersion();
// by default, assume Vitest v4 or higher
const isVitestV4OrHigher = (vitestMajorVersion ?? 4) >= 4;

const config: ViteUserConfig = {
test: {
pool: "forks",
poolOptions: {
forks: {
execArgv: getV8Flags(),
},
},
...(isVitestV4OrHigher
? { execArgv: v8Flags }
: {
// Compat with Vitest v3
// See: https://vitest.dev/guide/migration.html#pool-rework
// poolOptions only exists in Vitest v3
poolOptions: {
forks: {
execArgv: v8Flags,
},
},
}),
globalSetup: [getCodSpeedFileFromName("globalSetup")],
...(runnerFile && {
runner: runnerFile,
Expand Down
Loading
Loading