ElementUI table not rendering in a Jest test

Viewed 823

I have noticed that some of my components that use ElementUI tables are failing their tests, with Jest and Vue-test-utils. Looking into it some more, when I reproduce a simple example and use console.log(wrapper.html) some of the inner parts of the table are simply not being rendered.

I am by no means a frontend expert (more of a Python backend person), and working on this to help another team out and so I am not 100% convinced that I'm not doing something stupid, but I have explored a range of possibilities and I can't figure it out. What's more, the tests are not working, but the component itself works absolutely fine within the application - the table is rendered properly. So it's frustrating because it appears to work, but the test suite disagrees....

This is not the actual code, but it's a trimmed down example to reproduce the issue.

BasicTable.vue

<template>
  <div>
    <el-table
      :data="tdata"
    >
      <el-table-column #default="{ row }">
        {{ row.item }}
      </el-table-column>
      <el-table-column #default="{ row }">
        {{ row.size }}
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: 'BasicTable',
  data () {
    return {
      tdata: [{ item: 'A', size: 'L' },
        { item: 'B', size: 'M' },
        { item: 'C', size: 'XS' },
        { item: 'D', size: 'XXL' },
      ],
    }
  },

}
</script>

BasicTable.spec.js

import BasicTable from './BasicTable.vue'
import ElementUI from 'element-ui'
import { mount, createLocalVue } from '@vue/test-utils'


test('Render for basic table', () => {
  const localVue = createLocalVue()
  localVue.use(ElementUI)

  const wrapper = mount(BasicTable, {
     localVue
  }
  console.log(wrapper.html())
})

So I would expect the output of the wrapper.html() to just render the table, with the four rows, and two columns, as would be expected from the data.

However, what I actually get is

 <div>
      <div class="el-table el-table--fit el-table--enable-row-hover el-table--enable-row-transition">
        <div class="hidden-columns">
          <div></div>
          <div></div>
        </div>
        <div class="el-table__header-wrapper">
          <table cellspacing="0" cellpadding="0" border="0" class="el-table__header">
            <colgroup></colgroup>
            <thead class="">
              <tr class=""></tr>
            </thead>
          </table>
        </div>
        <div class="el-table__body-wrapper is-scrolling-none">
          <table cellspacing="0" cellpadding="0" border="0" class="el-table__body">
            <colgroup></colgroup>
            <tbody>
              <tr class="el-table__row"></tr>
              <tr class="el-table__row"></tr>
              <tr class="el-table__row"></tr>
              <tr class="el-table__row"></tr>
              <!---->
            </tbody>
          </table>
          <!---->
          <!---->
        </div>
        <!---->
        <!---->
        <!---->
        <!---->
        <div class="el-table__column-resize-proxy" style="display: none;"></div>
      </div>
    </div>

So between the <tbody></tbody> tags, the correct number of rows are present (4) but then they seem to have no internal content.

A few things I initially considered but discounted as the issue:

  • I made sure I was mounting and not shallowMounting
  • using LocalVue and using ElementUI does appear to be working, the ElementUI components are being rendered as basic html, with the relevant classes added (e.g. <table class="el-table">)
  • Some of the actual components use a computed() to calculate the data that goes into the table, or have it passed via a prop. I thought this might be causing some issue, but I set up this basic example with the most simple case I could think of (i.e just hardcoded data in the component) and i still see the same result.

I have struggled to find much specific ElementUI/Jest/Vue-test-utils help online, so any suggestions would be greatly appreciated! And if I have done something stupid, please let me know because as I said this is not my main area of expertise.

Versions of stuff I am using (from package.json)

 "dependencies": {
    "element-ui": "^2.4.5",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "core-js": "^3.6.5",
    "@vue/cli-service": "~4.5.0"
  },

Note: The project is setup with Vue-cli and I believe Jest is bundled with that.

"@vue/cli-plugin-unit-jest": "~4.5.0",

I run the tests with npm run test:unit

1 Answers

I seem to have found an answer, so will post it here if anyone else stumbles across this.

The solution appears to be waiting for nextTick() for the DOM elements to properly render. I'll be honest, I am not 100% sure why this is the reason - I might expect this if the data was changing during the test (and I had used that approach for other tests when updating props or triggering a click for example) but in this case the data is passed in while mounting... If you come across this answer and have a more concrete explanation, please feel free to add it here!

So for completeness, something like

test('Render for basic table', async () => {
  const localVue = createLocalVue()
  localVue.use(ElementUI)

  const wrapper = mount(BasicTable, {
     localVue
  }
  await wrapper.vm.$nextTick()    <-- added this line (also made the test async)
  console.log(wrapper.html())
})

Appears to solve my problem!

Related