Simple things are often overlooked. When it comes to unit testing, a lot of teams just get involved in the interface area, and the UI layer is the most overlooked. Today I’m going to write unit tests at the UI level around a simple demo. This article is only for those who have not been exposed to unit testing at the UI level and want to get started quickly. Just move your mouse to the upper right corner and click X.

👓 front-end unit testing (what? why?)

  • Simulate user actions to detect problems before users.

What do 👇 need to know in advance? Prepare for what?

  • Libraries such as Char, Mocha, and Jest are easy to look at
  • If you want to get up to speed just follow me through the code
  • In the next test, Vuecli has provided the @vue/test-utils library
  • Due to personal habit, I have installed the chai assertion library separately (ts project needs to install @types/chai separately)

👏 Take a look at the demo I’m going to test

Very simple, but “pretty much covers” general UI level testing, considering what would fall within our testing range?

  • Click “Open the nested form Dialog” button to see if the popup window can pop up
  • Does the input value match the type we want (normally it is checked after clicking ok)
  • Click ok and cancel to close the popover

😾 take a look at the test details through the code

  1. Components that need to be tested
// The component to test<template>
  <div class="about">
    <el-button type="text" @click="dialogFormVisible = true">Opens the Dialog for the nested form</el-button>
    <el-dialog title="Shipping address" :visible.sync="dialogFormVisible">
      <el-form :model="form">
        <el-form-item label="Name" :label-width="formLabelWidth">
          <el-input v-model="form.name" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="Age" :label-width="formLabelWidth">
          <el-input v-model="form.age" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">Take away</el-button>
        <el-button type="primary" @click="dialogFormVisible = false">determine</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
@Component
export default class About extends Vue {
  private dialogFormVisible = false;
  private form = {
    name: ' '.age: 20}; private formLabelWidth ='120px';
}
</script>
Copy the code
  1. Let’s take a look at the specific code of the test case. The specific explanation is reflected in the code
import {mount, config, createLocalVue } from '@vue/test-utils';
import About from '@/views/About.vue';
import Vue from 'vue'
import ElementUI from 'element-ui'
import { expect } from 'chai'

// Introduce elementui without injecting anything into the global Vue constructor. We can archive them using the createLocalVue method:
constlocalVue = createLocalVue() localVue.use(ElementUI) config.stubs! .transition =false

describe('about.vue'.() = > {
  // Since the same container will be used in the next few tests, you only need to mount vue once
  const wrapper = mount(About, {
    localVue
  })
  // By default we will use async, await mode
  it('dialog pop'.async() = > {const dialog = wrapper.find('.el-dialog__wrapper') // Get the popover
    const openBtn = wrapper.findAll('.el-button').at(0) // Get the popup button

    expect(dialog.attributes().style).contain('display') // This step can be omitted because it is an internal component of elementUI that has features
    expect(wrapper.vm.$data.dialogFormVisible).to.be.eq(false) // The initial value of the control popover variable is false
    await openBtn.trigger('click') // Triggers the button click event
    expect(dialog.attributes().style).to.not.contain('display') // as above can be omitted
    expect(wrapper.vm.$data.dialogFormVisible).to.be.eq(true) // Controls whether the popover variable becomes true
  });

  // Check the value
  it('check value'.async() = > {const openBtn = wrapper.findAll('.el-button').at(0)
    await openBtn.trigger('click')

	// Simulate input values
    await wrapper.setData({
          form: {
            name: 'xiaomin'.age: 30
          }
        })
    expect(typeof(wrapper.vm.$data.form.name)).to.be.eq('string') // Check whether the input value is successfully entered and whether it is the preset type
    expect(typeof(wrapper.vm.$data.form.age)).to.be.eq('number') // wrapper.vm.$data to get all the variables
  })

  // Check whether the popover can close properly
  it('dialog close'.async() = > {const openBtn = wrapper.findAll('.el-button').at(0)
    await openBtn.trigger('click')

    expect(wrapper.vm.$data.dialogFormVisible).to.be.eq(true)

    const closeBtn = wrapper.findAll('.el-button').at(1) // According to the DOM position, get the cancel button and trigger
    await closeBtn.trigger('click')
    expect(wrapper.vm.$data.dialogFormVisible).to.be.eq(false)})});Copy the code
  1. Let’s look at the DOM of the Wrapper in the code above for a better understanding.

console.log(wrapper.html())

  1. Now run this test (NPM Run Test :unit)

  1. Two holes!

Can’t find stylesheet to import

  • A relative path can be changed to an absolute path

TypeError: Cannot read property ‘$el’ of undefined”

  • This is caused by the synchronous Transition stub component added by default to Vue Test Utils. You can turn it off using the stub optionconfig.stubs! .transition = false

😼 summary

  • Writing unit tests, whether front-end or back-end, is also a check on your code, so it is highly recommended to pay attention to unit tests
  • This article is only the code of personal views, if there are inappropriate places to write, welcome criticism.