Skip to content

Commit d469079

Browse files
author
Kubit
committed
Add InputDigitSequence component
1 parent faec08c commit d469079

22 files changed

+1679
-0
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
import userEvent from '@testing-library/user-event';
2+
3+
import { act, fireEvent } from '@testing-library/react';
4+
import * as React from 'react';
5+
6+
import { axe } from 'jest-axe';
7+
8+
import { renderProvider } from '@/tests/renderProvider/renderProvider.utility';
9+
import { windowMatchMedia } from '@/tests/windowMatchMedia';
10+
import { ROLES } from '@/types';
11+
12+
import { InputDigitSequence } from '../index';
13+
14+
const MOCK_PROPS = {
15+
variant: 'DEFAULT',
16+
title: { content: 'Label' },
17+
actionButton: {
18+
variant: 'ACTION_SECONDARY_ALT',
19+
icon: { icon: 'CARD_DETAIL' },
20+
content: 'Show code',
21+
['aria-label']: 'aria-label test',
22+
},
23+
errorText: { content: 'This is the error text' },
24+
errorIcon: { icon: 'ERROR', altText: 'Alt text error icon' },
25+
inputsArray: [
26+
{ blockedBySystem: false, ['aria-label']: 'input1' },
27+
{ blockedBySystem: false, ['aria-label']: 'input2' },
28+
{ blockedBySystem: true, ['aria-label']: 'input3' },
29+
{ blockedBySystem: true, ['aria-label']: 'input4' },
30+
{ blockedBySystem: false, ['aria-label']: 'input5' },
31+
{ blockedBySystem: true, ['aria-label']: 'input6' },
32+
{ blockedBySystem: true, ['aria-label']: 'input7' },
33+
{ blockedBySystem: true, ['aria-label']: 'input8' },
34+
],
35+
};
36+
37+
window.matchMedia = windowMatchMedia();
38+
39+
describe('InputDigitSequence component', () => {
40+
it('Should render InputDigitSequence', async () => {
41+
const { getByText, container } = renderProvider(<InputDigitSequence {...MOCK_PROPS} />);
42+
43+
expect(getByText('Label')).toBeInTheDocument();
44+
45+
const results = await axe(container);
46+
expect(container).toHTMLValidate();
47+
expect(results).toHaveNoViolations();
48+
});
49+
50+
it('Could have a help text', async () => {
51+
const { getByText, container } = renderProvider(
52+
<InputDigitSequence {...MOCK_PROPS} helpText={{ content: 'Help text' }} />
53+
);
54+
55+
expect(getByText('Help text')).toBeInTheDocument();
56+
57+
const results = await axe(container);
58+
expect(container).toHTMLValidate();
59+
expect(results).toHaveNoViolations();
60+
});
61+
62+
it('Could have a tooltip icon', async () => {
63+
const { getByAltText, container } = renderProvider(
64+
<InputDigitSequence
65+
{...MOCK_PROPS}
66+
tooltipIcon={{ icon: 'ICON_PLACEHOLDER', altText: 'Tooltip icon' }}
67+
/>
68+
);
69+
70+
expect(getByAltText('Tooltip icon')).toBeInTheDocument();
71+
72+
const results = await axe(container);
73+
expect(container).toHTMLValidate();
74+
expect(results).toHaveNoViolations();
75+
});
76+
77+
it('Could have a tooltip allong with the icon', async () => {
78+
const { getByAltText, container } = renderProvider(
79+
<InputDigitSequence
80+
{...MOCK_PROPS}
81+
tooltip={{
82+
variant: 'DEFAULT',
83+
title: { content: 'Tooltip title' },
84+
tooltipAsModal: false,
85+
}}
86+
tooltipIcon={{ icon: 'ICON_PLACEHOLDER', altText: 'Tooltip icon' }}
87+
/>
88+
);
89+
90+
expect(getByAltText('Tooltip icon')).toBeInTheDocument();
91+
92+
const results = await axe(container);
93+
expect(container).toHTMLValidate();
94+
expect(results).toHaveNoViolations();
95+
});
96+
97+
it('When animated, input-container-animated container is shown', () => {
98+
const { container } = renderProvider(<InputDigitSequence {...MOCK_PROPS} animated />);
99+
100+
const element = container.querySelector('[data-id="input-container-animated"]');
101+
expect(element).toBeInTheDocument();
102+
});
103+
104+
it('OnClick actionButton', async () => {
105+
const callbackOnClickActionButton = jest.fn();
106+
const { getByRole, container } = renderProvider(
107+
<InputDigitSequence
108+
{...MOCK_PROPS}
109+
actionButton={{ ...MOCK_PROPS.actionButton, onClick: callbackOnClickActionButton }}
110+
/>
111+
);
112+
113+
const triggerButton = getByRole('button', { name: MOCK_PROPS.actionButton['aria-label'] });
114+
await act(async () => {
115+
fireEvent.click(triggerButton);
116+
});
117+
118+
expect(callbackOnClickActionButton).toHaveBeenCalled();
119+
const results = await axe(container);
120+
expect(container).toHTMLValidate();
121+
expect(results).toHaveNoViolations();
122+
});
123+
124+
it('Write input sequence going to next input available after write and called callback', async () => {
125+
const callbackOnChangeInput = jest.fn();
126+
const { getByLabelText, container } = renderProvider(
127+
<InputDigitSequence {...MOCK_PROPS} onInputChange={callbackOnChangeInput} />
128+
);
129+
130+
const input1 = getByLabelText('input1') as HTMLInputElement;
131+
await act(async () => {
132+
await userEvent.type(input1, '789');
133+
});
134+
135+
const input2 = getByLabelText('input2') as HTMLInputElement;
136+
const input3 = getByLabelText('input3') as HTMLInputElement;
137+
const input4 = getByLabelText('input4') as HTMLInputElement;
138+
const input5 = getByLabelText('input5') as HTMLInputElement;
139+
const input6 = getByLabelText('input6') as HTMLInputElement;
140+
const input7 = getByLabelText('input7') as HTMLInputElement;
141+
const input8 = getByLabelText('input8') as HTMLInputElement;
142+
143+
expect(input1.value).toBe('7');
144+
expect(input2.value).toBe('8');
145+
expect(input3.value).toBe('');
146+
expect(input4.value).toBe('');
147+
expect(input5.value).toBe('9');
148+
expect(input6.value).toBe('');
149+
expect(input7.value).toBe('');
150+
expect(input8.value).toBe('');
151+
152+
expect(callbackOnChangeInput).toHaveBeenCalled();
153+
154+
const results = await axe(container);
155+
expect(container).toHTMLValidate();
156+
expect(results).toHaveNoViolations();
157+
});
158+
159+
it('Write input sequence going to next input available after write and called callback with showDigitAfterWrite=false', async () => {
160+
const callbackOnChangeInput = jest.fn();
161+
const { getByLabelText, container } = renderProvider(
162+
<InputDigitSequence
163+
{...MOCK_PROPS}
164+
showDigitAfterWrite={false}
165+
onInputChange={callbackOnChangeInput}
166+
/>
167+
);
168+
169+
const input1 = getByLabelText('input1') as HTMLInputElement;
170+
await act(async () => {
171+
await userEvent.type(input1, '789');
172+
});
173+
174+
const input2 = getByLabelText('input2') as HTMLInputElement;
175+
const input3 = getByLabelText('input3') as HTMLInputElement;
176+
const input4 = getByLabelText('input4') as HTMLInputElement;
177+
const input5 = getByLabelText('input5') as HTMLInputElement;
178+
const input6 = getByLabelText('input6') as HTMLInputElement;
179+
const input7 = getByLabelText('input7') as HTMLInputElement;
180+
const input8 = getByLabelText('input8') as HTMLInputElement;
181+
182+
expect(input1.value).toBe('7');
183+
expect(input2.value).toBe('8');
184+
expect(input3.value).toBe('');
185+
expect(input4.value).toBe('');
186+
expect(input5.value).toBe('9');
187+
expect(input6.value).toBe('');
188+
expect(input7.value).toBe('');
189+
expect(input8.value).toBe('');
190+
191+
expect(callbackOnChangeInput).toHaveBeenCalled();
192+
193+
const results = await axe(container);
194+
expect(container).toHTMLValidate();
195+
expect(results).toHaveNoViolations();
196+
});
197+
198+
it('InputDigitSequence error', async () => {
199+
const { getByRole, queryByText, container } = renderProvider(
200+
<InputDigitSequence {...MOCK_PROPS} error={true} />
201+
);
202+
203+
const error = queryByText(MOCK_PROPS.errorText.content);
204+
const errorIcon = getByRole(ROLES.IMG, { name: MOCK_PROPS.errorIcon.altText });
205+
206+
expect(error).toBeInTheDocument();
207+
expect(errorIcon).toBeInTheDocument();
208+
209+
const results = await axe(container);
210+
expect(container).toHTMLValidate();
211+
expect(results).toHaveNoViolations();
212+
});
213+
214+
it('InputDigitSequence disabled', async () => {
215+
const { getByLabelText, container } = renderProvider(
216+
<InputDigitSequence {...MOCK_PROPS} disabled={true} />
217+
);
218+
219+
const input1 = getByLabelText('input1') as HTMLInputElement;
220+
await act(async () => {
221+
await userEvent.type(input1, '789');
222+
});
223+
224+
const input2 = getByLabelText('input2') as HTMLInputElement;
225+
const input3 = getByLabelText('input3') as HTMLInputElement;
226+
expect(input1.value).toBe('');
227+
expect(input2.value).toBe('');
228+
expect(input3.value).toBe('');
229+
230+
const results = await axe(container);
231+
expect(container).toHTMLValidate();
232+
expect(results).toHaveNoViolations();
233+
});
234+
});
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { act, renderHook } from '@testing-library/react-hooks';
2+
3+
import { useAnimation } from '../hooks';
4+
5+
describe('useAnimation', () => {
6+
let rootMockElement;
7+
let inputWrapperMockElement;
8+
let animationContainer;
9+
let innerAnimationContainerElement;
10+
let originalContainer;
11+
let innerOriginalContainerElement;
12+
13+
beforeEach(() => {
14+
rootMockElement?.remove();
15+
inputWrapperMockElement?.remove();
16+
animationContainer?.remove();
17+
innerAnimationContainerElement?.remove();
18+
originalContainer?.remove();
19+
innerOriginalContainerElement?.remove();
20+
21+
rootMockElement = document.createElement('div');
22+
inputWrapperMockElement = document.createElement('div');
23+
animationContainer = document.createElement('div');
24+
animationContainer.setAttribute('data-id', 'input-container-animated');
25+
innerAnimationContainerElement = document.createElement('div');
26+
Object.defineProperty(innerAnimationContainerElement, 'clientWidth', {
27+
get: () => 500,
28+
});
29+
originalContainer = document.createElement('div');
30+
originalContainer.setAttribute('data-id', 'input-container');
31+
innerOriginalContainerElement = document.createElement('div');
32+
Object.defineProperty(innerOriginalContainerElement, 'clientWidth', {
33+
get: () => 500,
34+
});
35+
36+
rootMockElement.appendChild(inputWrapperMockElement);
37+
inputWrapperMockElement.appendChild(animationContainer);
38+
inputWrapperMockElement.appendChild(originalContainer);
39+
animationContainer.appendChild(innerAnimationContainerElement);
40+
originalContainer.appendChild(innerOriginalContainerElement);
41+
});
42+
43+
it('When no animation nothing happens', () => {
44+
const { result } = renderHook(() => useAnimation({ animated: false }));
45+
46+
// Call the ref callback with the mock element
47+
act(() => {
48+
(result.current.ref as (instance: HTMLDivElement | null) => void)(
49+
rootMockElement as HTMLDivElement
50+
);
51+
});
52+
53+
// Fire transitionend event
54+
act(() => {
55+
animationContainer.dispatchEvent(new Event('transitionend'));
56+
});
57+
58+
// Check if boxesAnimationDone is updated
59+
expect(result.current.boxesAnimationDone).toBe(false);
60+
61+
// Fire animationend event
62+
act(() => {
63+
animationContainer.dispatchEvent(new Event('animationend'));
64+
});
65+
66+
// Check if labelAnimationDone is updated
67+
expect(result.current.labelAnimationDone).toBe(false);
68+
});
69+
70+
it('When no ref nothing happens', () => {
71+
const { result } = renderHook(() => useAnimation({ animated: true }));
72+
73+
// Call the ref callback with the mock element
74+
act(() => {
75+
(result.current.ref as (instance: HTMLDivElement | null) => void)(null);
76+
});
77+
78+
// Fire transitionend event
79+
act(() => {
80+
animationContainer.dispatchEvent(new Event('transitionend'));
81+
});
82+
83+
// Check if boxesAnimationDone is updated
84+
expect(result.current.boxesAnimationDone).toBe(false);
85+
86+
// Fire animationend event
87+
act(() => {
88+
animationContainer.dispatchEvent(new Event('animationend'));
89+
});
90+
91+
// Check if labelAnimationDone is updated
92+
expect(result.current.labelAnimationDone).toBe(false);
93+
});
94+
95+
it('updates boxesAnimationDone and labelAnimationDone when transitionend and animationend events are fired', () => {
96+
const { result } = renderHook(() => useAnimation({ animated: true }));
97+
98+
// Call the ref callback with the mock element
99+
act(() => {
100+
(result.current.ref as (instance: HTMLDivElement | null) => void)(
101+
rootMockElement as HTMLDivElement
102+
);
103+
});
104+
105+
// Fire transitionend event
106+
act(() => {
107+
animationContainer.dispatchEvent(new Event('transitionend'));
108+
// this second event should not change the state
109+
animationContainer.dispatchEvent(new Event('transitionend'));
110+
});
111+
112+
// Check if boxesAnimationDone is updated
113+
expect(result.current.boxesAnimationDone).toBe(true);
114+
115+
// Fire animationend event
116+
act(() => {
117+
animationContainer.dispatchEvent(new Event('animationend'));
118+
// this second event should not change the state
119+
animationContainer.dispatchEvent(new Event('animationend'));
120+
});
121+
122+
// Check if labelAnimationDone is updated
123+
expect(result.current.labelAnimationDone).toBe(true);
124+
});
125+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './inputDigitSequenceHelpText';
2+
export * from './inputDigitSquenceTooltip';
3+
export * from './inputDigit';

0 commit comments

Comments
 (0)