Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to test middleware with Jest #32848

Closed
davidrhoderick opened this issue Dec 27, 2021 · 18 comments · Fixed by #35181
Closed

Unable to test middleware with Jest #32848

davidrhoderick opened this issue Dec 27, 2021 · 18 comments · Fixed by #35181
Labels
Middleware Related to Next.js Middleware Testing Related to testing with Next.js.

Comments

@davidrhoderick
Copy link

What version of Next.js are you using?

12.0.7

What version of Node.js are you using?

16.13.1

What browser are you using?

Firefox

What operating system are you using?

Pop!_OS

How are you deploying your application?

Vercel

Describe the Bug

When trying to test _middleware.js with Jest, I'm unable to import { NextResponse } from 'next/server' without throwing an error SyntaxError: Unexpected token 'export' because next/server uses export { NextRequest } in line 1.

Expected Behavior

I would like to be able to test my _middleware.js authentication methodology.

To Reproduce

  1. Create a Next app with the aforementioned versions.
  2. Create a _middleware.js
  3. Create a test for it in Jest.
  4. Try to import NextResponse from next/server.
  5. Run tests.
  6. Get error.
@davidrhoderick davidrhoderick added the bug Issue was opened via the bug report template. label Dec 27, 2021
@davidrhoderick
Copy link
Author

davidrhoderick commented Dec 27, 2021

P.S. I've tried the following resolutions to no avail:

  1. Convert the project to Typescript.
  2. Switch to using the Babel compiler.
  3. Adding next/server to the list of transformIgnorePatterns.

And follow-up question: Just to get through this, is there something similar to NextResponse.next() that I can use with a standard Javascript Response?

@davidrhoderick
Copy link
Author

davidrhoderick commented Dec 27, 2021

P.P.S. Maybe this is a documentation issue because if I include NextResponse by import NextResponse from 'next/dist/server/web/spec-extension/response';, the error goes away. I just kept going by the documentation and that's what threw me...

EDIT: I can get rid of the Jest error if I do that but then the middleware doesn't work, so this isn't a solution and I don't think it's just documentation.

@vanpham981986

This comment has been minimized.

@balazsorban44
Copy link
Member

balazsorban44 commented Jan 4, 2022

Do you have a more elaborate reproduction? I would like to see your test file, or get an idea of what you are trying to do.

Have you followed this guide? https://nextjs.org/docs/testing#setting-up-jest-with-the-rust-compiler

@RenanLorijola
Copy link

I'm experiencing the same issue using babel.

@davidrhoderick have you found any solution for this?

@wovalle
Copy link

wovalle commented Jan 15, 2022

I'm also having this error: #31152 (comment)

@balazsorban44 here you can quickly verify: https://codesandbox.io/s/laughing-moon-ykbrs?file=/pages/index.test.ts

Just uncomment line 6 in pages/index.ts

@Markos-Th09
Copy link
Contributor

Jest only understands commonjs that's the problem

@wovalle
Copy link

wovalle commented Jan 20, 2022

Yeah I guessed so, but what's weird is that transformIgnorePatterns is not being respected by next/jest. I had to go back to use @swc/jest directly since I wanted to test middleware functions.

In case someone else is interested:

// jest.config.js

const ignoredModules = ["next"].join("|")

module.exports = {
  clearMocks: true,
  transformIgnorePatterns: [`/node_modules/(?!${ignoredModules})`],
  testEnvironment: "jest-environment-jsdom",
  transform: {
    "^.+\\.(t|j)sx?$": ["@swc/jest"],
  },
  setupFiles: ["<rootDir>/jest.setup.js"],
}

The real deal is adding node_modules/next to transformIgnorePatterns. Probably it could be optimized by only transforming files under next/server but this is good enough for my use case

@balazsorban44 balazsorban44 added the Testing Related to testing with Next.js. label Jan 20, 2022
@sgharms
Copy link

sgharms commented Jan 20, 2022

Thank you for leaving some breadcrumbs here, @wovalle , I'm definitely struggling with the same challenge at the moment. I'm surprised that transformIgnorePatterns is being ignored though! I may have a chance to test this out today and will try to confirm your observation.

@gmotyl
Copy link

gmotyl commented Jan 26, 2022

I struggle with the same issue, when transforming with babel-jest I got SyntaxError: Unexpected token 'export'
with ts-jest though it seems to respect transformIgnorePatterns but another error appears:
ReferenceError: Request is not defined

my middleware used for testing is simple

import { NextResponse } from 'next/server'

export const experimentMiddleware = () => {
  let res = NextResponse.next()

  return res
}

using this jest config:

const ignoredModules = ['next'].join('|')

module.exports = {
  verbose: true,
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
  testPathIgnorePatterns: ['/node_modules/', '/.next/'],
  testEnvironment: 'jest-environment-jsdom',
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'ts-jest'
  },
  transformIgnorePatterns: [`/node_modules/(?!${ignoredModules})`]
}

@wovalle
Copy link

wovalle commented Jan 26, 2022

@gom3s yeah node doesn't include fetch and you have to use a polyfill.

Import node-fetch or isomorphic-fetch in your jest.setup.ts

@gmotyl
Copy link

gmotyl commented Jan 26, 2022

It works!! thank you @wovalle

final setup that works for me

// jest.setup.ts
import 'isomorphic-fetch'
// jest.config.js
const ignoredModules = ['next'].join('|')

module.exports = {
  verbose: true,
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
  testPathIgnorePatterns: ['/node_modules/', '/.next/'],
  testEnvironment: 'jest-environment-jsdom',
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'ts-jest'
  },
  transformIgnorePatterns: [`/node_modules/(?!${ignoredModules})`]
}

@timneutkens timneutkens added the Middleware Related to Next.js Middleware label Jan 27, 2022
@ghost
Copy link

ghost commented Feb 2, 2022

My solution was create src/__mocks__/next/server.js with the following content, that fixed the issue to me

import { NextRequest } from 'next/dist/server/web/spec-extension/request';
import { NextResponse } from 'next/dist/server/web/spec-extension/response';

export { NextRequest, NextResponse };

@Toxiapo
Copy link

Toxiapo commented Feb 4, 2022

My solution was create src/__mocks__/next/server.js with the following content, that fixed the issue to me

import { NextRequest } from 'next/dist/server/web/spec-extension/request';
import { NextResponse } from 'next/dist/server/web/spec-extension/response';

export { NextRequest, NextResponse };

Did this solution work for others? I added this but now getting TypeError: (0 , _utils.myValidFunction) is not a function error

@javivelasco
Copy link
Member

We aim to ship very soon a Jest runtime that will allow you to test middleware code without doing anything special. Just a heads up that we are working on this!

@ValentinH
Copy link
Contributor

import { NextRequest } from 'next/dist/server/web/spec-extension/request';
import { NextResponse } from 'next/dist/server/web/spec-extension/response';

export { NextRequest, NextResponse };

I like this solution. This works for me. 🎉

@balazsorban44 balazsorban44 removed the bug Issue was opened via the bug report template. label Feb 16, 2022
@javivelasco javivelasco added this to the Next.js Middleware GA milestone Feb 18, 2022
@8byr0
Copy link

8byr0 commented Mar 6, 2022

This issue does not occur only with jest. The solution proposed by @vxcamiloxv is fine because jest has a __mocks__ predefined folder allowing to override packages but if you use another framework you won't be able to fix it like that.

I posted #35089 (comment) for anyone using a framework relying on ts-node/register.

Basically the solution is to setup ts-node to transpile next/server at runtime (instead of assuming it's already a commonjs module).

Basically:

// cucumber.js || nyc.js || whatever config file


// This prevents `Request is not defined` error
require("isomorphic-fetch");

const ignoredModules = ["next/server"].join("|");

require("ts-node").register({
  transpileOnly: true,
  ignore: [`node_modules/(?!${ignoredModules})`],
  // Do not add custom tsconfig here, it is managed under root tsconfig.json
});
// tsconfig.json
{
    "ts-node": {
        "compilerOptions": {
            // ...
            "module": "commonjs",
            "jsx": "react-jsx", // override jsx for ts-node
            "allowJs": true
            // ...
        }
    },
    "compilerOptions": {
        // ...
        "jsx": "preserve" // required by NextJS: will be automatically updated if you use another value
        //...
    },
    // ...
}

@kodiakhq kodiakhq bot closed this as completed in #35181 Mar 9, 2022
kodiakhq bot pushed a commit that referenced this issue Mar 9, 2022
If different contexts (using Jest, using Nx, etc), server.js is getting imported when using middleware and throwing the error: "SyntaxError: Unexpected token 'export'".

fixes #32848



## Bug

- [x] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`


Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com>
@github-actions
Copy link
Contributor

github-actions bot commented Apr 9, 2022

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 9, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Middleware Related to Next.js Middleware Testing Related to testing with Next.js.
Projects
None yet
Development

Successfully merging a pull request may close this issue.