Skip to content

Commit ea1b1fd

Browse files
authored
test(counter): improve test coverage (#1999)
1 parent 529f808 commit ea1b1fd

1 file changed

Lines changed: 338 additions & 11 deletions

File tree

packages/varlet-ui/src/counter/__tests__/index.spec.js

Lines changed: 338 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { mount } from '@vue/test-utils'
22
import { expect, test, vi } from 'vite-plus/test'
33
import { createApp } from 'vue'
4-
import { z } from 'zod'
54
import Counter from '..'
65
import { delay, trigger } from '../../utils/test'
76
import VarCounter from '../Counter'
@@ -439,31 +438,359 @@ test('counter onIncrement & onDecrement', async () => {
439438

440439
wrapper.unmount()
441440
})
442-
test('counter validation with zod', async () => {
441+
442+
test('counter validate on increment trigger', async () => {
443+
const wrapper = mount({
444+
...Wrapper,
445+
template: `<var-counter ref="counter" :rules="[v => v < 1 || 'Too big']" v-model="value" />`,
446+
})
447+
448+
await wrapper.find('.var-counter__increment-button').trigger('click')
449+
await delay(16)
450+
451+
expect(wrapper.find('.var-form-details__error-message').text()).toBe('Too big')
452+
453+
wrapper.unmount()
454+
})
455+
456+
test('counter validate on decrement trigger', async () => {
457+
const wrapper = mount({
458+
...Wrapper,
459+
template: `<var-counter ref="counter" :rules="[v => v >= 0 || 'Too small']" v-model="value" />`,
460+
})
461+
462+
await wrapper.find('.var-counter__decrement-button').trigger('click')
463+
await delay(16)
464+
465+
expect(wrapper.find('.var-form-details__error-message').text()).toBe('Too small')
466+
467+
wrapper.unmount()
468+
})
469+
470+
test('counter press increment release stops timers', async () => {
471+
vi.useFakeTimers()
472+
const wrapper = mount(Wrapper)
473+
474+
await trigger(wrapper.find('.var-counter__increment-button'), 'touchstart')
475+
vi.advanceTimersByTime(700)
476+
477+
const current = wrapper.vm.value
478+
expect(current).toBeGreaterThan(0)
479+
480+
await trigger(wrapper.find('.var-counter__increment-button'), 'touchend')
481+
vi.advanceTimersByTime(300)
482+
483+
expect(wrapper.vm.value).toBe(current)
484+
485+
wrapper.unmount()
486+
vi.useRealTimers()
487+
})
488+
489+
test('counter validate on increment and decrement methods', async () => {
490+
const wrapper = mount({
491+
...Wrapper,
492+
template: `<var-counter :rules="[v => v === 0 || 'Invalid']" v-model="value" />`,
493+
})
494+
495+
const counter = wrapper.findComponent(VarCounter)
496+
497+
counter.vm.increment()
498+
await delay(16)
499+
expect(wrapper.find('.var-form-details__error-message').text()).toBe('Invalid')
500+
501+
counter.vm.decrement()
502+
await delay(16)
503+
expect(wrapper.find('.var-form-details__error-message').exists()).toBe(false)
504+
505+
wrapper.unmount()
506+
})
507+
508+
test('counter press increment and release methods', () => {
509+
vi.useFakeTimers()
510+
const wrapper = mount(Wrapper)
511+
const counter = wrapper.findComponent(VarCounter)
512+
513+
counter.vm.pressIncrement()
514+
vi.advanceTimersByTime(700)
515+
516+
const current = wrapper.vm.value
517+
counter.vm.releaseIncrement()
518+
vi.advanceTimersByTime(300)
519+
520+
expect(wrapper.vm.value).toBe(current)
521+
522+
wrapper.unmount()
523+
vi.useRealTimers()
524+
})
525+
526+
test('counter press decrement and release methods', () => {
527+
vi.useFakeTimers()
528+
const wrapper = mount(Wrapper)
529+
const counter = wrapper.findComponent(VarCounter)
530+
531+
counter.vm.pressDecrement()
532+
vi.advanceTimersByTime(700)
533+
534+
const current = wrapper.vm.value
535+
counter.vm.releaseDecrement()
536+
vi.advanceTimersByTime(300)
537+
538+
expect(wrapper.vm.value).toBe(current)
539+
540+
wrapper.unmount()
541+
vi.useRealTimers()
542+
})
543+
544+
test('counter touchcancel on increment', async () => {
545+
const wrapper = mount(Wrapper)
546+
547+
await trigger(wrapper.find('.var-counter__increment-button'), 'touchstart')
548+
await delay(100)
549+
550+
await trigger(wrapper.find('.var-counter__increment-button'), 'touchcancel')
551+
await delay(100)
552+
553+
expect(wrapper.vm.value).toBe(0)
554+
555+
wrapper.unmount()
556+
})
557+
558+
test('counter touchcancel on decrement', async () => {
559+
const wrapper = mount(Wrapper)
560+
561+
await trigger(wrapper.find('.var-counter__decrement-button'), 'touchstart')
562+
await delay(100)
563+
564+
await trigger(wrapper.find('.var-counter__decrement-button'), 'touchcancel')
565+
await delay(100)
566+
567+
expect(wrapper.vm.value).toBe(0)
568+
569+
wrapper.unmount()
570+
})
571+
572+
test('counter lazy change with decrement validation', async () => {
573+
const onBeforeChange = vi.fn((value, change) => change(value))
574+
575+
const wrapper = mount({
576+
...Wrapper,
577+
methods: {
578+
onBeforeChange,
579+
},
580+
template: `<var-counter lazy-change :rules="[v => v >= 0 || 'Invalid']" v-model="value" @before-change="onBeforeChange" />`,
581+
})
582+
583+
await wrapper.find('.var-counter__decrement-button').trigger('click')
584+
await delay(16)
585+
586+
expect(onBeforeChange).toHaveBeenCalled()
587+
expect(wrapper.find('.var-form-details__error-message').text()).toBe('Invalid')
588+
589+
wrapper.unmount()
590+
})
591+
592+
test('counter lazy change with increment validation', async () => {
593+
const onBeforeChange = vi.fn((value, change) => change(value))
594+
595+
const wrapper = mount({
596+
...Wrapper,
597+
methods: {
598+
onBeforeChange,
599+
},
600+
template: `<var-counter lazy-change :rules="[v => v <= 0 || 'Invalid']" v-model="value" @before-change="onBeforeChange" />`,
601+
})
602+
603+
await wrapper.find('.var-counter__increment-button').trigger('click')
604+
await delay(16)
605+
606+
expect(onBeforeChange).toHaveBeenCalled()
607+
expect(wrapper.find('.var-form-details__error-message').text()).toBe('Invalid')
608+
609+
wrapper.unmount()
610+
})
611+
612+
test('counter press increment long enough to set incrementTimer then release', async () => {
443613
const wrapper = mount({
444614
...Wrapper,
445615
data: () => ({
446616
value: 0,
447-
rules: z.number().min(1, 'The value must be more than zero'),
448617
}),
449-
template: `<var-counter ref="counter" :rules="[v => v > 0 || 'The value must be more than zero']" v-model="value" />`,
618+
template: `<var-counter press v-model="value" />`,
450619
})
451620

452-
const { counter } = wrapper.vm.$refs
621+
// Press and hold long enough for continuedIncrement to be called
622+
// DELAY is 600ms, SPEED is 100ms, so after 800ms incrementTimer should be set
623+
await trigger(wrapper.find('.var-counter__increment-button'), 'touchstart')
624+
await delay(800)
453625

454-
counter.validate()
626+
const current = wrapper.vm.value
627+
expect(current).toBeGreaterThan(0)
628+
629+
// Release should clear both incrementTimer and incrementDelayTimer (line 319-320)
630+
await trigger(wrapper.find('.var-counter__increment-button'), 'touchend')
631+
await delay(200)
632+
633+
// Value should not change after release
634+
expect(wrapper.vm.value).toBe(current)
635+
636+
wrapper.unmount()
637+
})
638+
639+
test('counter press decrement long enough to set decrementTimer then release', async () => {
640+
const wrapper = mount({
641+
...Wrapper,
642+
data: () => ({
643+
value: 0,
644+
}),
645+
template: `<var-counter press v-model="value" />`,
646+
})
647+
648+
// Press and hold long enough for continuedDecrement to be called
649+
await trigger(wrapper.find('.var-counter__decrement-button'), 'touchstart')
650+
await delay(800)
651+
652+
const current = wrapper.vm.value
653+
expect(current).toBeLessThan(0)
654+
655+
// Release should clear both decrementTimer and decrementDelayTimer (line 314-315)
656+
await trigger(wrapper.find('.var-counter__decrement-button'), 'touchend')
657+
await delay(200)
658+
659+
// Value should not change after release
660+
expect(wrapper.vm.value).toBe(current)
661+
662+
wrapper.unmount()
663+
})
664+
665+
test('counter reset with min resets to min', async () => {
666+
// reset() takes the `min != null ? toNumber(min) : 0` true branch at line 184
667+
const wrapper = mount({
668+
...Wrapper,
669+
data: () => ({
670+
value: 5,
671+
}),
672+
template: `<var-counter ref="counter" :min="2" v-model="value" />`,
673+
})
674+
675+
const { counter } = wrapper.vm.$refs
676+
counter.reset()
455677
await delay(16)
678+
expect(wrapper.vm.value).toBe(2)
456679

457-
expect(wrapper.html()).toMatchSnapshot()
458-
expect(wrapper.find('.var-form-details__error-message').text()).toBe('The value must be more than zero')
680+
wrapper.unmount()
681+
})
682+
683+
test('counter lazy change via input typing', async () => {
684+
// handleChange takes the lazyChange branch of the ternary at line 214
685+
const onBeforeChange = vi.fn((value, change) => change(value))
686+
687+
const wrapper = mount({
688+
...Wrapper,
689+
data: () => ({
690+
value: 0,
691+
}),
692+
methods: {
693+
onBeforeChange,
694+
},
695+
template: `<var-counter lazy-change v-model="value" @before-change="onBeforeChange" />`,
696+
})
697+
698+
wrapper.find('.var-counter__input').setValue('5')
699+
await wrapper.find('.var-counter__input').trigger('change')
700+
701+
expect(onBeforeChange).toHaveBeenCalledWith(5, expect.any(Function))
702+
expect(wrapper.vm.value).toBe(5)
703+
704+
wrapper.unmount()
705+
})
706+
707+
test('counter increment at max returns early', async () => {
708+
// increment() hits the `if (isMax.value) return` guard at line 272
709+
const wrapper = mount({
710+
...Wrapper,
711+
data: () => ({
712+
value: 10,
713+
}),
714+
template: `<var-counter :max="10" v-model="value" />`,
715+
})
459716

717+
await wrapper.find('.var-counter__increment-button').trigger('click')
718+
expect(wrapper.vm.value).toBe(10)
719+
720+
wrapper.unmount()
721+
})
722+
723+
test('counter decrement at min returns early', async () => {
724+
// decrement() hits the `if (isMin.value) return` guard at line 237
725+
const wrapper = mount({
726+
...Wrapper,
727+
data: () => ({
728+
value: 0,
729+
}),
730+
template: `<var-counter :min="0" v-model="value" />`,
731+
})
732+
733+
await wrapper.find('.var-counter__decrement-button').trigger('click')
734+
expect(wrapper.vm.value).toBe(0)
735+
736+
wrapper.unmount()
737+
})
738+
739+
test('counter press disabled does not increment or decrement', async () => {
740+
// pressIncrement (line 305) and pressDecrement (line 293) return early when press is false
741+
const wrapper = mount({
742+
...Wrapper,
743+
data: () => ({
744+
value: 0,
745+
}),
746+
template: `<var-counter :press="false" v-model="value" />`,
747+
})
748+
749+
await trigger(wrapper.find('.var-counter__increment-button'), 'touchstart')
750+
await delay(800)
751+
expect(wrapper.vm.value).toBe(0)
752+
753+
await trigger(wrapper.find('.var-counter__decrement-button'), 'touchstart')
754+
await delay(800)
755+
expect(wrapper.vm.value).toBe(0)
756+
757+
wrapper.unmount()
758+
})
759+
760+
test('counter increment without lazyChange triggers validation', async () => {
761+
const wrapper = mount({
762+
...Wrapper,
763+
data: () => ({
764+
value: 0,
765+
}),
766+
template: `<var-counter :rules="[v => v === 0 || 'error']" :lazy-change="false" v-model="value" />`,
767+
})
768+
769+
// Increment should trigger validateWithTrigger at line 285
460770
await wrapper.find('.var-counter__increment-button').trigger('click')
461771
await delay(16)
462-
expect(wrapper.find('.var-form-details__error-message').exists()).toBeFalsy()
463772

464-
counter.reset()
773+
// Validation should have been triggered
774+
expect(wrapper.find('.var-form-details__error-message').text()).toBe('error')
775+
776+
wrapper.unmount()
777+
})
778+
779+
test('counter decrement without lazyChange triggers validation', async () => {
780+
const wrapper = mount({
781+
...Wrapper,
782+
data: () => ({
783+
value: 0,
784+
}),
785+
template: `<var-counter :rules="[v => v === 0 || 'error']" :lazy-change="false" v-model="value" />`,
786+
})
787+
788+
// Decrement should trigger validateWithTrigger at line 250
789+
await wrapper.find('.var-counter__decrement-button').trigger('click')
465790
await delay(16)
466-
expect(wrapper.vm.value).toBe(0)
791+
792+
// Validation should have been triggered
793+
expect(wrapper.find('.var-form-details__error-message').text()).toBe('error')
467794

468795
wrapper.unmount()
469796
})

0 commit comments

Comments
 (0)