import { nextTick, ref, reactive, defineComponent } from 'vue' import { mount } from '@vue/test-utils' import { describe, it, expect, fn, beforeEach, afterEach } from 'vitest' import { useModelToggle, useModelToggleProps } from '../use-model-toggle' import type { VueWrapper } from '@vue/test-utils' const AXIOM = 'Rem is the best girl' const onShow = fn() const onHide = fn() let flag = true const shouldProceed = () => flag const Comp = defineComponent({ props: { ...useModelToggleProps, disabled: Boolean, }, setup(props) { const indicator = ref(false) const { show, hide, toggle } = useModelToggle({ indicator, onShow, onHide, shouldProceed, shouldHideWhenRouteChanges: ref(true), }) return () => { return ( <> {indicator.value || props.modelValue ?
{AXIOM}
: undefined} ) } }, }) describe('use-model-toggle', () => { let wrapper: VueWrapper beforeEach(() => { flag = true wrapper = mount(Comp) onShow.mockClear() onHide.mockClear() }) afterEach(() => { wrapper.unmount() }) it('should render correctly', async () => { expect(wrapper.text()).not.toContain(AXIOM) }) it('should show and hide via API calls', async () => { expect(wrapper.text()).not.toContain(AXIOM) await wrapper.find('.show').trigger('click') expect(wrapper.text()).toContain(AXIOM) expect(onShow).toHaveBeenCalledTimes(1) await wrapper.find('.hide').trigger('click') expect(wrapper.text()).not.toContain(AXIOM) expect(onHide).toHaveBeenCalledTimes(1) }) it('should call callbacks correctly', async () => { expect(wrapper.text()).not.toContain(AXIOM) await wrapper.find('.show').trigger('click') expect(wrapper.text()).toContain(AXIOM) expect(onShow).toHaveBeenCalledTimes(1) await wrapper.find('.show').trigger('click') expect(onShow).toHaveBeenCalledTimes(1) await wrapper.find('.hide').trigger('click') expect(wrapper.text()).not.toContain(AXIOM) expect(onHide).toHaveBeenCalledTimes(1) await wrapper.find('.hide').trigger('click') expect(onHide).toHaveBeenCalledTimes(1) }) it('should toggle show and hide via API calls', async () => { expect(wrapper.text()).not.toContain(AXIOM) await wrapper.find('.toggle').trigger('click') expect(wrapper.text()).toContain(AXIOM) expect(onShow).toHaveBeenCalledTimes(1) await wrapper.find('.toggle').trigger('click') expect(wrapper.text()).not.toContain(AXIOM) expect(onHide).toHaveBeenCalledTimes(1) }) it('should not proceed when the should proceed returns false', async () => { flag = false expect(wrapper.text()).not.toContain(AXIOM) await wrapper.find('.show').trigger('click') expect(wrapper.text()).not.toContain(AXIOM) expect(onShow).not.toHaveBeenCalled() await wrapper.find('.toggle').trigger('click') expect(wrapper.text()).not.toContain(AXIOM) expect(onShow).not.toHaveBeenCalled() }) it('should bind with modelValue', async () => { wrapper.unmount() const model = ref(false) const disabled = ref(false) wrapper = mount({ setup: () => () => , }) expect(wrapper.findComponent(Comp).text()).not.toContain(AXIOM) await wrapper.find('.show').trigger('click') expect(model.value).toBe(true) expect(wrapper.findComponent(Comp).text()).toContain(AXIOM) await wrapper.find('.hide').trigger('click') expect(onHide).toHaveBeenCalledTimes(1) expect(model.value).toBe(false) expect(wrapper.findComponent(Comp).text()).not.toContain(AXIOM) model.value = true disabled.value = true await nextTick() // when disabled emits false that modifies the model expect(model.value).toBe(false) // should not hide when disabled await wrapper.find('.hide').trigger('click') expect(onHide).toHaveBeenCalledTimes(1) }) it('should hide when route changes', async () => { wrapper.unmount() const router = reactive({ test: '/', }) wrapper = mount(Comp, { global: { config: { globalProperties: { $route: router, }, }, }, }) expect(wrapper.text()).not.toContain(AXIOM) await wrapper.find('.show').trigger('click') expect(wrapper.text()).toContain(AXIOM) expect(onHide).toHaveBeenCalledTimes(0) router.test = '/test/changed' await nextTick() expect(onHide).toHaveBeenCalledTimes(1) }) })