Adding more test coverage

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.

Learning Objectives

Product testing prep

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();
});

Testing the Add to cart button

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).

Assignment - Coding challenge

Part 1

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.

Part 2

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.

Part 3

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.