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

Commit 10c0eb3

Browse files
committed
feat: XHR spying and stubbing working, close #5
1 parent 4476e05 commit 10c0eb3

File tree

5 files changed

+91
-2
lines changed

5 files changed

+91
-2
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
## Known problems
1212

1313
- [ ] some DOM events are not working when running all tests at once [#4](https://github.com/bahmutov/cypress-react-unit-test/issues/4)
14-
- [ ] cannot mock server XHR for injected components [#5](https://github.com/bahmutov/cypress-react-unit-test/issues/5)
14+
- [x] cannot mock server XHR for injected components [#5](https://github.com/bahmutov/cypress-react-unit-test/issues/5)
1515
- [ ] cannot spy on `window.alert` [#6](https://github.com/bahmutov/cypress-react-unit-test/issues/6)
1616

1717
## Install
@@ -115,6 +115,7 @@ All components are in [src](src) folder. All tests are in [cypress/integration](
115115
* [counter-spec.js](cypress/integration/counter-spec.js) clicks on the component and confirms the result
116116
* [stateless-spec.js](cypress/integration/stateless-spec.js) shows testing a stateless component from [stateless.jsx](src/stateless.jsx)
117117
* [transpiled-spec.js](cypress/integration/stateless-spec.js) shows testing a component with class properties syntax from [transpiled.jsx](src/stateless.jsx)
118+
* [users-spec.js](cypress/integration/users-spec.js) shows how to observe XHR requests, mock server responses for component [users.jsx](src/users.jsx)
118119

119120
## Large examples
120121

@@ -126,3 +127,4 @@ Same feature for unit testing components from other framesworks using Cypress
126127

127128
* [cypress-vue-unit-test](https://github.com/bahmutov/cypress-vue-unit-test) for Vue.js
128129
* [cypress-hyperapp-unit-test](https://github.com/bahmutov/cypress-hyperapp-unit-test) for Hyperapp
130+
* [cypress-svelte-unit-test](https://github.com/bahmutov/cypress-svelte-unit-test) for Svelte.js

cypress/integration/users-spec.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Users } from '../../src/users.jsx'
2+
import React from 'react'
3+
import { mount } from '../../lib'
4+
5+
/* eslint-env mocha */
6+
describe('Users', () => {
7+
beforeEach(() => {
8+
mount(<Users />)
9+
})
10+
11+
it('fetches 3 users from remote API', () => {
12+
cy.get('li').should('have.length', 3)
13+
})
14+
15+
it('can inspect real data in XHR', () => {
16+
cy.server()
17+
cy.route('/users?_limit=3').as('users')
18+
cy.wait('@users').its('response.body').should('have.length', 3)
19+
})
20+
21+
it('can display mock XHR response', () => {
22+
cy.server()
23+
const users = [{id: 1, name: 'foo'}]
24+
cy.route('GET', '/users?_limit=3', users).as('users')
25+
cy.get('li').should('have.length', 1)
26+
.first().contains('foo')
27+
})
28+
29+
it('can inspect mocked XHR', () => {
30+
cy.server()
31+
const users = [{id: 1, name: 'foo'}]
32+
cy.route('GET', '/users?_limit=3', users).as('users')
33+
cy.wait('@users').its('response.body').should('deep.equal', users)
34+
})
35+
36+
it('can delay and wait on XHR', () => {
37+
cy.server()
38+
const users = [{id: 1, name: 'foo'}]
39+
cy.route({
40+
method: 'GET',
41+
url: '/users?_limit=3',
42+
response: users,
43+
delay: 1000
44+
}).as('users')
45+
cy.get('li').should('have.length', 0)
46+
cy.wait('@users')
47+
cy.get('li').should('have.length', 1)
48+
})
49+
})

lib/index.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ const copyStyles = component => {
3535
})
3636
}
3737

38+
function setXMLHttpRequest (w) {
39+
// by grabbing the XMLHttpRequest from app's iframe
40+
// and putting it here - in the test iframe
41+
// we suddenly get spying and stubbing 😁
42+
window.XMLHttpRequest = w.XMLHttpRequest
43+
return w
44+
}
45+
3846
/* eslint-env mocha */
3947
export const mount = jsx => {
4048
// include React and ReactDOM from CDN to force DOM to register all DOM event listeners
@@ -51,7 +59,8 @@ export const mount = jsx => {
5159
document.write(html)
5260
document.close()
5361

54-
cy.window({ log: false})
62+
cy.window({log: false})
63+
.then(setXMLHttpRequest)
5564
.its('ReactDOM.render')
5665
.then(render => {
5766
Cypress._component = render(jsx, document.getElementById('app'))

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"devDependencies": {
3030
"@cypress/webpack-preprocessor": "^1.1.2",
3131
"@types/node": "^8.5.2",
32+
"axios": "^0.17.1",
3233
"babel-core": "^6.26.0",
3334
"babel-loader": "^7.1.2",
3435
"babel-plugin-transform-class-properties": "^6.24.1",

src/users.jsx

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react'
2+
import axios from 'axios'
3+
4+
export class Users extends React.Component {
5+
constructor (props) {
6+
super(props)
7+
this.state = {
8+
users: []
9+
}
10+
}
11+
12+
componentDidMount () {
13+
axios.get('http://jsonplaceholder.typicode.com/users?_limit=3')
14+
.then(response => {
15+
// JSON responses are automatically parsed.
16+
this.setState({
17+
users: response.data
18+
})
19+
})
20+
}
21+
22+
render () {
23+
return <div>
24+
{this.state.users.map(user =>
25+
<li key={user.id}><strong>{user.id}</strong> - {user.name}</li>)}
26+
</div>
27+
}
28+
}

0 commit comments

Comments
 (0)