Skip to content

honox createApp() vitest throws TypeError: (intermediate value).glob is not a function #350

Description

@awwong1

What version of HonoX are you using?

0.1.52

What steps can reproduce the bug?

Initialized a new project using create-hono version 0.19.4, setup @cloudflare/vitest-pool-workers test dependency following Cloudflare documentation.

See also minimal reproduction commit within awwong1/honox-cf-unit-test-issue@788fd4e#diff-b55cdbef4907b7045f32cc5360d48d262cca5f94062e353089f189f4460039e0

npm i -D @types/node vitest@~3.2.0 @cloudflare/vitest-pool-workers
npm uninstall @cloudfalre/workers-types
npx wrangler types

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "skipLibCheck": true,
    "lib": ["ESNext", "DOM"],
    "types": ["vite/client"],
    "jsx": "react-jsx",
    "jsxImportSource": "hono/jsx",
    "allowSyntheticDefaultImports": true
  },
  "include": ["**/*.ts", "**/*.tsx"]
}

vitest.config.ts

import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";

export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: "./wrangler.jsonc" },
      },
    },
  },
});

test.env.d.ts

declare module "cloudflare:test" {
  // ProvidedEnv controls the type of `import("cloudflare:test").env`
  interface ProvidedEnv extends Env {}
}

test/tsconfig.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "lib": ["ESNext"],
    "types": [
      "../worker-configuration.d.ts",
      "@cloudflare/vitest-pool-workers" // For `cloudflare:test` types
    ]
  },
  "include": ["./**/*.ts"]
}

test/unit.spec.ts

import {
  env,
  createExecutionContext,
  waitOnExecutionContext,
} from "cloudflare:test";
import { describe, it, expect } from "vitest";
// Import your worker so you can unit test it
import worker from "../app/server";

// For now, you'll need to do something like this to get a correctly-typed
// `Request` to pass to `worker.fetch()`.
const IncomingRequest = Request<unknown, IncomingRequestCfProperties>;

describe("Hello World worker", () => {
  it("responds with Hello World!", async () => {
    const request = new IncomingRequest("http://example.com/404");
    // Create an empty context to pass to `worker.fetch()`
    const ctx = createExecutionContext();
    const response = await worker.fetch(request, env, ctx);
    // Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions
    await waitOnExecutionContext(ctx);
    expect(response.status).toBe(404);
    expect(await response.text()).toBe("404 Not Found");
  });
});

What is the expected behavior?

Test should pass with no errors.

What do you see instead?

When running vitest the following output is observed:

 DEV  v3.2.4 honox-cf-unit-test-issue

[vpw:debug] Adding `enable_nodejs_tty_module` compatibility flag during tests as this feature is needed to support the Vitest runner.
[vpw:debug] Adding `enable_nodejs_fs_module` compatibility flag during tests as this feature is needed to support the Vitest runner.
[vpw:debug] Adding `enable_nodejs_http_modules` compatibility flag during tests as this feature is needed to support the Vitest runner.
[vpw:debug] Adding `enable_nodejs_perf_hooks_module` compatibility flag during tests as this feature is needed to support the Vitest runner.
[vpw:info] Starting isolated runtimes for vitest.config.ts...
[mf:warn] The latest compatibility date supported by the installed Cloudflare Workers Runtime is "2025-12-17",
but you've requested "2025-12-28". Falling back to "2025-12-17"...
stdout | test/unit.spec.ts
GET  /


⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  test/unit.spec.ts [ test/unit.spec.ts ]
TypeError: (intermediate value).glob is not a function
 ❯ createApp honox-cf-unit-test-issue/node_modules/honox/dist/server/with-defaults.js:8:50
 ❯ app/server.ts:4:13
      2| import { createApp } from 'honox/server'
      3|
      4| const app = createApp()
       |             ^
      5|
      6| showRoutes(app)
 ❯ test/unit.spec.ts:8:1

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯


 Test Files  1 failed (1)
      Tests  no tests
   Start at  11:12:27
   Duration  630ms (transform 26ms, setup 0ms, collect 0ms, tests 0ms, environment 0ms, prepare 66ms)

 FAIL  Tests failed. Watching for file changes...
       press h to show help, press q to quit

Additional information

Integration test appears to work without issues.

test/integration.spec.ts

import { SELF } from "cloudflare:test";
import { describe, it, expect } from "vitest";

describe("Hello World worker", () => {
  it("responds with not found and proper status for /404", async () => {
    const response = await SELF.fetch("http://example.com/404");
    expect(response.status).toBe(404);
    expect(await response.text()).toContain("404 Not Found");
  });
});

Activity

  1. yusukebe commented on Jan 2, 2026

    @yusukebe
    Member

    Hi @awwong1

    This is because the app imported from ../app/server you specified is using the Vite-specific function import.meta.glob internally since the app is not compiled. On the other hand, in the integration test, the app dist/index.js, which wrangler.json specifies, is compiled, and it works well.

    If you want to write a unit test, you can do it without @cloudflare/vitest-pool-workers.

    vitest.cofing.ts:

    import honox from 'honox/vite'
    import { defineConfig } from 'vitest/config'
    
    export default defineConfig({
      plugins: [honox()]
    })

    unit.spec.ts:

    import { describe, it, expect } from 'vitest'
    import app from '../app/server'
    
    describe('Hello World worker', () => {
      it('responds with Hello World!', async () => {
        const res = await app.fetch(new Request('http://localhost'))
        expect(res.status).toBe(200)
      })
    })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions