Skip to content

Commit

Permalink
test(lib): update Table spec
Browse files Browse the repository at this point in the history
- Updates the unit tests (spec) of `Table` so that they work with Vue 3
  and `@vue/test-utils` V2:
    - Removes `setVueInstance` because it does nothing on `buefy-next`.
    - Replaces `sinon`'s `useFakeTimers` with a combination of
      `jest.useFakeTimers` and `jest.advanceTimersByTime` so that we
      will be able to remove `sinon` from dependencies in the future.
      Awaits `$nextTick` after `jest.advanceTimersByTime` to make sure
      DOM is updated, otherwise the test fails.
    - Replaces `wrapper.find` with `wrapper.findComponent` to locate a
      component, because `wrapper.find` is dedicated to finding a DOM
      element on `@vue/test-utils` V2.
    - Replaces `isEmpty` of `Wrapper` with a combination of `element`
      and `toBeEmptyDOMElement`, because `Wrapper` no longer provides
      `isEmpty` on `@vue/test-utils` V2.
    - Replaces `contains` of `Wrapper` with a combination of `find` and
      `exists`, because `Wrapper` no longer provides `contains` on
      `@vue/test-utils` V2.
    - Replaces `wrapper.name()` with `wrapper.vm.$options.name`, because
      `wrapper.name` no longer exists in `@vue/test-utils` V2.
    - Replaces the test on `wrapper.isVueInstance()` with presence of
      `wrapper.vm`, because `wrapper.isVueInstance` no longer exists in
      `@vue/test-utils` V2.
    - Awaits `wrapper.setProps` to make sure the subsequent tests verify
      the updated state.
    - Replaces `propsData` with `props`, because `propsData` might be
      deprecated in the future.
    - Refreshes the snapshot. I temporarily fixed the bug I found while
      updating the spec (ntohq#8) to make the snapshot.
    - NOTE: the tests won't pass until the bug is fixed:
        - ntohq#8

issue ntohq#1
  • Loading branch information
kikuomax committed Sep 1, 2023
1 parent 324bd50 commit f0db147
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 62 deletions.
95 changes: 49 additions & 46 deletions src/components/table/Table.spec.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import Vue from 'vue'
import '@testing-library/jest-dom'
import { shallowMount } from '@vue/test-utils'
import { useFakeTimers } from 'sinon'
import BInput from '@components/input/Input'
import BTable from '@components/table/Table'
import { setVueInstance } from '../../utils/config'

describe('BTable', () => {
setVueInstance(Vue)

let wrapper
beforeEach(() => {
wrapper = shallowMount(BTable)
})

let tableCols = shallowMount(BTable, {
propsData: {
const tableCols = shallowMount(BTable, {
props: {
columns: [
{ label: 'default', width: '100px' },
{ label: 'pecent', width: '50%' },
Expand All @@ -25,15 +21,15 @@ describe('BTable', () => {
})

it('is called', () => {
expect(wrapper.name()).toBe('BTable')
expect(wrapper.isVueInstance()).toBeTruthy()
expect(wrapper.vm).toBeTruthy()
expect(wrapper.vm.$options.name).toBe('BTable')

expect(tableCols.name()).toBe('BTable')
expect(tableCols.isVueInstance()).toBeTruthy()
expect(tableCols.vm).toBeTruthy()
expect(tableCols.vm.$options.name).toBe('BTable')
})

it('has the filter row visible when searchable', () => {
wrapper.setProps({
it('has the filter row visible when searchable', async () => {
await wrapper.setProps({
columns: [
{
field: 'id',
Expand All @@ -46,7 +42,7 @@ describe('BTable', () => {
// Don't show if no searchable column
expect(wrapper.vm.hasSearchablenewColumns).toBe(false)
// Show if one or more searchable column
wrapper.setProps({
await wrapper.setProps({
columns: [
{
field: 'id',
Expand All @@ -65,12 +61,12 @@ describe('BTable', () => {
})

it('holds columns', () => {
let headers = tableCols.findAll('th')
const headers = tableCols.findAll('th')

expect(headers.length).toBeGreaterThanOrEqual(4)

let cols = headers.filter((th) => {
let div = th.find('div')
const cols = headers.filter((th) => {
const div = th.find('div')

return div.classes('th-wrap')
})
Expand All @@ -92,7 +88,7 @@ describe('BTable', () => {
]
beforeEach(() => {
wrapper = shallowMount(BTable, {
propsData: {
props: {
columns: [
{ label: 'ID', field: 'id' },
{ label: 'Name', field: 'name' }
Expand All @@ -106,39 +102,39 @@ describe('BTable', () => {
expect(wrapper.findAll('tbody tr.is-selected')).toHaveLength(0)
})

it('unselected( column-row-key )', () => {
wrapper.setProps({
it('unselected( column-row-key )', async () => {
await wrapper.setProps({
customRowKey: 'id'
})
expect(wrapper.findAll('tbody tr.is-selected')).toHaveLength(0)
})

it('compare by instance itself', () => {
wrapper.setProps({
it('compare by instance itself', async () => {
await wrapper.setProps({
selected: data[0]
})
const rows = wrapper.findAll('tbody tr')
expect(rows.at(0).classes()).toContain('is-selected')
})

it('target data and key match', () => {
wrapper.setProps({
it('target data and key match', async () => {
await wrapper.setProps({
selected: data[1],
customRowKey: 'id'
})
const rows = wrapper.findAll('tbody tr')
expect(rows.at(1).classes()).toContain('is-selected')
})

it('clear data', () => {
wrapper.setProps({
it('clear data', async () => {
await wrapper.setProps({
selected: data[0],
customRowKey: 'id'
})
const rows = wrapper.findAll('tbody tr')
expect(rows.at(0).classes()).toContain('is-selected')

wrapper.setProps({
await wrapper.setProps({
selected: undefined
})
expect(wrapper.findAll('tbody tr.is-selected')).toHaveLength(0)
Expand All @@ -159,7 +155,7 @@ describe('BTable', () => {

beforeEach(() => {
wrapper = shallowMount(BTable, {
propsData: {
props: {
columns: [
{ label: 'ID', field: 'id', numeric: true },
{ label: 'Name', field: 'name', searchable: true }
Expand All @@ -169,7 +165,7 @@ describe('BTable', () => {
})
headRows = wrapper.findAll('thead tr')
bodyRows = wrapper.findAll('tbody tr')
searchInput = wrapper.find(BInput)
searchInput = wrapper.findComponent(BInput)
})

it('displays filter row when at least one column is searchable', () => {
Expand All @@ -179,38 +175,43 @@ describe('BTable', () => {
it('displays filter input only on searchable columns', () => {
const filterCells = headRows.at(1).findAll('.th-wrap')

expect(filterCells.at(0).isEmpty()).toBe(true) // ID column is not searchable
expect(filterCells.at(1).contains(BInput)).toBe(true) // Name column is searchable
expect(filterCells.at(0).element).toBeEmptyDOMElement() // ID column is not searchable
expect(
filterCells.at(1).findComponent(BInput).exists()
).toBe(true) // Name column is searchable
})

it('displays all data', () => {
expect(bodyRows).toHaveLength(5)
})

it('displays filtered data when searching', () => {
searchInput.vm.$emit('input', 'J')
it('displays filtered data when searching', async () => {
searchInput.vm.$emit('update:modelValue', 'J')
await searchInput.vm.$nextTick() // makes sure the DOM is updated
bodyRows = wrapper.findAll('tbody tr')

expect(bodyRows).toHaveLength(2) // Jesse and João
})

it('displays filtered data when searching by name without accent', () => {
searchInput.vm.$emit('input', 'Joao')
it('displays filtered data when searching by name without accent', async () => {
searchInput.vm.$emit('update:modelValue', 'Joao')
await searchInput.vm.$nextTick() // makes sure the DOM is updated
bodyRows = wrapper.findAll('tbody tr')

expect(bodyRows).toHaveLength(1) // João
})

it('displays filtered data when searching by name with accent', () => {
searchInput.vm.$emit('input', 'João')
it('displays filtered data when searching by name with accent', async () => {
searchInput.vm.$emit('update:modelValue', 'João')
await searchInput.vm.$nextTick() // makes sure the DOM is updated
bodyRows = wrapper.findAll('tbody tr')

expect(bodyRows).toHaveLength(1) // João
})

it('displays filtered data when searching and updating data', () => {
searchInput.vm.$emit('input', 'J')
wrapper.setProps({
it('displays filtered data when searching and updating data', async () => {
searchInput.vm.$emit('update:modelValue', 'J')
await wrapper.setProps({
data: [
...data,
{ id: 6, name: 'Justin' }
Expand All @@ -221,18 +222,20 @@ describe('BTable', () => {
expect(bodyRows).toHaveLength(3) // Jesse, João and Justin
})

it('debounce search filtering when debounce-search is defined', () => {
let clock = useFakeTimers()
wrapper.setProps({
it('debounce search filtering when debounce-search is defined', async () => {
jest.useFakeTimers()
await wrapper.setProps({
debounceSearch: 1000
})
for (let i = 0; i < 10; i++) {
searchInput.vm.$emit('input', 'J'.repeat(10 - i))
clock.tick(500)
searchInput.vm.$emit('update:modelValue', 'J'.repeat(10 - i))
jest.advanceTimersByTime(500)
await wrapper.vm.$nextTick() // makes sure the DOM is updated
bodyRows = wrapper.findAll('tbody tr')
expect(bodyRows).toHaveLength(5) // No filtering yet
}
clock.tick(1000)
jest.advanceTimersByTime(1000)
await wrapper.vm.$nextTick() // makes sure the DOM is updated
bodyRows = wrapper.findAll('tbody tr')
expect(bodyRows).toHaveLength(2) // Filtering after debounce
})
Expand Down
32 changes: 16 additions & 16 deletions src/components/table/__snapshots__/Table.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@

exports[`BTable render correctly 1`] = `
<div class="b-table">
<!---->
<!---->
<div class="table-wrapper has-mobile-cards">
<table class="table">
<!---->
<!---->
<tbody>
<tr class="is-empty">
<td colspan="0"></td>
</tr>
</tbody>
<!---->
</table>
<!---->
</div>
<!---->
<!--v-if-->
<!--v-if-->
<div class="table-wrapper has-mobile-cards">
<table class="table">
<!--v-if-->
<!--v-if-->
<tbody>
<tr class="is-empty">
<td colspan="0"></td>
</tr>
</tbody>
<!--v-if-->
</table>
<!--v-if-->
</div>
<!--v-if-->
</div>
`;

0 comments on commit f0db147

Please sign in to comment.