Skip to content

Commit

Permalink
Merge branch 'canary' into fix-30398
Browse files Browse the repository at this point in the history
  • Loading branch information
javivelasco committed Dec 1, 2021
2 parents 056131b + f225179 commit f8983ee
Show file tree
Hide file tree
Showing 104 changed files with 1,508 additions and 393 deletions.
8 changes: 7 additions & 1 deletion .github/labeler.json
Expand Up @@ -10,7 +10,8 @@
"packages/next-codemod/**",
"packages/eslint-plugin-next/**",
"packages/eslint-config-next/**",
"packages/next-env/**"
"packages/next-env/**",
"packages/next-swc/**"
],
"created-by: Chrome Aurora": [
{ "type": "user", "pattern": "spanicker" },
Expand All @@ -31,6 +32,11 @@
{ "type": "user", "pattern": "leerob" },
{ "type": "user", "pattern": "kdy1" },
{ "type": "user", "pattern": "timneutkens" }
],
"created-by: Next.js docs team": [
{ "type": "user", "pattern": "MaedahBatool" },
{ "type": "user", "pattern": "molebox" },
{ "type": "user", "pattern": "ismaelrumzan" }
]
}
}
8 changes: 4 additions & 4 deletions docs/advanced-features/static-html-export.md
Expand Up @@ -64,9 +64,9 @@ Features that require a Node.js server, or dynamic logic that cannot be computed

It's possible to use the [`getInitialProps`](/docs/api-reference/data-fetching/getInitialProps.md) API instead of `getStaticProps`, but it comes with a few caveats:

- `getInitialProps` cannot be used alongside `getStaticProps` or `getStaticPaths` on any given page. If you have dynamic routes, instead of using `getStaticPaths` you'll need to configure the [`exportPathMap`](/docs/api-reference/next.config.js/exportPathMap.md) parameter in your [`next.config.js`](/docs/api-reference/next.config.js/introduction.md) file to let the exporter know which HTML files it should output.
- When `getInitialProps` is called during export, the `req` and `res` fields of its [`context`](/docs/api-reference/data-fetching/getInitialProps.md#context-object) parameter will be empty objects, since during export there is no server running.
- `getInitialProps` **will be called on every client-side navigation**, if you'd like to only fetch data at build-time, switch to `getStaticProps`.
- `getInitialProps` should fetch from an API and cannot use Node.js-specific libraries or the file system like `getStaticProps` can.
- `getInitialProps` cannot be used alongside `getStaticProps` or `getStaticPaths` on any given page. If you have dynamic routes, instead of using `getStaticPaths` you'll need to configure the [`exportPathMap`](/docs/api-reference/next.config.js/exportPathMap.md) parameter in your [`next.config.js`](/docs/api-reference/next.config.js/introduction.md) file to let the exporter know which HTML files it should output.
- When `getInitialProps` is called during export, the `req` and `res` fields of its [`context`](/docs/api-reference/data-fetching/getInitialProps.md#context-object) parameter will be empty objects, since during export there is no server running.
- `getInitialProps` **will be called on every client-side navigation**, if you'd like to only fetch data at build-time, switch to `getStaticProps`.
- `getInitialProps` should fetch from an API and cannot use Node.js-specific libraries or the file system like `getStaticProps` can.

We recommend migrating towards `getStaticProps` over `getInitialProps` whenever possible.
22 changes: 16 additions & 6 deletions docs/api-reference/next/server.md
Expand Up @@ -4,19 +4,29 @@ description: Use Middleware to run code before a request is completed.

# next/server

Middleware is created by using a `middleware` function that lives inside a `_middleware` file. The Middleware API is based upon the native [`FetchEvent`](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent), [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), and [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) objects.
The `next/server` module provides several exports for server-only helpers, such as [Middleware](/docs/middleware.md).

## NextMiddleware

Middleware is created by using a `middleware` function that lives inside a `_middleware` file. The Middleware API is based upon the native [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request), [`FetchEvent`](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent), and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects.

These native Web API objects are extended to give you more control over how you manipulate and configure a response, based on the incoming requests.

The function signature:
The function signature is defined as follows:

```ts
import type { NextRequest, NextFetchEvent } from 'next/server'
type NextMiddlewareResult = NextResponse | Response | null | undefined

export type Middleware = (
type NextMiddleware = (
request: NextRequest,
event: NextFetchEvent
) => Promise<Response | undefined> | Response | undefined
) => NextMiddlewareResult | Promise<NextMiddlewareResult>
```
It can be imported from `next/server` with the following:
```ts
import type { NextMiddleware } from 'next/server'
```

The function can be a default export and as such, does **not** have to be named `middleware`. Though this is a convention. Also note that you only need to make the function `async` if you are running asynchronous code.
Expand All @@ -25,7 +35,7 @@ The function can be a default export and as such, does **not** have to be named

The `NextRequest` object is an extension of the native [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) interface, with the following added methods and properties:

- `cookie` - Has the cookies from the `Request`
- `cookies` - Has the cookies from the `Request`
- `nextUrl` - Includes an extended, parsed, URL object that gives you access to Next.js specific properties such as `pathname`, `basePath`, `trailingSlash` and `i18n`
- `geo` - Has the geo location from the `Request`
- `geo.country` - The country code
Expand Down
104 changes: 71 additions & 33 deletions docs/testing.md
@@ -1,5 +1,5 @@
---
description: Learn how to set up Next.js with three commonly used testing tools — Cypress, Jest, and React Testing Library.
description: Learn how to set up Next.js with three commonly used testing tools — Cypress, Playwright, Jest, and React Testing Library.
---

# Testing
Expand Down Expand Up @@ -243,55 +243,96 @@ You can learn more about Playwright and Continuous Integration from these resour

## Jest and React Testing Library

Jest and React Testing Library are frequently used together for **Unit Testing**.
Jest and React Testing Library are frequently used together for **Unit Testing**. There are three ways you can start using Jest within your Next.js application:

1. Using one of our [quickstart examples](https://nextjs.org/docs/testing#quickstart-2)
2. With the [Next.js Rust Compiler](https://nextjs.org/docs/testing#setting-up-jest-with-the-rust-compiler)
3. With [Babel](https://nextjs.org/docs/testing#setting-up-jest-with-babel)

The following sections will go through how you can set up Jest with each of these options:

### Quickstart

You can use `create-next-app` with the [with-jest example](https://github.com/vercel/next.js/tree/canary/examples/with-jest) to quickly get started with Jest and React Testing Library:
You can use `create-next-app` with the [with-jest](https://github.com/vercel/next.js/tree/canary/examples/with-jest) example to quickly get started with Jest and React Testing Library:

```bash
npx create-next-app@latest --example with-jest with-jest-app
```

### Manual setup
### Setting up Jest (with the Rust Compiler)

Since the release of [Next.js 12](https://nextjs.org/blog/next-12), Next.js now has built-in configuration for Jest.

To manually set up Jest and React Testing Library, install `jest` , `@testing-library/react`, `@testing-library/jest-dom` as well as some supporting packages:
To set up Jest, install `jest` , `@testing-library/react`, `@testing-library/jest-dom` and `react-test-renderer`:

```bash
npm install --save-dev jest babel-jest @testing-library/react @testing-library/jest-dom identity-obj-proxy react-test-renderer
npm install --save-dev jest @testing-library/react @testing-library/jest-dom react-test-renderer
```

**Configuring Jest**

Create a `jest.config.js` file in your project's root directory and add the following configuration options:
Create a `jest.config.js` file in your project's root directory and add the following:

```jsx
// jest.config.js
const nextJest = require('next/jest')

const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})

// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
}

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
```

Under the hood, `next/jest` is automatically configuring Jest for you, including:

- Setting up `transform` using [SWC](https://nextjs.org/docs/advanced-features/compiler)
- Auto mocking stylesheets (`.css`, `.module.css`, and their scss variants) and image imports
- Loading `.env` (and all variants) into `process.env`
- Ignoring `node_modules` from test resolving and transforms
- Ignoring `.next` from test resolving
- Loading `next.config.js` for flags that enable SWC transforms

### Setting up Jest (with Babel)

If you opt-out of the [Rust Compiler](https://nextjs.org/docs/advanced-features/compiler), you will need to manually configure Jest and install `babel-jest` and `identity-obj-proxy` in addition to the packages above.

Here are the recommended options to configure Jest for Next.js:

```jsx
// jest.config.js
module.exports = {
collectCoverageFrom: [
'**/*.{js,jsx,ts,tsx}',
'!**/*.d.ts',
'!**/node_modules/**',
],
moduleNameMapper: {
/* Handle CSS imports (with CSS modules)
https://jestjs.io/docs/webpack#mocking-css-modules */
// Handle CSS imports (with CSS modules)
// https://jestjs.io/docs/webpack#mocking-css-modules
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',

// Handle CSS imports (without CSS modules)
'^.+\\.(css|sass|scss)$': '<rootDir>/__mocks__/styleMock.js',

/* Handle image imports
https://jestjs.io/docs/webpack#handling-static-assets */
'^.+\\.(jpg|jpeg|png|gif|webp|avif|svg)$':
'<rootDir>/__mocks__/fileMock.js',
// Handle image imports
// https://jestjs.io/docs/webpack#handling-static-assets
'^.+\\.(jpg|jpeg|png|gif|webp|avif|svg)$': `<rootDir>/__mocks__/fileMock.js`,

// Handle module aliases
'^@/components/(.*)$': '<rootDir>/components/$1',
},
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
testEnvironment: 'jsdom',
transform: {
/* Use babel-jest to transpile tests with the next/babel preset
https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object */
// Use babel-jest to transpile tests with the next/babel preset
// https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
'^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
},
transformIgnorePatterns: [
Expand All @@ -301,55 +342,50 @@ module.exports = {
}
```

You can learn more about each option above in the [Jest docs](https://jestjs.io/docs/configuration).
You can learn more about each configuration option in the [Jest docs](https://jestjs.io/docs/configuration).

**Handling stylesheets and image imports**

These files aren't useful in tests but importing them may cause errors, so we will need to mock them. Create the mock files we referenced in the configuration above - `fileMock.js` and `styleMock.js` - inside a `__mocks__` directory:
Styleheets and images aren't used in the tests but importing them may cause errors, so they will need to be mocked. Create the mock files referenced in the configuration above - `fileMock.js` and `styleMock.js` - inside a `__mocks__` directory:

```json
```js
// __mocks__/fileMock.js

(module.exports = "test-file-stub")
module.exports = 'test-file-stub'
```

```json
```js
// __mocks__/styleMock.js

module.exports = {};
module.exports = {}
```

If you're running into the issue `"Failed to parse src "test-file-stub" on 'next/image'"`, add a '/' to your fileMock.

```json
```js
// __mocks__/fileMock.js

(module.exports = "/test-file-stub")
module.exports = '/test-file-stub'
```

For more information on handling static assets, please refer to the [Jest Docs](https://jestjs.io/docs/webpack#handling-static-assets).

**Extend Jest with custom matchers**
**Optional: Extend Jest with custom matchers**

`@testing-library/jest-dom` includes a set of convenient [custom matchers](https://github.com/testing-library/jest-dom#custom-matchers) such as `.toBeInTheDocument()` making it easier to write tests. You can import the custom matchers for every test by adding the following option to the Jest configuration file:

```json
```js
// jest.config.js

setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
```

Then, inside `jest.setup.js`, add the following import:

```jsx
// jest.setup.js

import '@testing-library/jest-dom/extend-expect'
```

If you need to add more setup options before each test, it's common to add them to the `jest.setup.js` file above.

**Absolute Imports and Module Path Aliases**
**Optional: Absolute Imports and Module Path Aliases**

If your project is using [Module Path Aliases](https://nextjs.org/docs/advanced-features/module-path-aliases), you will need to configure Jest to resolve the imports by matching the paths option in the `jsconfig.json` file with the `moduleNameMapper` option in the `jest.config.js` file. For example:

Expand All @@ -372,6 +408,8 @@ moduleNameMapper: {
}
```

### Creating your tests:

**Add a test script to package.json**

Add the Jest executable in watch mode to the `package.json` scripts:
Expand Down
15 changes: 15 additions & 0 deletions examples/with-jest-babel/.eslintrc.json
@@ -0,0 +1,15 @@
{
"root": true,
"extends": ["next/core-web-vitals"],
"plugins": ["testing-library"],
"overrides": [
// Only uses Testing Library lint rules in test files
{
"files": [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[jt]s?(x)"
],
"extends": ["plugin:testing-library/react"]
}
]
}
34 changes: 34 additions & 0 deletions examples/with-jest-babel/.gitignore
@@ -0,0 +1,34 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
23 changes: 23 additions & 0 deletions examples/with-jest-babel/README.md
@@ -0,0 +1,23 @@
# Next.js + Jest

This example shows how to configure Jest to work with Next.js and Babel. Since the release of Next.js 12, Next.js has in-built configuration for Jest with SWC. See the [with-jest](https://github.com/vercel/next.js/tree/canary/examples/with-jest) example for the latest implementation.

This includes Next.js' built-in support for Global CSS, CSS Modules, and TypeScript!

## How to Use

Quickly get started using [Create Next App](https://github.com/vercel/next.js/tree/canary/packages/create-next-app#readme)!

In your terminal, run the following command:

```bash
npx create-next-app --example with-jest with-jest-app
# or
yarn create next-app --example with-jest with-jest-app
```

## Run Jest Tests

```bash
npm test
```
File renamed without changes.
File renamed without changes.

0 comments on commit f8983ee

Please sign in to comment.