UNPKG

@stackoverfloweth/vue-compositions

Version:

A collection of reusable vue compositions.

159 lines 7.31 kB
/* eslint-disable vue/one-component-per-file */ import { mount } from '@vue/test-utils'; import { describe, expect, it, vi } from 'vitest'; import { defineComponent, ref } from 'vue'; import { useValidation } from '../useValidation/useValidation'; import { timeout } from '../utilities/tests'; const isGreaterThanZero = (value, name) => { if (value > 0) { return true; } return `${name} must be greater than 0`; }; describe('useValidation', () => { describe('validate', () => { it.each([ { value: 1, valueType: 'plain value' }, { value: ref(1), valueType: 'ref' }, { value: () => 1, valueType: 'getter' }, ])('sets valid to true when the rules pass (with $valueType)', async ({ value }) => { const { valid, error, validate } = useValidation(value, isGreaterThanZero); await validate(); expect(valid.value).toBe(true); expect(error.value).toBe(''); }); it.each([ { value: 0, valueType: 'plain value' }, { value: ref(0), valueType: 'ref' }, { value: () => 1, valueType: 'getter' }, ])('sets valid to false with an error message when the rules do not pass (with $valueType)', async ({ value }) => { const errorMessage = 'Validation did not pass'; const validationRule = () => errorMessage; const { valid, error, validate } = useValidation(value, validationRule); await validate(); expect(valid.value).toBe(false); expect(error.value).toBe(errorMessage); }); it('triggers automatically when the value changes', async () => { const theValue = ref(0); const validationRule = vi.fn().mockResolvedValue('Validation did not pass'); const wrapper = mount(defineComponent({ name: 'TestComponent', expose: ['valid', 'error'], setup() { const { valid, error } = useValidation(theValue, validationRule); return { valid, error }; }, })); expect(wrapper.vm.valid).toBe(true); expect(wrapper.vm.error).toBe(''); expect(validationRule).not.toHaveBeenCalled(); theValue.value = 1; await timeout(); expect(validationRule).toHaveBeenCalled(); expect(wrapper.vm.error).toBe('Validation did not pass'); expect(wrapper.vm.valid).toBe(false); }); }); describe('pause and resume', () => { it('prevents validation from running when paused', async () => { const theValue = ref(0); const validationRule = vi.fn().mockResolvedValue('Validation did not pass'); const wrapper = mount(defineComponent({ name: 'TestComponent', expose: ['valid', 'error', 'pause', 'resume'], setup() { const { valid, error, pause, resume } = useValidation(theValue, validationRule); return { valid, error, pause, resume }; }, })); expect(wrapper.vm.valid).toBe(true); expect(wrapper.vm.error).toBe(''); expect(validationRule).not.toHaveBeenCalled(); wrapper.vm.pause(); theValue.value = 1; await timeout(); expect(validationRule).not.toHaveBeenCalled(); expect(wrapper.vm.error).toBe(''); expect(wrapper.vm.valid).toBe(true); wrapper.vm.resume(); theValue.value = 2; await timeout(); expect(validationRule).toHaveBeenCalled(); expect(wrapper.vm.error).toBe('Validation did not pass'); expect(wrapper.vm.valid).toBe(false); }); }); describe('reset', () => { it('resets the validation state', async () => { const { state, validate, reset } = useValidation(ref(0), () => 'Validation did not pass'); await validate(); expect(state.valid).toBe(false); expect(state.error).toBe('Validation did not pass'); reset(); expect(state.valid).toBe(true); expect(state.error).toBe(''); expect(state.validated).toBe(false); }); it('resets the validation state and optionally allows the value to be reset without revalidating', async () => { const theValue = ref(0); async function updateTheValueAndWaitForEffects(value) { theValue.value = value; await timeout(); } const wrapper = mount(defineComponent({ name: 'TestComponent', expose: ['state', 'reset', 'pause', 'resume'], setup() { const { state, reset, pause, resume } = useValidation(theValue, isGreaterThanZero); return { state, reset, pause, resume }; }, })); expect(wrapper.vm.state.valid).toBe(true); await updateTheValueAndWaitForEffects(-1); expect(wrapper.vm.state.valid).toBe(false); // without the reset callback managing pause/resume, changing the value triggers validations again wrapper.vm.reset(); expect(wrapper.vm.state.valid).toBe(true); await updateTheValueAndWaitForEffects(0); expect(wrapper.vm.state.valid).toBe(false); // now try with a reset callback await updateTheValueAndWaitForEffects(1); expect(wrapper.vm.state.valid).toBe(true); wrapper.vm.reset(() => theValue.value = 0); await timeout(); expect(theValue.value).toBe(0); expect(wrapper.vm.state.valid).toBe(true); // make sure it resumes normal behavior await updateTheValueAndWaitForEffects(-1); expect(wrapper.vm.state.valid).toBe(false); }); it('resumes validation if an error occurs in the reset callback', async () => { const theValue = ref(0); const validationRule = vi.fn().mockResolvedValue('Validation did not pass'); const wrapper = mount(defineComponent({ name: 'TestComponent', expose: ['state', 'reset'], setup() { const { state, reset } = useValidation(theValue, validationRule); return { state, reset }; }, })); expect(wrapper.vm.state.valid).toBe(true); expect(wrapper.vm.state.error).toBe(''); expect(validationRule).not.toHaveBeenCalled(); expect(() => wrapper.vm.reset(() => { theValue.value = 1; throw new Error('Something went wrong'); })).toThrowError('Something went wrong'); await timeout(); expect(validationRule).not.toHaveBeenCalled(); expect(wrapper.vm.state.valid).toBe(true); // watcher resumed theValue.value = 2; await timeout(); expect(validationRule).toHaveBeenCalled(); }); }); }); //# sourceMappingURL=useValidation.spec.js.map