At this point we have a test in our product test file that tests the out of stock functionality. We should also have a couple of tests in our footer file. Now it's time to add some more product tests.
Each Product component has an "Add to cart" button that adds the product to the cart and changes the text of the button. Adding the product to the cart belongs, for the most part, to the cart module in Vuex and the data is rendered in the nav bar (i.e 'Cart (1)'). For that reason, for now, we'll simply test whether the button state changes and that that functionality works as intended for our users.
In order to do this we need to add a mechanism that adds one or more of the products to the cart. Now, this sounds like a useful piece of functionality that we would want to reuse and fortunately in Cypress, we can leverage the commands file (cypress/support/commands.js) to add a command.
In your commands file, add:
// cypress/support/commands.js
Cypress.Commands.add('addProductsToCart', () => {
cy.get('[data-cy=product--addToCart]').each(($el, index) => {
$el.click();
});
});
You'll be familiar with cy.get
at this point. Notice that we get the product--addToCart
elements. This means we need to add an attribute to each button as follows:
<!-- Product component -->
<button
v-on:click="addToCart(product)"
v-if="product.stockLevel > 0"
data-cy="product--addToCart"
>
{{ product.addedToCart ? "Remove from cart" : "Add to cart" }}
</button>
Prefixing with product--
is just a useful way to say that the addToCart
element belongs to the product component. This helps us keep track of our attributes.
Moving on, you'll notice that we then call the each
function on each button element and we call click()
on each one. We can not reuse this command whenever we needed to.
We can now call our command in our test:
it('should change the button text when clicked', () => {
cy.addProductsToCart();
});
To test all of the buttons, we can grab all of the elements, loop through them and then test if they contain the string 'Remove from cart'.
This is the full code:
// product.spec.js
it('should change the button text when clicked', () => {
cy.addProductsToCart();
cy.get('[data-cy=product--addToCart]').each(($el, index) => {
expect($el).to.contain('Remove from cart');
});
});
If you run your tests now, you should find that the tests pass.
At this point, we could in theory check that the cart in the navbar has the full compliment of products added, but instead, we'll let the component where that belongs take care of that (see the coding challenge below).
The first part of this coding challenge is to add a navbar.spec.js
file and test the cart output. Don't forget you can reuse the addProductsToCart
command you created before to add the products to the cart.
When testing, try and maintain an awareness of whether the tests you are creating are "flaky" or not. Would this consistently pass if the data changed? We don't need to change them if they are at this stage, but just have an awareness.
You'll notice the the active link, also in the navbar, has a router-link-exact-active
class added by Vue Router. Write a test to verify this class gets added to the home page and at least one other page after clicking the link.
Hint: in Cypress, get the element as normal, then call the click()
function on it to visit the link.
You may have noticed we have no product details tests. The last part of this challenge is to add test coverage for these pages. Before you start, consider what you will test first and how you might test those elements.