Continuation from pt.4
Implementation
4. test DrillDownSearch
Create files
touch __tests__/pages/DrillDownSearch.spec.js
mkdir -p __tests__/components
touch __tests__/components/Dialog.spec.js
touch __tests__/components/DrillDown.spec.js
Describe DrillDownSearch page
vim __tests__/pages/DrillDownSearch.spec.js
▼
// __tests__/pages/DrillDownSearch.spec.js
import { mount } from '@vue/test-utils'
import Vue from 'vue'
import Vuetify from 'vuetify'
import DrillDownSearch from '../../pages/DrillDownSearch.vue'
Vue.use(Vuetify)
// cf. https://github.com/vuejs/vue-test-utils/issues/974#issuecomment-423721358
// [Vue warn]: Error in mounted hook: "ReferenceError: requestAnimationFrame is not defined"
global.requestAnimationFrame = (cb) => cb()
// This is temporary solution for remove warn below
// [Vue warn]: Error in callback for watcher "isActive": "ReferenceError: cancelAnimationFrame is not defined"
global.cancelAnimationFrame = function() {
setTimeout(function() {}, 0)
}
// This is temporary solution for remove warn below
// [Vue warn]: Error in directive click-outside inserted hook: "ReferenceError: ShadowRoot is not defined"
global.ShadowRoot = (cb) => cb()
// cf. https://github.com/vuejs/vue/issues/9698#issuecomment-473258879
// Attempted to log "[Vue warn]: Error in callback for watcher "listIndex": "ReferenceError: performance is not defined"
// eslint-disable-next-line no-undef
global.performance = window.performance;
describe('DrillDownSearch page', () => {
const app = document.createElement('div')
app.setAttribute('data-app', true)
document.body.appendChild(app)
let vuetify
let wrapper
beforeEach(() => {
vuetify = new Vuetify
wrapper = mount(DrillDownSearch, {
vuetify,
stubs: ['DrillDown']
})
})
it('test', () => {
expect(1).toBe(1)
})
})
It should use dialog when use drilldown
vim __tests__/pages/DrillDownSearch.spec.js
▼
// __tests__/pages/DrillDownSearch.spec.js
// ...
describe('DrillDownSearch page', () => {
// ...
it('should use dialog when use drilldown', async () => {
const buttonElms = wrapper.findAll('.v-btn')
buttonElms.at(0).trigger('click')
await wrapper.vm.$nextTick()
expect(wrapper.vm.isDialogOpened).toBe(true)
})
})
It can access DrillDown data when dialog have been closed
vim __tests__/pages/DrillDownSearch.spec.js
▼
// __tests__/pages/DrillDownSearch.spec.js
// ...
describe('DrillDownSearch page', () => {
// ...
it('can access DrillDown data when dialog have been closed', async () => {
const buttonElms = wrapper.findAll('.v-btn')
buttonElms.at(0).trigger('click')
await wrapper.vm.$nextTick()
wrapper.vm.$refs.confirm.agree()
await wrapper.vm.$nextTick()
expect(wrapper.vm.isResoleved).toBe(true)
})
})
Describe Dialog component
vim __tests__/components/Dialog.spec.js
▼
// __tests__/components/Dialog.spec.js
import { mount } from '@vue/test-utils'
import Vue from 'vue'
import Vuetify from 'vuetify'
import Dialog from '../../components/Dialog.vue'
Vue.use(Vuetify)
// cf. https://github.com/vuejs/vue-test-utils/issues/974#issuecomment-423721358
// [Vue warn]: Error in mounted hook: "ReferenceError: requestAnimationFrame is not defined"
global.requestAnimationFrame = (cb) => cb()
// This is temporary solution for remove warn below
// [Vue warn]: Error in callback for watcher "isActive": "ReferenceError: cancelAnimationFrame is not defined"
global.cancelAnimationFrame = function() {
setTimeout(function() {}, 0)
}
// This is temporary solution for remove warn below
// [Vue warn]: Error in directive click-outside inserted hook: "ReferenceError: ShadowRoot is not defined"
global.ShadowRoot = (cb) => cb()
// cf. https://github.com/vuejs/vue/issues/9698#issuecomment-473258879
// Attempted to log "[Vue warn]: Error in callback for watcher "listIndex": "ReferenceError: performance is not defined"
// eslint-disable-next-line no-undef
global.performance = window.performance;
describe('Dialog component', () => {
const app = document.createElement('div')
app.setAttribute('data-app', true)
document.body.appendChild(app)
let wrapper
let vuetify
beforeEach(() => {
vuetify = new Vuetify
wrapper = mount(Dialog, {
vuetify
})
jest.spyOn(wrapper.vm, 'agree')
jest.spyOn(wrapper.vm, 'cancel')
})
it('test', () => {
expect(1).toBe(1)
})
})
It should return Promise when open itself (pending)
vim __tests__/components/Dialog.spec.js
▼
// __tests__/components/Dialog.spec.js
// ...
describe('Dialog component', () => {
it('should return Promise when open itself (pending)', async () => {
const ret = wrapper.vm.open()
await wrapper.vm.$nextTick()
expect(ret instanceof Promise).toBe(true)
})
})
It should resolve/reject Promise when close itself (notification)
vim __tests__/components/Dialog.spec.js
▼
// __tests__/components/Dialog.spec.js
// ...
describe('Dialog component', () => {
it('should resolve/reject Promise when close itself (notification)', async () => {
const ret = wrapper.vm.open()
await wrapper.vm.$nextTick()
const buttonElms = wrapper.findAll('.v-btn')
buttonElms.at(0).trigger('click')
expect(wrapper.vm.cancel).toHaveBeenCalled()
buttonElms.at(1).trigger('click')
expect(wrapper.vm.agree).toHaveBeenCalled()
})
})
Describe DrillDown component
vim __tests__/components/DrillDown.spec.js
▼
// __tests__/components/DrillDown.spec.js
import { mount } from '@vue/test-utils'
import Vue from 'vue'
import Vuetify from 'vuetify'
import Vuex from 'vuex'
import axios from 'axios'
import DrillDown from '../../components/DrillDown.vue'
Vue.use(Vuetify)
Vue.use(Vuex)
jest.mock('axios', () => ({
$get: jest.fn((path, { params }) => {
const res = makeResDataBy(params)
return Promise.resolve(res)
})
}))
const makeResDataBy = (params) => {
const dummy = require('../../__mock__/api/drillDown/dummy.json')
const res = {
option2: null,
option3: null
}
const reqKeys = Object.keys(params)
const resKeys = Object.keys(res)
const reqLength = Object.keys(params).length
const reqKey = reqKeys[reqLength - 1]
const resKey = resKeys[reqLength - 1]
const reqValue = params[reqKey]
res[resKey] = dummy[reqValue]
return res
}
const state = {
drillDown: {
option2: null,
option3: null
}
}
const actions = {
'drillDown/fetch': jest.fn(async ({ commit }, params) => {
const path = `/drillDown`
axios.$get(path, {params: params})
.then(res => {
commit('SET', res)
})
})
}
const mutations = {
SET(state, obj) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
if (obj[keys[i]]) {
state.drillDown[keys[i]] = obj[keys[i]]
break
}
}
}
}
// cf. https://github.com/vuejs/vue-test-utils/issues/974#issuecomment-423721358
// [Vue warn]: Error in mounted hook: "ReferenceError: requestAnimationFrame is not defined"
global.requestAnimationFrame = (cb) => cb()
// This is temporary solution for remove warn below
// [Vue warn]: Error in directive click-outside inserted hook: "ReferenceError: ShadowRoot is not defined"
global.ShadowRoot = (cb) => cb()
// cf. https://github.com/vuejs/vue/issues/9698#issuecomment-473258879
// Attempted to log "[Vue warn]: Error in callback for watcher "listIndex": "ReferenceError: performance is not defined"
// eslint-disable-next-line no-undef
global.performance = window.performance;
describe('DrillDown component', () => {
// NOTE: this code cause transition-stub do not function
// const app = document.createElement('div')
// app.setAttribute('data-app', true)
// document.body.appendChild(app)
let wrapper
let vuetify
let store
beforeEach(() => {
axios.$get.mockClear();
vuetify = new Vuetify()
store = new Vuex.Store({
state,
actions,
mutations
})
wrapper = mount(DrillDown, {
vuetify,
store,
propsData: {
firstItems: [1, 2, 3],
initialItem: {
option1: '1',
option2: '',
option3: ''
},
path: 'drillDown/fetch'
}
})
})
it('test', () => {
expect(1).toBe(1)
})
})
It have multiple slot
vim __tests__/components/DrillDown.spec.js
▼
// __tests__/components/DrillDown.spec.js
// ...
describe('DrillDown', () => {
// ...
it('have multiple slot', () => {
const elm = wrapper.findAll('.v-input__slot')
expect(elm.length > 1).toBe(true)
})
})
It get options and initial value from parent Class
vim __tests__/components/DrillDown.spec.js
▼
// __tests__/components/DrillDown.spec.js
// ...
describe('DrillDown', () => {
// ...
it('get options and initial value from parent Class', () => {
const list = []
const inputElms = wrapper.findAll('input')
for (let i = 0; i < inputElms.length; i++) {
if (inputElms.at(i).attributes().type !== 'hidden') continue
if (inputElms.at(i).attributes().value) {
list.push(inputElms.at(i).attributes().value)
continue
}
list.push('')
}
const initialItem = wrapper.props().initialItem
Object.keys(initialItem).forEach((item, index) => {
expect(initialItem[item]).toBe(list[index])
})
})
})
It is selected in order
vim __tests__/components/DrillDown.spec.js
▼
// __tests__/components/DrillDown.spec.js
// ...
describe('DrillDown', () => {
// ...
it('is selected in order', () => {
const selections = wrapper.findAll('.v-select__selections')
const initialItem = wrapper.props().initialItem
const optionKeys = Object.keys(initialItem)
let nextIndex = 0
for (let i = 0; i < optionKeys.length; i++) {
if (initialItem[optionKeys[i]] === '') break
nextIndex++
}
const disabled = selections.at(nextIndex + 1).find('input').attributes().disabled
expect(disabled).toBe('disabled')
})
})
It get the next item from api each time one item is selected
vim __tests__/components/DrillDown.spec.js
▼
// __tests__/components/DrillDown.spec.js
// ...
describe('DrillDown', () => {
// ...
it('get the next item from api each time one item is selected', async () => {
const inputElms = wrapper.findAll('.v-input__slot')
wrapper.vm.$nextTick(() => {
expect(axios.$get).toHaveBeenCalledTimes(2)
})
inputElms.at(0).trigger('click')
await wrapper.vm.$nextTick()
const itemElms = wrapper.findAll('.v-list-item')
itemElms.at(2).trigger('click')
await wrapper.vm.$nextTick()
wrapper.vm.$nextTick(() => {
expect(axios.$get).toHaveBeenCalledTimes(3)
})
})
})