miniflare icon indicating copy to clipboard operation
miniflare copied to clipboard

jest-environment-miniflare unable to find Durable Object for worker with default configuration

Open spelexander opened this issue 2 years ago • 4 comments

Hi! First up thanks for an awesome tool

I'm bumping into an issue where I'm unable to use jest-environment-miniflare for my worker because it's unable to find the Durable Object class:

 FAIL  src/worker.test.ts
  ● Test suite failed to run

    DurableObjectError [ERR_CLASS_NOT_FOUND]: Class "Channel" for Durable Object "channel" not found

      at DurableObjectsPlugin.reload (node_modules/@miniflare/durable-objects/src/plugin.ts:263:15)
      at EventTarget.#runAllReloads (node_modules/@miniflare/core/src/index.ts:667:24)
      at EventTarget.#reload (node_modules/@miniflare/core/src/index.ts:810:13)
      at async EventTarget.getGlobalScope (node_modules/@miniflare/core/src/index.ts:990:5)
      at async MiniflareEnvironment.setup (node_modules/jest-environment-miniflare/src/index.ts:206:27)

I'm able to run my worker using npx wrangler@beta dev --local and wrangler dev. I've also deployed it already without any issues.

My wrangler.toml:

name = "example"
main = "src/index.ts"
compatibility_date = "2022-05-19"

[durable_objects]
tag = "v1"
bindings = [
    { name = "channel", class_name = "Channel" }
]

[[migrations]]
tag = "v1" # Should be unique for each entry
new_classes = ["Channel"]

And jest.config.ts:

import type {Config} from 'jest';
export default (): Config => {
    return {
        "testEnvironment": "miniflare",    
    };
}

My package.json contains:

    ....
    "jest-environment-miniflare": "^2.6.0",
    "miniflare": "^2.6.0",
    ....
   "module": "./dist/worker.mjs"
   ....

I'm using esbuild with the following settings to build the worker from typescript: esbuild ./src/index.ts --bundle --platform=browser --target=esnext --format=esm --outfile=./dist/worker.mjs

I'm importing and exporting the Durable Object in my worker from another file that is at the same directory level named channel.ts (as I mentioned I can run, and deploy this worker with bindings fine).

And I can see the class does indeed end up in the built file ./dist/worker.mjs:

// src/channel.ts
var Channel = class {
...

Additionally I've tried manually specifying the durable object according to: https://miniflare.dev/testing/jest This has no effect. I've also tried using mounting as specified in the miniflare docs which hasn't worked.

Please let me know, If you can see anything obvious I'm doing wrong.

spelexander avatar Aug 07 '22 03:08 spelexander

Hey! 👋 Really glad you've found this tool useful! 🙂

I think the issue here is that Miniflare only partially supports the options added in Wrangler 2. Specifically, Miniflare doesn't support the main option in wrangler.toml, so can't find your script containing the Durable Objects.

To fix this, you can explicitly tell Miniflare where the script is in your Jest config using something like:

return {
  testEnvironment: "miniflare",
  testEnvironmentOptions: {
    // Miniflare doesn't yet support the `main` field in `wrangler.toml` so we
    // need to explicitly tell it where our built worker is. We also need to
    // explicitly mark it as an ES module.
    scriptPath: "dist/worker.mjs",
    modules: true,
  }
};

For a complete example project, see https://github.com/cloudflare/miniflare-typescript-esbuild-jest.

Hope this helps, and let me know if you have any other questions. 👍

mrbbot avatar Aug 11 '22 14:08 mrbbot

I'm running into a similar issue, but this is with getMiniflareBindings() I have a directory named serverless within a frontend project and I'm trying to run the tests from the outside because the whole project will be deployed on cloudflare pages.

Here is the error I'm running into:

error TS2304: Cannot find name 'getMiniflareBindings'.

my jest.config.ts:

import type { Config } from 'jest'
export default (): Config => {
return {
    preset: 'ts-jest',
    transform: {
        '^.+\\.ts?$': 'ts-jest'
    },
    testEnvironment: 'miniflare',
    testEnvironmentOptions: {
        // Miniflare doesn't yet support the `main` field in `wrangler.toml` so we
        // need to explicitly tell it where our built worker is. We also need to
        // explicitly mark it as an ES module.
        scriptPath: 'dist/index.mjs',
        modules: true
     }
   }
}

and my handler.test.ts file:

 import worker from '../src/index'

test('handle GET', async () => {
const env = getMiniflareBindings()
const result = await worker.fetch(new Request('/', { method: 'GET' }), env)
expect(result.status).toEqual(200)
const text = await result.text()
expect(text).toEqual('request method: GET')
})

da7a90-backup avatar Aug 18 '22 22:08 da7a90-backup

I just figured out I needed to create the globals.d.ts file in the test directory to be able to use the method as a global object

da7a90-backup avatar Aug 18 '22 22:08 da7a90-backup

now I'm running into the same issue as @spelexander and even after specifying ./dist/index.mjs in the jest config it still throws the same error

da7a90-backup avatar Aug 30 '22 16:08 da7a90-backup

Hey @da7a90-backup! Really sorry for the delayed response, seems like this issue got buried. 🙁 Is this still an issue for you? If it is, could you share your full logs?

mrbbot avatar Jan 09 '23 16:01 mrbbot

Hi! First up thanks for an awesome tool

I'm bumping into an issue where I'm unable to use jest-environment-miniflare for my worker because it's unable to find the Durable Object class:

 FAIL  src/worker.test.ts
  ● Test suite failed to run

    DurableObjectError [ERR_CLASS_NOT_FOUND]: Class "Channel" for Durable Object "channel" not found

      at DurableObjectsPlugin.reload (node_modules/@miniflare/durable-objects/src/plugin.ts:263:15)
      at EventTarget.#runAllReloads (node_modules/@miniflare/core/src/index.ts:667:24)
      at EventTarget.#reload (node_modules/@miniflare/core/src/index.ts:810:13)
      at async EventTarget.getGlobalScope (node_modules/@miniflare/core/src/index.ts:990:5)
      at async MiniflareEnvironment.setup (node_modules/jest-environment-miniflare/src/index.ts:206:27)

I'm able to run my worker using npx wrangler@beta dev --local and wrangler dev. I've also deployed it already without any issues.

My wrangler.toml:

name = "example"
main = "src/index.ts"
compatibility_date = "2022-05-19"

[durable_objects]
tag = "v1"
bindings = [
    { name = "channel", class_name = "Channel" }
]

[[migrations]]
tag = "v1" # Should be unique for each entry
new_classes = ["Channel"]

And jest.config.ts:

import type {Config} from 'jest';
export default (): Config => {
    return {
        "testEnvironment": "miniflare",    
    };
}

My package.json contains:

    ....
    "jest-environment-miniflare": "^2.6.0",
    "miniflare": "^2.6.0",
    ....
   "module": "./dist/worker.mjs"
   ....

I'm using esbuild with the following settings to build the worker from typescript: esbuild ./src/index.ts --bundle --platform=browser --target=esnext --format=esm --outfile=./dist/worker.mjs

I'm importing and exporting the Durable Object in my worker from another file that is at the same directory level named channel.ts (as I mentioned I can run, and deploy this worker with bindings fine).

And I can see the class does indeed end up in the built file ./dist/worker.mjs:

// src/channel.ts
var Channel = class {
...

Additionally I've tried manually specifying the durable object according to: https://miniflare.dev/testing/jest This has no effect. I've also tried using mounting as specified in the miniflare docs which hasn't worked.

Please let me know, If you can see anything obvious I'm doing wrong.

I am encountering a comparable issue with the vitest tool, where the test previously functioned correctly with KVnamespace, but it has ceased working since Durable Objects were implemented. Despite attempting every conceivable workaround for this and similar problems, I have been unable to find a solution thus far.

image

KamaniBhavin avatar May 03 '23 04:05 KamaniBhavin

Hey! 👋 We're planning on revamping the Vitest environment for Miniflare 3 soon, and will be sure to include docs for usage with Durable Objects. I'm going to close this issue as the original issue seems to be solved. 👍

mrbbot avatar Nov 07 '23 15:11 mrbbot