-
Notifications
You must be signed in to change notification settings - Fork 35
Description
Hey all!
Why?
Because this is a very big issue for cypress developers...
When using cypress fixtures you are required to write out static JSON files in order to have mocked out responses.
I think this could be a huge selling point for mirage because you could swap using these static very limited in power JSON files to use the full power of a browser database with really minimal work.
How
So generally in order to mock out an HTTP request with cypress you would do something like this:
// createUser.json
{
"id": 1,
"firstName": "John",
"lstName": "Doe"
}
// create-user.spec.js
it('Should create a new user', () => {
// Lets assume we have an endpoint for creating a user
// And we stub it out by telling cypress to use a fixture called createUser.json
cy.server()
cy.route({
method: 'POST',
url: '/users',
response: 'fixture:createUser.json'
}).as('createUser')
// We define the values we want to enter into the inputs
const FIRST_NAME = 'John'
const LAST_NAME = 'Doe'
// We find the form on the page, type in our predefined values and submit the form
cy.get('form')
.within(() => {
cy.get('input[name="first_name"]').type(FIRST_NAME)
cy.get('input[name="last_name"]').type(FIRST_NAME)
})
.submit()
// We wait our app to send the request we stubbed out
cy.wait('@createUser').then(({ response, request }) => {
// and assert that the values that where sent to the server are the ones we typed in
expect(request.body.firstName).to.equal(FIRST_NAME)
expect(request.body.lastName).to.equal(LAST_NAME)
// We want to make sure we are redirected to the correct url using the id that was created for the user
cy.location().should(loc => {
expect(loc.pathname).to.eq(`/users/${response.body.id}`)
})
// We want to make sure that the form is populated with the values that were returned from our api
cy.get('form').within(() => {
cy.get('input[name="first_name"]').should('have.value', FIRST_NAME)
cy.get('input[name="last_name"]').should('have.value', LAST_NAME)
})
})
})The problem here is that if we ever change John Doe to be Jane Doe, this test would fail because the fixture JSON file doesn't change.
Luckily, not much is required to change this test to use mirage instead:
// server.js
import { Server } from 'miragejs'
new Server({
routes() {
this.post('/users', (schema, request) => {
const user = JSON.parse(request.requestBody)
return schema.users.create(user)
})
}
})
// create-user.spec.js
import { makeServer } from "../../src/server"
let server
beforeEach(() => {
server = makeServer({ environment: "test" })
})
afterEach(() => {
server.shutdown()
})
it('Should create a new user', () => {
// Lets assume we have an endpoint for creating a user
// And we stub it out by telling cypress to use a fixture called createUser.json
cy.server()
cy.route({
method: 'POST',
url: '/users'
// Remove 👇👇👇 this line to tell cypress to let the request through
// response: 'fixture:createUser.json'
// Now we can change the user's name to anything and the test will still pass
}).as('createUser')
// We define the values we want to enter into the inputs
const FIRST_NAME = 'John'
const LAST_NAME = 'Doe'
// We find the form on the page, type in our predefined values and submit the form
cy.get('form')
.within(() => {
cy.get('input[name="first_name"]').type(FIRST_NAME)
cy.get('input[name="last_name"]').type(FIRST_NAME)
})
.submit()
// We wait our app to send the request we stubbed out
cy.wait('@createUser').then(({ response, request }) => {
// and assert that the values that where sent to the server are the ones we typed in
expect(request.body.firstName).to.equal(FIRST_NAME)
expect(request.body.lastName).to.equal(LAST_NAME)
// We want to make sure we are redirected to the correct url using the id that was created for the user
cy.location().should(loc => {
expect(loc.pathname).to.eq(`/users/${response.body.id}`)
})
// We want to make sure that the form is populated with the values that were returned from our api
cy.get('form').within(() => {
cy.get('input[name="first_name"]').should('have.value', FIRST_NAME)
cy.get('input[name="last_name"]').should('have.value', LAST_NAME)
})
})
}) So basiclly all we had to do to make the transition to mirage is define the route handler (which you need to do regradless) and remove one line from our test file.