UNPKG

@maxpike/vue

Version:

Vue VariantJS: Fully configurable Vue 3 components styled with TailwindCSS

278 lines (204 loc) 6.78 kB
import { mount } from '@vue/test-utils'; import TAlert from '@/components/TAlert.vue'; import { scopedParamsAsString, parseScopedParams } from '../testUtils'; describe('TAlert.vue', () => { it('renders the component without errors', () => { const wrapper = mount(TAlert, { slots: { default: 'Hello World!', }, }); expect(wrapper.vm.$el.textContent).toEqual('Hello World!'); expect(wrapper.vm.$refs.wrapper).toBeTruthy(); expect(wrapper.vm.$refs.body).toBeTruthy(); expect(wrapper.vm.$refs.close).toBeTruthy(); expect(wrapper.vm.$refs.closeIcon).toBeTruthy(); }); it('renders the `text` prop on the alert body', () => { const wrapper = mount(TAlert, { props: { text: 'Hello World!', }, }); expect(wrapper.vm.$el.textContent).toEqual('Hello World!'); }); it('prioritized the slot over the `text` prop', () => { const wrapper = mount(TAlert, { props: { text: 'Goodbye World!', }, slots: { default: 'Hello World!', }, }); expect(wrapper.vm.$el.textContent).toEqual('Hello World!'); }); it('accepts a custom `tagName` for the alert wrapper', () => { const wrapper = mount(TAlert, { props: { tagName: 'fieldset', }, }); expect(wrapper.vm.$refs.wrapper.tagName).toBe('FIELDSET'); }); it('accepts a custom `bodyTagName` for the alert wrapper', () => { const wrapper = mount(TAlert, { props: { bodyTagName: 'fieldset', }, }); expect(wrapper.vm.$refs.body.tagName).toBe('FIELDSET'); }); it('hides the closeButton if `dismissible` is set to `false`', () => { const wrapper = mount(TAlert, { props: { dismissible: false, }, }); expect(wrapper.vm.$refs.close).toBeUndefined(); }); it('hides the component when the close button is pressed ', async () => { const wrapper = mount(TAlert); const trigger = wrapper.get('button'); await trigger.trigger('click'); expect(wrapper.vm.shown).toBe(false); }); it('starts with the alert hidden if `show` if set to `false`', () => { const wrapper = mount(TAlert, { props: { show: false, }, }); expect(wrapper.vm.shown).toBe(false); }); it('emits `update:show` when show property is updated', async () => { const wrapper = mount(TAlert); wrapper.vm.doHide(); await wrapper.vm.$nextTick(); // assert event has been emitted expect(wrapper.emitted()['update:show']).toBeTruthy(); // assert event payload expect(wrapper.emitted()['update:show']).toEqual([[false]]); wrapper.vm.doShow(); await wrapper.vm.$nextTick(); // assert event has been emitted expect(wrapper.emitted()['update:show']).toBeTruthy(); // assert event payload expect(wrapper.emitted()['update:show']).toEqual([[false], [true]]); }); it('hides the element after the `timeout`', async () => { jest.useFakeTimers(); const wrapper = mount(TAlert, { props: { timeout: 500, }, }); jest.advanceTimersByTime(499); expect(wrapper.vm.shown).toBe(true); jest.advanceTimersByTime(1); expect(wrapper.vm.shown).toBe(false); jest.useRealTimers(); }); it('doesnt clear the timeout if not defined', async () => { jest.useFakeTimers(); const timeoutSpy = spyOn(window, 'setTimeout'); const clearTimeoutSpy = spyOn(window, 'clearTimeout'); const wrapper = mount(TAlert); wrapper.unmount(); expect(timeoutSpy).not.toHaveBeenCalled(); expect(clearTimeoutSpy).not.toHaveBeenCalled(); }); it('clears the `timeout` when the element is unmounted', async () => { jest.useFakeTimers(); const wrapper = mount(TAlert, { props: { timeout: 500, }, }); const hideAction = jest.spyOn(wrapper.vm, 'doHide'); jest.advanceTimersByTime(499); wrapper.unmount(); jest.advanceTimersByTime(1); expect(hideAction).not.toHaveBeenCalled(); jest.useRealTimers(); }); it('clears the `timeout` when the element is hidden manually', async () => { const clearTimeoutSpy = spyOn(window, 'clearTimeout'); const wrapper = mount(TAlert, { props: { timeout: 500, }, }); wrapper.vm.doHide(); expect(clearTimeoutSpy).toHaveBeenCalled(); }); it('accepts a custom `closeIcon``', async () => { const closeIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M12.707" clip-rule="evenodd"></path> </svg>`; const wrapper = mount(TAlert, { props: { closeIcon, }, }); expect(wrapper.vm.$refs.close.innerHTML).toContain('<path fill-rule="evenodd" d="M12.707" clip-rule="evenodd"'); }); it('has a closeButton slot', async () => { // Supress "Property undefined was accessed during render but is not defined on instance." warning // @TODO consider an alternative to this jest.spyOn(console, 'warn').mockImplementation(() => {}); const closeButton = '<button><span>x</span></button>'; const wrapper = mount(TAlert, { slots: { closeButton, }, }); expect(wrapper.html()).toContain(closeButton); }); it('exposes the `toggle`, `show` and `hide` methods and the configuration to the closeButton slot ', () => { const wrapper = mount(TAlert, { slots: { closeButton: (params) => scopedParamsAsString(params), }, }); const scopeParamKeys = parseScopedParams(wrapper.text()); expect(scopeParamKeys).toEqual({ show: 'function', hide: 'function', toggle: 'function', configuration: 'object', }); }); it('exposes the `toggle`, `show` and `hide` methods and the configuration to the default slot ', () => { const wrapper = mount(TAlert, { slots: { default: (params) => scopedParamsAsString(params), }, }); const scopeParamKeys = parseScopedParams(wrapper.text()); expect(scopeParamKeys).toEqual({ show: 'function', hide: 'function', toggle: 'function', configuration: 'object', }); }); it('syncs the `shown` value with the prop configuration', async () => { const wrapper = mount(TAlert); await wrapper.setProps({ show: false, }); expect(wrapper.vm.shown).toBe(false); await wrapper.setProps({ show: true, }); expect(wrapper.vm.shown).toBe(true); }); it('hides or shows the component with the doToggle method', () => { const wrapper = mount(TAlert); wrapper.vm.doToggle(); expect(wrapper.vm.shown).toBe(false); wrapper.vm.doToggle(); expect(wrapper.vm.shown).toBe(true); }); });