1 | import { shallowMount } from '@vue/test-utils';
|
2 | import { waitForAnimationFrame } from '~/utils/test_utils';
|
3 | import GlAnimatedNumber from './animated_number.vue';
|
4 |
|
5 | const duration = 2000;
|
6 | const ACTION_ANIMATED = 'animated';
|
7 | const ACTION_ANIMATING = 'animating';
|
8 |
|
9 | describe('GlAnimatedNumber', () => {
|
10 | let wrapper;
|
11 |
|
12 | const createComponent = ({ number = 100, decimalPlaces = 0, animateOnMount = false } = {}) => {
|
13 | wrapper = shallowMount(GlAnimatedNumber, {
|
14 | propsData: {
|
15 | number,
|
16 | decimalPlaces,
|
17 | duration,
|
18 | animateOnMount,
|
19 | },
|
20 | });
|
21 | };
|
22 |
|
23 | const runOutAnimationTimer = async () => {
|
24 | const {
|
25 | vm: { startTime },
|
26 | } = wrapper;
|
27 |
|
28 | wrapper.setData({
|
29 | startTime: startTime - duration,
|
30 | });
|
31 |
|
32 | await waitForAnimationFrame();
|
33 | };
|
34 |
|
35 | it('renders the component', () => {
|
36 | createComponent();
|
37 |
|
38 | expect(wrapper.findComponent(GlAnimatedNumber).exists()).toBe(true);
|
39 | });
|
40 |
|
41 | describe('when animateOnMount is false', () => {
|
42 | describe.each`
|
43 | withDecimal | number | updatedNumber | decimalPlaces | expectedInitialOnMount | expectedInitialOnUpdate
|
44 | ${false} | ${100} | ${200} | ${0} | ${'100'} | ${'200'}
|
45 | ${true} | ${100.2} | ${200.2} | ${1} | ${'100.2'} | ${'200.2'}
|
46 | `(
|
47 | 'withDecimal === $withDecimal',
|
48 | ({
|
49 | number,
|
50 | updatedNumber,
|
51 | decimalPlaces,
|
52 | expectedInitialOnMount,
|
53 | expectedInitialOnUpdate,
|
54 | }) => {
|
55 | beforeEach(() => {
|
56 | createComponent({ number, decimalPlaces });
|
57 | });
|
58 |
|
59 | it('displays the correct number on mount', async () => {
|
60 | await waitForAnimationFrame();
|
61 |
|
62 | expect(wrapper.text()).toBe(expectedInitialOnMount);
|
63 | });
|
64 |
|
65 | it('displays the correct number when updated', async () => {
|
66 | await waitForAnimationFrame();
|
67 |
|
68 | await wrapper.setProps({ number: updatedNumber });
|
69 |
|
70 | await runOutAnimationTimer();
|
71 |
|
72 | expect(wrapper.text()).toBe(expectedInitialOnUpdate);
|
73 | });
|
74 | }
|
75 | );
|
76 | });
|
77 |
|
78 | describe('when animateOnMount is true', () => {
|
79 | describe.each`
|
80 | withDecimal | number | decimalPlaces | expectedInitial
|
81 | ${false} | ${100} | ${0} | ${'0'}
|
82 | ${true} | ${100.2} | ${1} | ${'0.0'}
|
83 | `('withDecimal === $withDecimal', ({ number, decimalPlaces, expectedInitial }) => {
|
84 | beforeEach(() => {
|
85 | createComponent({ number, decimalPlaces, animateOnMount: true });
|
86 | });
|
87 |
|
88 | it('displays the correct intial number', () => {
|
89 | expect(wrapper.text()).toBe(expectedInitial);
|
90 | });
|
91 |
|
92 | it('displays the correct end number', async () => {
|
93 | await runOutAnimationTimer();
|
94 |
|
95 | expect(wrapper.text()).toBe(`${number}`);
|
96 | });
|
97 | });
|
98 | });
|
99 |
|
100 | describe('animation event emissions', () => {
|
101 | beforeEach(() => {
|
102 | createComponent({ animateOnMount: true });
|
103 | });
|
104 |
|
105 | it(`emits ${ACTION_ANIMATING} when the animation starts`, () => {
|
106 | expect(wrapper.emitted(ACTION_ANIMATING)).toHaveLength(1);
|
107 | });
|
108 |
|
109 | it(`emits ${ACTION_ANIMATED} when the animation completes`, async () => {
|
110 | expect(wrapper.emitted(ACTION_ANIMATED)).toBeUndefined();
|
111 |
|
112 | await waitForAnimationFrame();
|
113 |
|
114 | expect(wrapper.emitted(ACTION_ANIMATED)).toBeUndefined();
|
115 |
|
116 | await runOutAnimationTimer();
|
117 |
|
118 | expect(wrapper.emitted(ACTION_ANIMATED)).toHaveLength(1);
|
119 | });
|
120 | });
|
121 | });
|