Skip to content

Commit

Permalink
Update Jest and Vitest example for App Router. (#54989)
Browse files Browse the repository at this point in the history
Building off #54891, updates the `with-jest` and `with-vitest` examples with updated packages and App Router tests.
  • Loading branch information
leerob committed Sep 5, 2023
1 parent 7288c86 commit 7a256e6
Show file tree
Hide file tree
Showing 27 changed files with 233 additions and 32 deletions.
10 changes: 8 additions & 2 deletions examples/with-jest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

This example shows how to configure Jest to work with Next.js.

This includes Next.js' built-in support for Global CSS, CSS Modules and TypeScript.
This includes Next.js' built-in support for Global CSS, CSS Modules and TypeScript. This example also shows how to use Jest with the App Router and React Server Components.

> **Note:** Since tests can be co-located alongside other files inside the App Router, we have placed those tests in `app/` to demonstrate this behavior (which is different than `pages/`). You can still place all tests in `__tests__` if you prefer.
## Deploy your own

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-jest&project-name=with-jest&repository-name=with-jest)

## How to Use

Expand All @@ -22,7 +28,7 @@ yarn create next-app --example with-jest with-jest-app
pnpm create next-app --example with-jest with-jest-app
```

## Run Jest Tests
## Running Tests

```bash
npm test
Expand Down
3 changes: 3 additions & 0 deletions examples/with-jest/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @jest-environment jsdom
*/
import { render, screen } from '@testing-library/react'
import Home from '@/pages/index'

Expand Down
3 changes: 3 additions & 0 deletions examples/with-jest/__tests__/snapshot.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @jest-environment jsdom
*/
import { render } from '@testing-library/react'
import Home from '@/pages/index'

Expand Down
11 changes: 11 additions & 0 deletions examples/with-jest/app/blog/[slug]/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @jest-environment jsdom
*/
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import Page from './page'

it('App Router: Works with dynamic route segments', () => {
render(<Page params={{ slug: 'Test' }} />)
expect(screen.getByRole('heading')).toHaveTextContent('Slug: Test')
})
13 changes: 13 additions & 0 deletions examples/with-jest/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type Params = {
params: {
slug: string
}
}

export async function generateMetadata({ params }: Params) {
return { title: `Post: ${params.slug}` }
}

export default function Page({ params }: Params) {
return <h1>Slug: {params.slug}</h1>
}
10 changes: 10 additions & 0 deletions examples/with-jest/app/client/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @jest-environment jsdom
*/
import { render, screen } from '@testing-library/react'
import ClientComponent from './page'

it('App Router: Works with Client Components', () => {
render(<ClientComponent />)
expect(screen.getByRole('heading')).toHaveTextContent('Client Component')
})
5 changes: 5 additions & 0 deletions examples/with-jest/app/client/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client'

export default function ClientComponent() {
return <h1>Client Component</h1>
}
12 changes: 12 additions & 0 deletions examples/with-jest/app/component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* @jest-environment jsdom
*/
import { fireEvent, render, screen } from '@testing-library/react'
import Component from './component'

it('App Router: Works with Client Components (React State)', () => {
render(<Component />)
expect(screen.getByRole('heading')).toHaveTextContent('0')
fireEvent.click(screen.getByRole('button'))
expect(screen.getByRole('heading')).toHaveTextContent('1')
})
13 changes: 13 additions & 0 deletions examples/with-jest/app/component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useState } from 'react'

export default function Counter() {
const [count, setCount] = useState(0)
return (
<>
<h2>{count}</h2>
<button type="button" onClick={() => setCount(count + 1)}>
+
</button>
</>
)
}
11 changes: 11 additions & 0 deletions examples/with-jest/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
10 changes: 10 additions & 0 deletions examples/with-jest/app/rsc/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @jest-environment jsdom
*/
import { render, screen } from '@testing-library/react'
import Page from './page'

it('App Router: Works with Server Components', () => {
render(<Page />)
expect(screen.getByRole('heading')).toHaveTextContent('App Router')
})
9 changes: 9 additions & 0 deletions examples/with-jest/app/rsc/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'server-only'

export const metdata = {
title: 'App Router',
}

export default function Page() {
return <h1>App Router</h1>
}
6 changes: 1 addition & 5 deletions examples/with-jest/jest.setup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
// Optional: configure or set up a testing framework before each test.
// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`

// Used for __tests__/testing-library.js
// Learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect'
import '@testing-library/jest-dom'
15 changes: 8 additions & 7 deletions examples/with-jest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@
"dependencies": {
"next": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"server-only": "^0.0.1"
},
"devDependencies": {
"@testing-library/jest-dom": "5.16.4",
"@testing-library/jest-dom": "6.1.2",
"@testing-library/react": "14.0.0",
"@testing-library/user-event": "14.4.3",
"@types/react": "18.0.28",
"@types/testing-library__jest-dom": "5.14.5",
"jest": "29.5.0",
"jest-environment-jsdom": "29.5.0",
"typescript": "4.9.5"
"@types/react": "18.2.21",
"@types/testing-library__jest-dom": "6.0.0",
"jest": "29.6.4",
"jest-environment-jsdom": "29.6.4",
"typescript": "5.2.2"
}
}
12 changes: 10 additions & 2 deletions examples/with-vitest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

This example shows how to use [Vitest](https://github.com/vitest-dev/vitest) with Next.js.

## Deploy your own
This includes Next.js' built-in support for Global CSS, CSS Modules and TypeScript. This example also shows how to use Vitest with the App Router and React Server Components.

> **Note:** Since tests can be co-located alongside other files inside the App Router, we have placed those tests in `app/` to demonstrate this behavior (which is different than `pages/`). You can still place all tests in `__tests__` if you prefer.
Deploy the example using [Vercel](https://vercel.com/) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-vitest)
## Deploy your own

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-vitest&project-name=with-vitest&repository-name=with-vitest)

Expand All @@ -25,3 +27,9 @@ pnpm create next-app --example with-vitest with-vitest-app
```

Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

## Running Tests

```bash
npm test
```
2 changes: 1 addition & 1 deletion examples/with-vitest/__tests__/Home.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, test } from 'vitest'
import { render, screen, within } from '@testing-library/react'
import Home from '../pages'

test('home', () => {
test('Pages Router', () => {
render(<Home />)
const main = within(screen.getByRole('main'))
expect(
Expand Down
10 changes: 10 additions & 0 deletions examples/with-vitest/app/blog/[slug]/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect, test } from 'vitest'
import { render, screen } from '@testing-library/react'
import Page from './page'

test('App Router: Works with dynamic route segments', () => {
render(<Page params={{ slug: 'Test' }} />)
expect(
screen.getByRole('heading', { level: 1, name: 'Slug: Test' })
).toBeDefined()
})
13 changes: 13 additions & 0 deletions examples/with-vitest/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type Params = {
params: {
slug: string
}
}

export async function generateMetadata({ params }: Params) {
return { title: `Post: ${params.slug}` }
}

export default function Page({ params }: Params) {
return <h1>Slug: {params.slug}</h1>
}
10 changes: 10 additions & 0 deletions examples/with-vitest/app/client/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect, test } from 'vitest'
import { render, screen } from '@testing-library/react'
import ClientComponent from './page'

test('App Router: Works with Client Components', () => {
render(<ClientComponent />)
expect(
screen.getByRole('heading', { level: 1, name: 'Client Component' })
).toBeDefined()
})
5 changes: 5 additions & 0 deletions examples/with-vitest/app/client/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client'

export default function ClientComponent() {
return <h1>Client Component</h1>
}
10 changes: 10 additions & 0 deletions examples/with-vitest/app/component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect, test } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import Component from './component'

test('App Router: Works with Client Components (React State)', () => {
render(<Component />)
expect(screen.getByRole('heading', { level: 2, name: '0' })).toBeDefined()
fireEvent.click(screen.getByRole('button'))
expect(screen.getByRole('heading', { level: 2, name: '1' })).toBeDefined()
})
13 changes: 13 additions & 0 deletions examples/with-vitest/app/component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useState } from 'react'

export default function Counter() {
const [count, setCount] = useState(0)
return (
<>
<h2>{count}</h2>
<button type="button" onClick={() => setCount(count + 1)}>
+
</button>
</>
)
}
11 changes: 11 additions & 0 deletions examples/with-vitest/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
10 changes: 10 additions & 0 deletions examples/with-vitest/app/rsc/page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect, test } from 'vitest'
import { render, screen } from '@testing-library/react'
import Page from './page'

test('App Router: Works with Server Components', () => {
render(<Page />)
expect(
screen.getByRole('heading', { level: 1, name: 'App Router' })
).toBeDefined()
})
10 changes: 10 additions & 0 deletions examples/with-vitest/app/rsc/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// import 'server-only' does not currently
// work with Vitest

export const metdata = {
title: 'App Router',
}

export default function Page() {
return <h1>App Router</h1>
}
6 changes: 0 additions & 6 deletions examples/with-vitest/next.config.js

This file was deleted.

22 changes: 13 additions & 9 deletions examples/with-vitest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@
},
"dependencies": {
"next": "latest",
"react": "18.0.0",
"react-dom": "18.0.0"
"react": "^18.2.0",
"react-dom": "^18.2.0",
"server-only": "^0.0.1"
},
"devDependencies": {
"@testing-library/react": "^12.1.4",
"@types/node": "17.0.23",
"@types/react": "17.0.43",
"@vitejs/plugin-react": "1.3.0",
"jsdom": "^19.0.0",
"typescript": "4.6.3",
"vitest": "0.8.4"
"@testing-library/jest-dom": "6.1.2",
"@testing-library/react": "14.0.0",
"@testing-library/user-event": "14.4.3",
"@types/node": "20.5.9",
"@types/react": "18.2.21",
"@types/testing-library__jest-dom": "6.0.0",
"@vitejs/plugin-react": "4.0.4",
"jsdom": "^22.1.0",
"typescript": "5.2.2",
"vitest": "0.34.3"
}
}

0 comments on commit 7a256e6

Please sign in to comment.