buefy
Version:
Lightweight UI components for Vue.js (v3) based on Bulma
168 lines (145 loc) • 5.94 kB
text/typescript
import { transformVNodeArgs } from 'vue'
import { shallowMount } from '@vue/test-utils'
import type { VueWrapper } from '@vue/test-utils'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { BModal, ModalProgrammatic } from '@components/modal'
import config, { setOptions } from '@utils/config'
import type { ModalCancellableOption } from '@utils/config'
let wrapper: VueWrapper<InstanceType<typeof BModal>>
describe('BModal', () => {
beforeEach(() => {
wrapper = shallowMount(BModal, {
props: {
modelValue: true
},
global: {
stubs: {
// intentionally stubs transition component
// to avoid potentially flaky snapshots
transition: true
}
}
})
})
it('is called', () => {
expect(wrapper.vm).toBeTruthy()
expect(wrapper.vm.$options.name).toBe('BModal')
})
it('render correctly', () => {
expect(wrapper.html()).toMatchSnapshot()
})
it('manage props validator', () => {
const ariaRole = wrapper.vm.$options.props.ariaRole
const ariaLabel = wrapper.vm.$options.props.ariaLabel
expect(ariaRole.type).toBe(String)
expect(ariaRole.validator && ariaRole.validator('d')).toBeFalsy()
expect(ariaRole.validator && ariaRole.validator('dialog')).toBeTruthy()
expect(ariaRole.validator && ariaRole.validator('alertdialog')).toBeTruthy()
expect(ariaLabel.type).toBe(String)
expect(ariaLabel.validator && ariaLabel.validator('')).toBeFalsy()
expect(ariaLabel.validator && ariaLabel.validator('d')).toBeTruthy()
})
it('manage default config props values', () => {
setOptions(Object.assign(config, {
defaultModalScroll: 'keep'
}))
wrapper = shallowMount(BModal)
expect(wrapper.vm.scroll).toEqual(config.defaultModalScroll)
})
it('sets isActive when active (modelValue) prop is changed', async () => {
await wrapper.setProps({ modelValue: false })
expect(wrapper.vm.isActive).toBeFalsy()
})
it('manage cancel options', async () => {
await wrapper.setProps({ canCancel: true })
expect(wrapper.vm.cancelOptions).toEqual(config.defaultModalCanCancel)
await wrapper.setProps({ canCancel: false })
expect(wrapper.vm.cancelOptions).toEqual([])
const options: ModalCancellableOption[] = ['escape']
await wrapper.setProps({ canCancel: options })
expect(wrapper.vm.cancelOptions).toEqual(options)
wrapper.vm.close = vi.fn(() => wrapper.vm.close)
// @ts-expect-error leave this for backward compatibility test
wrapper.vm.cancel()
expect(wrapper.vm.close).not.toHaveBeenCalled()
wrapper.vm.cancel('escape')
expect(wrapper.vm.close).toHaveBeenCalledTimes(1)
})
it('close on escape', async () => {
await wrapper.setProps({ canCancel: true })
await wrapper.setProps({ modelValue: true })
wrapper.vm.cancel = vi.fn(() => wrapper.vm.cancel)
const event = new KeyboardEvent('keyup', { key: 'Escape' })
// @ts-expect-error leave this for backward compatibility test
wrapper.vm.keyPress({})
expect(wrapper.vm.cancel).not.toHaveBeenCalled()
wrapper.vm.keyPress(event)
expect(wrapper.vm.cancel).toHaveBeenCalledTimes(1)
})
it('emit events on close but stay active', () => {
wrapper.vm.close()
expect(wrapper.emitted().close).toBeTruthy()
expect(wrapper.emitted()['update:modelValue']).toBeTruthy()
expect(wrapper.vm.isActive).toBeTruthy()
})
it('should be deactivated on close if programmatic', async () => {
await wrapper.setProps({ programmatic: true })
wrapper.vm.close()
expect(wrapper.vm.isActive).toBeFalsy()
})
describe('programmatically opened', () => {
beforeEach(() => {
// resets stubs introduced by @vue/test-utils
// otherwise, every BModal becomes a stub
transformVNodeArgs()
})
it('should be able to be manually closed', async () => {
const modal = new ModalProgrammatic().open({
content: 'content'
})
await modal.$nextTick() // makes sure DOM is updated
expect(document.querySelector('.modal')).toBeTruthy()
vi.useFakeTimers()
modal.close()
vi.advanceTimersByTime(150)
expect(document.querySelector('.modal')).toBeFalsy()
vi.useRealTimers()
})
})
it('emit event on transition after-enter hook.', () => {
wrapper.vm.afterEnter()
expect(wrapper.emitted()['after-enter']).toBeTruthy()
})
it('emit event on transition after-leave hook.', () => {
wrapper.vm.afterLeave()
expect(wrapper.emitted()['after-leave']).toBeTruthy()
})
it('should not be rendered on mounted if active and renderOnMounted are false', () => {
const wrapper = shallowMount(BModal, {
props: {
modelValue: false,
renderOnMounted: false
},
global: {
stubs: {
transition: false
}
}
})
expect(wrapper.find('.modal.is-active').exists()).toBeFalsy()
})
it('should be rendered on mounted if active is false but renderOnMounted is true', () => {
const wrapper = shallowMount(BModal, {
props: {
modelValue: false,
renderOnMounted: true
},
global: {
stubs: {
transition: false
}
}
})
expect(wrapper.find('.modal.is-active').exists()).toBeTruthy()
})
})