From 2504c630d846468ca591243147a90f612315e177 Mon Sep 17 00:00:00 2001 From: Amine Ilidrissi <38422328+aminevg@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:23:55 +0900 Subject: [PATCH 1/3] Stabilize flaky Vitest fixtures and parallel builds - isolate Vite cache dirs per run - avoid shared dist cleanup in fixture teardown - raise Vitest timeouts and use forked workers --- packages/core/tests/dev/error.test.ts | 14 +++++++++----- packages/core/tests/fixture.ts | 19 +++++++++++-------- packages/core/vitest.config.ts | 4 +++- packages/hono/tests/cli.test.ts | 19 ++++++++++++++++--- packages/hono/tests/fixture.ts | 24 +++++++++++------------- packages/hono/vitest.config.ts | 3 ++- vitest.config.ts | 3 ++- 7 files changed, 54 insertions(+), 32 deletions(-) diff --git a/packages/core/tests/dev/error.test.ts b/packages/core/tests/dev/error.test.ts index 3fe835d..1c1dfc8 100644 --- a/packages/core/tests/dev/error.test.ts +++ b/packages/core/tests/dev/error.test.ts @@ -3,23 +3,26 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; describe("dev error fixture", () => { let fixture: ReturnType; + let stop: () => Promise; beforeEach(() => { fixture = getFixture("dev.basic"); + stop = () => fixture.clean(); vi.spyOn(console, "error").mockImplementation(() => {}); }); afterEach(async () => { vi.restoreAllMocks(); - await fixture.clean(); + await stop(); }); it("renders the Astro error overlay", async () => { - const { render } = await fixture.startDevServer({ + const devServer = await fixture.startDevServer({ config: { logLevel: "silent" }, }); + stop = devServer.stop; - const response = await render({ + const response = await devServer.render({ component: "error", partial: false, }); @@ -30,15 +33,16 @@ describe("dev error fixture", () => { }); it("throws an error when hmr.overlay is false", async () => { - const { render } = await fixture.startDevServer({ + const devServer = await fixture.startDevServer({ config: { logLevel: "silent", vite: { server: { hmr: { overlay: false } } }, }, }); + stop = devServer.stop; await expect( - render({ + devServer.render({ component: "error", partial: false, }), diff --git a/packages/core/tests/fixture.ts b/packages/core/tests/fixture.ts index 482cd14..87514c5 100644 --- a/packages/core/tests/fixture.ts +++ b/packages/core/tests/fixture.ts @@ -47,19 +47,20 @@ export function getFixture(fixtureName: string): { `dist-${Math.random().toString(36).substring(2, 15)}`, ); + // Isolate Vite dep-optimization cache per Vitest run to prevent + // ENOTEMPTY race when multiple `pnpm test` processes run in parallel. + const viteCacheDir = path.join( + import.meta.dirname, + "..", + "node_modules", + `.vite-${process.ppid || process.pid}`, + ); + const clean = async () => { await rm(outDir, { recursive: true, force: true, }); - await rm(path.join(fixtureRoot, ".astro"), { - recursive: true, - force: true, - }); - await rm(path.join(fixtureRoot, "node_modules"), { - recursive: true, - force: true, - }); }; const DEV_TEST_ADDRESS = "http://host-placeholder.test"; @@ -78,6 +79,7 @@ export function getFixture(fixtureName: string): { { root: fixtureRoot, logLevel: "warn", + vite: { cacheDir: viteCacheDir }, }, params?.config ?? {}, ), @@ -115,6 +117,7 @@ export function getFixture(fixtureName: string): { outDir, logLevel: "warn", vite: { + cacheDir: viteCacheDir, build: { rollupOptions: { external: ["@/context"] }, }, diff --git a/packages/core/vitest.config.ts b/packages/core/vitest.config.ts index 53fea7a..624f7c1 100644 --- a/packages/core/vitest.config.ts +++ b/packages/core/vitest.config.ts @@ -8,6 +8,8 @@ export default defineConfig({ "@/": `${path.resolve(import.meta.dirname, "src")}/`, "@tests/": `${path.resolve(import.meta.dirname, "tests")}/`, }, - testTimeout: 30000, + testTimeout: 120000, + hookTimeout: 60000, + pool: "forks", }, }); diff --git a/packages/hono/tests/cli.test.ts b/packages/hono/tests/cli.test.ts index 51ddaf2..91c803f 100644 --- a/packages/hono/tests/cli.test.ts +++ b/packages/hono/tests/cli.test.ts @@ -1,4 +1,4 @@ -import { readFile } from "node:fs/promises"; +import { mkdir, readFile, rm, symlink } from "node:fs/promises"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { runCli } from "../src/cli/run"; @@ -30,12 +30,25 @@ describe("cli", () => { }); it("builds the fixture when --root is provided before the command", async () => { + // Use the unique outDir as a build root (with symlinks to fixture source) + // to avoid parallel build conflicts on the shared dist/ directory. + const buildRoot = fixture.outDir; + await mkdir(buildRoot, { recursive: true }); + await symlink( + path.join(fixture.fixtureRoot, "astro.config.ts"), + path.join(buildRoot, "astro.config.ts"), + ); + await symlink( + path.join(fixture.fixtureRoot, "src"), + path.join(buildRoot, "src"), + ); + await expect( - runCli(["--root", fixture.fixtureRoot, "build"]), + runCli(["--root", buildRoot, "build"]), ).resolves.toBe(undefined); const output = await readFile( - path.join(fixture.fixtureRoot, "dist", "client", "index.html"), + path.join(buildRoot, "dist", "client", "index.html"), "utf-8", ); diff --git a/packages/hono/tests/fixture.ts b/packages/hono/tests/fixture.ts index 03149b6..9c8def7 100644 --- a/packages/hono/tests/fixture.ts +++ b/packages/hono/tests/fixture.ts @@ -42,20 +42,17 @@ export function getFixture(fixtureName: string): { `dist-${Math.random().toString(36).substring(2, 15)}`, ); + // Isolate Vite dep-optimization cache per Vitest run to prevent + // ENOTEMPTY race when multiple `pnpm test` processes run in parallel. + const viteCacheDir = path.join( + import.meta.dirname, + "..", + "node_modules", + `.vite-${process.ppid || process.pid}`, + ); + const clean = async (): Promise => { await rm(outDir, { recursive: true, force: true }); - await rm(path.join(fixtureRoot, "dist"), { - recursive: true, - force: true, - }); - await rm(path.join(fixtureRoot, ".astro"), { - recursive: true, - force: true, - }); - await rm(path.join(fixtureRoot, "node_modules"), { - recursive: true, - force: true, - }); }; return { @@ -69,6 +66,7 @@ export function getFixture(fixtureName: string): { outDir, logLevel: "warn", vite: { + cacheDir: viteCacheDir, build: { rollupOptions: { external: ["@gomighty/core/context"], @@ -94,7 +92,7 @@ export function getFixture(fixtureName: string): { const middleware = devMiddleware({ ...params, config: mergeConfig( - { root: fixtureRoot, logLevel: "warn" }, + { root: fixtureRoot, logLevel: "warn", vite: { cacheDir: viteCacheDir } }, params?.config ?? {}, ), }); diff --git a/packages/hono/vitest.config.ts b/packages/hono/vitest.config.ts index 20a75d0..7b6aeb5 100644 --- a/packages/hono/vitest.config.ts +++ b/packages/hono/vitest.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ alias: { "@/": `${path.resolve(import.meta.dirname, "src")}/`, }, - testTimeout: 30000, + testTimeout: 120000, + hookTimeout: 60000, }, }); diff --git a/vitest.config.ts b/vitest.config.ts index 7959d17..4968b89 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { projects: ["packages/*"], - testTimeout: 30000, + testTimeout: 120000, + hookTimeout: 60000, }, }); From 5dc3a8748d136d10a69eec3a7f215ef58b108748 Mon Sep 17 00:00:00 2001 From: Amine Ilidrissi <38422328+aminevg@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:32:59 +0900 Subject: [PATCH 2/3] Stabilize Hono CLI test fixtures - Simplify the build assertion formatting - Normalize fixture config formatting for consistency --- packages/hono/tests/cli.test.ts | 8 ++++---- packages/hono/tests/fixture.ts | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/hono/tests/cli.test.ts b/packages/hono/tests/cli.test.ts index 91c803f..42f6593 100644 --- a/packages/hono/tests/cli.test.ts +++ b/packages/hono/tests/cli.test.ts @@ -1,4 +1,4 @@ -import { mkdir, readFile, rm, symlink } from "node:fs/promises"; +import { mkdir, readFile, symlink } from "node:fs/promises"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { runCli } from "../src/cli/run"; @@ -43,9 +43,9 @@ describe("cli", () => { path.join(buildRoot, "src"), ); - await expect( - runCli(["--root", buildRoot, "build"]), - ).resolves.toBe(undefined); + await expect(runCli(["--root", buildRoot, "build"])).resolves.toBe( + undefined, + ); const output = await readFile( path.join(buildRoot, "dist", "client", "index.html"), diff --git a/packages/hono/tests/fixture.ts b/packages/hono/tests/fixture.ts index 9c8def7..1c660d0 100644 --- a/packages/hono/tests/fixture.ts +++ b/packages/hono/tests/fixture.ts @@ -92,7 +92,11 @@ export function getFixture(fixtureName: string): { const middleware = devMiddleware({ ...params, config: mergeConfig( - { root: fixtureRoot, logLevel: "warn", vite: { cacheDir: viteCacheDir } }, + { + root: fixtureRoot, + logLevel: "warn", + vite: { cacheDir: viteCacheDir }, + }, params?.config ?? {}, ), }); From e65643b1da915bf3426d07d86c1511ae7eb46fba Mon Sep 17 00:00:00 2001 From: Amine Ilidrissi <38422328+aminevg@users.noreply.github.com> Date: Mon, 23 Mar 2026 20:13:05 +0900 Subject: [PATCH 3/3] Remove forks pool from core Vitest config - Let Vitest use the default pool to reduce flaky test behavior --- packages/core/vitest.config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/vitest.config.ts b/packages/core/vitest.config.ts index 624f7c1..b95d3a5 100644 --- a/packages/core/vitest.config.ts +++ b/packages/core/vitest.config.ts @@ -10,6 +10,5 @@ export default defineConfig({ }, testTimeout: 120000, hookTimeout: 60000, - pool: "forks", }, });