🎁 You can find the pull request with the tests from this blog post in the branch implement-toggle-video of the repo bahmutov/cypress-workshop-basics. The code can be seen in the pull request #75.
The step by step tests and the application changes described in this blog post are shown in my new video below
The application
In the workshop repository, I have a simple TodoMVC with the items stored by the backend server. Unfortunately, the application does not implement storing the "completed" item property. The user interface shows the item as completed, but when reloading the page, the completed status disappears.
The testing plan
Let's implement this feature. While working on the feature I will follow the test-drive development practice. I will first write a failing Cypress test, then implement the application code to make the test green. To start testing, I first will plan my "attack" by looking at the application architecture. The application has the web page interface, which shows the data in the Veux data store. The data store is synced with the backend via REST API calls. My first test will verify the REST API is working correctly. Then I will test how the web application passes the "completed" property to the Veux data store. Finally, I will test the web page UI and confirm it calls the backend API by using the cy.intercept command.
The API test
We first confirm that our backend supports changing the todo's "completed" property and correctly updates the database. We can write a Cypress API test. Cypress can be quite happily calling the HTTP endpoints and verifying the results, as the video below shows:
Let's write our test:
1 | it('completes an item using API', () => { |
The above test uses the cy.request command to make HTTP calls. We first create an item using the POST /todos <item>
call. Then we verify the todos by asking the server using GET /todos
. We then use the REST convention to PATCH /todos/:id <changed properties>
. Finally, we verify the server has saved the changed "completed" property by request the Todo item and confirmed its properties.
1 | cy.request('GET', `/todos/${id}`) |
Tip: while running an API test, the application is not visited, leaving the entire iframe empty. You can use it to display the requests and responses by using the cy-api plugin.
The UI to Vuex data store test
The REST part was easy - our server already supports updating an object using the PATCH
method. Can our application call these methods? Let's write a test to first confirm that the UI updates the internal data store. To access the internal Vuex data store, we can expose it to the test by setting it as a window
property.
1 | // our application instance |
Then from the test we can check the data store using the cy.window and cy.its commands.
1 | cy.window() |
The entire test
1 | it('updates the Vuex store', () => { |
Tip: notice that the above test has a combination of API calls (to reset all existing todos and to create the first todo) and page commands (to verify the list of todos). I like using REST API calls to set the data really quickly.
Super, our application UI does update the data store. But does the store update the backend? Let's make the test fail.
Observe the network test
Let's spy on the network traffic to confirm if the Vuex data store calls the backend with PATCH
method.
1 | it('toggles an item', () => { |
Ok, our Vuex data store that syncs the data with the backend never calls the backend to update the Todo item when we click the "toggle" checkbox. Let's implement it in the app.js
1 | // add toggleTodo to Vuex actions |
The test turns green.
We can even confirm that clicking the item again sends the 2nd call to clear the property
1 | it('toggles an item', () => { |
The final test
Let's put the final test together that reloads the page and checks the completed property is still there.
1 | it('stays completed', () => { |
Happy Testing!