remix icon indicating copy to clipboard operation
remix copied to clipboard

`@remix-run/web-fetch` causes tests to error after upgrade to jest 28

Open penx opened this issue 2 years ago • 19 comments

What version of Remix are you using?

1.5.1

Steps to Reproduce

  • update jest-related dependencies to v28 as per #3400
  • add transformIgnorePatterns as per https://github.com/remix-run/remix/pull/3400#issuecomment-1147594562
  • run yarn test:primary

Expected Behavior

Tests should pass

Actual Behavior

    TypeError: Class extends value undefined is not a constructor or null

      34 | class NodeRequest extends WebRequest {
      35 |   constructor(info: NodeRequestInfo, init?: NodeRequestInit) {
    > 36 |     super(info, init as RequestInit);
         |                                     ^
      37 |   }
      38 |

This seems to relate to the types output by @remix-run/web-fetch:

export { default, fetch, Headers, Request, Response } from "./fetch.js";
export { ReadableStream, Blob, FormData } from "./package.js";
//# sourceMappingURL=lib.node.d.ts.map

node_modules/@remix-run/web-fetch/dist/src/lib.node.d.ts

fetch.js and package.js do not exist in the distributed @remix-run/web-fetch and should either be included or lib.node.d.ts should be pointing to fetch.d.ts and package.d.ts

penx avatar Jun 06 '22 17:06 penx

@penx You can always create a PR to https://github.com/remix-run/web-std-io if you want.

MichaelDeBoey avatar Jun 06 '22 17:06 MichaelDeBoey

On closer inspection, vscode's ts server seems to be able to resolve WebRequest to src/request.js (via dist/src/lib.node.d.ts, I assume via the source map), whereas Jest (or babel) is complaining, so perhaps this is a babel or config issue.

penx avatar Jun 06 '22 19:06 penx

@penx Would be nice if we could find the root cause.

MichaelDeBoey avatar Jun 06 '22 19:06 MichaelDeBoey

I'm looking 😄 if I can't figure it out soon I may need to look again later in the week. My understanding is Jest is configured to use Babel to compile the TS, which is reporting the TypeError due to not being able to resolve the type via the sourcemap, wheras TypeScript manages to do this.

edit: having said that, I don't think Babel checks types...

I haven't yet found any issues on babel referencing this.

I am wondering whether ts-jest has been considered?

penx avatar Jun 06 '22 20:06 penx

I haven't completely traced the source of the issue but it seems changing

    ".": {
      "browser": "./src/lib.js",
      "require": "./dist/lib.node.cjs",
      "import": "./src/lib.node.js",
      "types": "./dist/src/lib.node.d.ts"
    },

to

    ".": {
      "require": "./dist/lib.node.cjs",
      "import": "./src/lib.node.js",
      "types": "./dist/src/lib.node.d.ts",
      "browser": "./src/lib.js"
    },

...in the @remix-run/web-fetch package.json seems to resolve this issue.

There are continued Jest issues after this though so I'll try to keep digging.

penx avatar Jun 06 '22 20:06 penx

Ok I have test:primary all passing via either this change above or adding to transformIgnorePatterns

  transformIgnorePatterns: [
    "/node_modules/(?!(@remix-run/web-fetch|@remix-run/web-blob|@remix-run/web-stream|@remix-run/web-form-data|@remix-run/web-file|@web3-storage/multipart-parser)/)",
  ],

I was going to suggest the above change anyway as it the exports order is important and I don't understand why the browser export would appear first (or why it would point to the source) so can raise a PR for that.

penx avatar Jun 06 '22 20:06 penx

https://github.com/remix-run/web-std-io/pull/11

penx avatar Jun 06 '22 20:06 penx

Read something about Community Conditions Definitions today (can't remember where though 😅), which says types should always be first. So that might already be a good thing to change.

https://nodejs.org/api/packages.html#community-conditions-definitions

MichaelDeBoey avatar Jun 06 '22 20:06 MichaelDeBoey

Changing the order to

      "types": "./dist/src/lib.node.d.ts",
      "browser": "./src/lib.js",
      "require": "./dist/lib.node.cjs",
      "import": "./src/lib.node.js"

Still results in the same issue, though

      "types": "./dist/src/lib.node.d.ts",
      "require": "./dist/lib.node.cjs",
      "import": "./src/lib.node.js",
      "browser": "./src/lib.js"

It is fixed as before. I'd read about the types export recently too - I'll update my PR to do that.

penx avatar Jun 06 '22 20:06 penx

@penx Yeah I think you referenced it somewhere. Just can't find it anymore 😕

MichaelDeBoey avatar Jun 06 '22 21:06 MichaelDeBoey

"types" - can be used by typing systems to resolve the typing file for the given export. This condition should always be included first.

https://nodejs.org/api/packages.html

Not sure if this is what you mean you couldn't find as that's what you just linked to :-)

penx avatar Jun 06 '22 21:06 penx

@penx I meant the thing you referenced that was referencing Community Conditions Definitions.

MichaelDeBoey avatar Jun 06 '22 21:06 MichaelDeBoey

@penx It was mentioned in https://github.com/GoogleCloudPlatform/functions-framework-nodejs/pull/461#discussion_r881220889.

Do we still need the update jest to v28 after that change?

MichaelDeBoey avatar Jun 06 '22 21:06 MichaelDeBoey

Ah ok, I was about to link to these which I've been looking at over last couple days

  • https://nodejs.org/api/esm.html#esm_main_entry_point_export
  • https://github.com/evanw/esbuild/issues/187

penx avatar Jun 06 '22 21:06 penx

Do we still need the update jest to v28 after that change?

yes I am pretty sure the jest update is still needed so that it can resolve

import { getTestServer } from "@google-cloud/functions-framework/testing";

From what I remember, before Jest 28, Jest won't look for exports defined in package.json

penx avatar Jun 06 '22 21:06 penx

Although I'm not sure why https://github.com/GoogleCloudPlatform/functions-framework-nodejs/pull/461 is needed - when the d.ts files are in the same folder as the source they should be resolved automatically.

penx avatar Jun 06 '22 21:06 penx

I was able to get most tests working following this thread, but I still cannot get a simple fetch request to pass. I always get this error:

TypeError: webBlob.ReadableStream is not a constructor

      at fromStream (node_modules/@remix-run/web-fetch/src/body.js:482:17)
      at new Body (node_modules/@remix-run/web-fetch/src/body.js:96:17)
      at new Response (node_modules/@remix-run/web-fetch/src/response.js:30:3)
      at ClientRequest.<anonymous> (node_modules/@remix-run/web-fetch/src/fetch.js:262:16)

  ● MSW test with Remix 1.5.1

    Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close

I'm transforming these files within jest:

transformIgnorePatterns: [
    "/node_modules/(?!(@remix-run/web-fetch|@remix-run/web-blob|@remix-run/web-stream|@remix-run/web-form-data|@remix-run/web-file|@web3-storage/multipart-parser)/)"
  ],
  transform: {
    "^.+\\.(js|ts)$": "ts-jest",
  },

Here is my fetch request:

export const fetchExampleTest = async () => {
  const url = 'https://jsonplaceholder.typicode.com/todos/1';
  return await fetch(url, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    }
  })
}

Once I import this into the test and try to run it - I get that error. Here is my repo: https://github.com/spencersmb/remix-msw

spencersmb avatar Jun 10 '22 02:06 spencersmb

@penx is this still a problem for you?

machour avatar Jan 22 '23 10:01 machour

This was preventing the upgrade from Jest 27 to 28+

Remix is still using Jest 27 and the upstream PR I raised to resolve this has not been merged, so I am pretty sure it is still an issue.

https://github.com/remix-run/web-std-io/pull/11

penx avatar Jan 22 '23 10:01 penx

For what it's worth, we're running into this exact same issue and had to downgrade to Jest 27. I guess we're blocked until Remix upgrades to Jest 28?

    /Users/vpfaulkner/Documents/Code/yellowhat/appy/node_modules/@remix-run/web-fetch/src/lib.js:4
    export { ReadableStream, Blob, FormData  } from './package.js';
    ^^^^^^

    SyntaxError: Unexpected token 'export'

      1 | import type { ActionArgs } from "@remix-run/node"
    > 2 | import { json } from "@remix-run/node"

Our Jest config:

module.exports = {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  transform: {
    "^.+\\.(ts|tsx)?$": "ts-jest",
  },
  moduleNameMapper: {
    "^~/(.*)$": "<rootDir>/app/$1",
  },
}

vpfaulkner avatar Mar 09 '23 15:03 vpfaulkner

We ran into the same problem when attempting to upgrade to Jest 28 (or Jest 29 for that matter). I have not tested the fix in https://github.com/remix-run/web-std-io/pull/11 but that seems like a simple fix to unblock those of us who would like to upgrade Jest.

zmdavis avatar Jul 18 '23 23:07 zmdavis

The actual fix wouldn't be https://github.com/remix-run/web-std-io/pull/11, but https://github.com/remix-run/web-std-io/pull/43 instead

MichaelDeBoey avatar Aug 23 '23 01:08 MichaelDeBoey