Component Tests with Vue.js

Goals of Testing

~ Part 1 ~

Confidence/Removal of Fear to Change Code

Code Quality

“Test a single concept in each test function”

- Uncle Bob (Clean Code)

Code Quality

  • Single Responsibility Principle
  • Modular code
  • What is my component really doing?
it ('should display a formatted username', () => {});
it ('should display a formatted username with a custom 
    avatar', () => {});
it ('should display a formatted username in green with 
    a custom avatar if the user is logged in, otherwise
    it should display a generic avatar and display the 
    username in red', () => {});

Documentation

describe('AddButton.vue', () => {
  describe(':props', () => {
    it(':label - should render a button with the passed-in label text', () => {
    })
  });

  describe('@events', () => {
    it('@add - should emit an "add" event when the button is clicked', () => {
    })
  });
})

Confidence to Change / Removal of Fear +

**Developer Happiness**

High Code Quality +

Well-Documented Code =

Vue Component Testing

~ Part 2 ~

Component Contract

"A contract defines the expected behavior of your component and what assumptions are reasonable to have about its usage."

Props

Events

User Interaction

Rendered Output

MyComponent

Lifecycle

Methods

Test the Public Interface!

Connection with

Children

Some Examples

If there's logic in the template we should test it

Avoriaz

Props

Rendered Output

UserSettingsBar

Testing template logic

What's outside the scope of our component tests?

Implementation Details

SquareButton.spec.js

 

Events

User Interaction

SquareButton

Testing the framework itself

<p>{{myProp}}</p>

expect(p.text()).to.be(/* some prop  value */)

Prop validation

1

2

Vue

Us

 ✨ Trust the framework ✨

Integration

Shallow

Test the component with the idea that sub components (and their subcomponents) are all part of it's "component contract"

Subcomponents more than one level down are not part of the component contract.

Integration

Counter.vue

CounterDisplay.vue

Button.vue

"increment" event

"count" prop

TEST

Find button element, trigger click

Find display element, assert render

Counter.spec.js

User Interaction

Rendered Output

Counter

Counter Integration Tests

Shallow

Counter.vue

CounterDisplay.vue

Button.vue

"increment" event

"count" prop

TEST

TEST

We don't care how this will be rendered

We don't care how this was triggered

Props

Counter

Counter

Display

Button

Props

Events

Counter Shallow Tests

Integration

Shallow

Maintainability

Coverage

Modularity

High

High

High

Medium/Low

Low

Medium

Tradeoffs

Want to learn more?

Avoriaz -> vue-test-utils

Snapshot Testing / Jest

E2E tests: Webdriver IO / Nightwatch

Testing Vuex

Thanks!

github: @matt-oconnell

deck

By mattoconnell