Skip to content
This repository was archived by the owner on Mar 5, 2022. It is now read-only.

Commit bf94dea

Browse files
feat: Nextjs support plugin (#422)
- closes #155 Co-authored-by: Gleb Bahmutov <gleb.bahmutov@gmail.com>
1 parent 54857cd commit bf94dea

File tree

23 files changed

+5835
-2161
lines changed

23 files changed

+5835
-2161
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ package-lock.json
88
.nyc_output
99
coverage
1010
*.generated.css
11+
.next

circle.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,26 @@ workflows:
8585
npm run only-covered
8686
working_directory: examples/react-scripts
8787

88+
- cypress/run:
89+
name: Example Next.js
90+
requires:
91+
- Install
92+
executor: cypress/base-12
93+
# each example installs "cypress-react-unit-test" as a local dependency (symlink)
94+
install-command: npm install
95+
verify-command: echo 'Already verified'
96+
no-workspace: true
97+
working_directory: examples/nextjs
98+
command: npm test
99+
store_artifacts: true
100+
post-steps:
101+
- run:
102+
name: Check coverage 📈
103+
command: |
104+
npm run check-coverage
105+
npm run only-covered
106+
working_directory: examples/nextjs
107+
88108
- cypress/run:
89109
# react-scripts example with component tests not in "src" folder
90110
# but in "cypress/component" folder

cypress/component/advanced/framer-motion/Motion.spec.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ describe('framer-motion', () => {
1010
cy.get("[data-testid='motion']").should('have.css', 'border-radius', '20%')
1111
})
1212

13-
it('Mocks setTimeout and requestAnimationFrame', () => {
13+
// looks like cy.tick issue. Refer to the https://github.com/bahmutov/cypress-react-unit-test/issues/420
14+
it.skip('Mocks setTimeout and requestAnimationFrame', () => {
1415
cy.clock()
1516
mount(<Motion />)
1617

examples/nextjs/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

examples/nextjs/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# example: Next.js
2+
3+
> A typical project using [next.js](https://nextjs.org/)
4+
5+
## Configuration
6+
7+
In order to reuse next's webpack configuration and all the custom configuration defined in `next.config.js` connect special plugin in [plugin file](./cypress/plugins/index.js)
8+
9+
```js
10+
const preprocessor = require('cypress-react-unit-test/plugins/next')
11+
12+
module.exports = (on, config) => {
13+
preprocessor(on, config)
14+
15+
return config
16+
}
17+
```
18+
19+
## Usage
20+
21+
1. Run `npm install` in this folder to install dependencies.
22+
23+
```bash
24+
# in this folder
25+
npm install
26+
```
27+
28+
3. Start Cypress
29+
30+
```bash
31+
npm run cy:open
32+
# or just run headless tests
33+
npm test
34+
```
35+
36+
## Server side props
37+
38+
⚠️⚠️ **Important:** ⚠️⚠️ Please do not test the page components using component testing. These components have too much responsibility and need to be tested as a part of your application flow. Consider using cypress `integration` tests.
39+
40+
But if you still want to test the page component, make sure that it will be mounted as any other pure `React` component. It means that next's specific functions like `getInitialProps` or `getStaticProps` **won't be called**.
41+
42+
But still you can call them manually:
43+
44+
```js
45+
IndexPage.getInitialProps().then(props => {
46+
mount(<IndexPage {...props} />)
47+
})
48+
49+
cy.contains(
50+
'`.getInitialProps()` was called and passed props to this component',
51+
)
52+
```
53+
54+
Find more examples in [Page.spec.jsx](./cypress/components/Page.spec.jsx).
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Hello, *world*!
2+
3+
Below is an example of JSX embedded in Markdown. <br /> **Try and change
4+
the background color!**
5+
6+
<div style={{ padding: '20px', backgroundColor: 'tomato' }}>
7+
<h3>This is JSX</h3>
8+
</div>

examples/nextjs/components/Search.jsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import * as React from 'react'
2+
3+
export function Search() {
4+
const [value, setValue] = React.useState('')
5+
return (
6+
<div>
7+
<input
8+
aria-label="search"
9+
value={value}
10+
onChange={e => setValue(e.currentTarget.value)}
11+
/>
12+
13+
<p className="search-text">You are searching for: {value}</p>
14+
15+
<style jsx>{`
16+
input {
17+
border-radius: 20px;
18+
}
19+
div {
20+
padding: 16px;
21+
background: tomato;
22+
}
23+
`}</style>
24+
</div>
25+
)
26+
}

examples/nextjs/cypress.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"testFiles": "**/*.spec.{js,jsx}",
3+
"viewportWidth": 500,
4+
"viewportHeight": 800,
5+
"experimentalComponentTesting": true,
6+
"experimentalFetchPolyfill": true,
7+
"componentFolder": "cypress/components"
8+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/// <reference types="cypress" />
2+
import * as React from 'react'
3+
import IndexPage from '../../pages/index'
4+
import { mount } from 'cypress-react-unit-test'
5+
6+
describe('NextJS page', () => {
7+
it('Renders page component', () => {
8+
mount(<IndexPage />)
9+
10+
cy.contains('Welcome to Next.js')
11+
})
12+
13+
it("It doesn't run the `.getInitialProps()`", () => {
14+
mount(<IndexPage />)
15+
16+
cy.get('[data-testid="server-result"').should(
17+
'not.contain',
18+
'`.getInitialProps()` was called and passed props to this component',
19+
)
20+
})
21+
22+
it('Allows to manually mock the server side props', () => {
23+
mount(<IndexPage asyncProp />)
24+
25+
cy.contains(
26+
'`.getInitialProps()` was called and passed props to this component',
27+
)
28+
})
29+
30+
it('can be tested with real .getInitialProps call', () => {
31+
IndexPage.getInitialProps().then(props => {
32+
mount(<IndexPage {...props} />)
33+
})
34+
35+
cy.contains(
36+
'`.getInitialProps()` was called and passed props to this component',
37+
)
38+
})
39+
})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// <reference types="cypress" />
2+
import * as React from 'react'
3+
import { mount } from 'cypress-react-unit-test'
4+
import { Search } from '../../components/Search'
5+
import HelloWorld from '../../components/HelloWorld.mdx'
6+
7+
describe('<Search /> NextJS component', () => {
8+
it('Renders component', () => {
9+
mount(<Search />)
10+
11+
cy.get('input').type('124152')
12+
cy.contains('.search-text', '124152').should('be.visible')
13+
})
14+
15+
it('Renders mdx component using custom next.config.js', () => {
16+
mount(<HelloWorld />)
17+
18+
cy.contains('Hello').should('have.css', 'fontWeight', '700')
19+
cy.contains('This is JSX')
20+
.parent()
21+
.should('have.css', 'background-color', 'rgb(255, 99, 71)')
22+
})
23+
})

0 commit comments

Comments
 (0)