Skip to content

Commit fcb8e1d

Browse files
committed
test(input-otp): add tests for basic, color, fill, separators, shape, size
1 parent 2e2eebd commit fcb8e1d

File tree

6 files changed

+434
-0
lines changed

6 files changed

+434
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
4+
/**
5+
* Functionality is the same across modes & directions
6+
*/
7+
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
8+
test.describe(title('input-otp: basic functionality'), () => {
9+
test('should render with 4 input boxes and a default value', async ({ page }) => {
10+
await page.setContent(
11+
`
12+
<ion-input-otp value="12">Description</ion-input-otp>
13+
`,
14+
config
15+
);
16+
17+
const inputBoxes = page.locator('ion-input-otp input');
18+
await expect(inputBoxes).toHaveCount(4);
19+
20+
await expect(inputBoxes.nth(0)).toHaveValue('1');
21+
await expect(inputBoxes.nth(1)).toHaveValue('2');
22+
23+
const inputOtp = page.locator('ion-input-otp');
24+
await expect(inputOtp).toHaveAttribute('value', '12');
25+
});
26+
27+
test('should render with 8 input boxes when length is set to 8 and a default value', async ({ page }) => {
28+
await page.setContent(
29+
`
30+
<ion-input-otp length="8" value="12345678">Description</ion-input-otp>
31+
`,
32+
config
33+
);
34+
35+
const inputBoxes = page.locator('ion-input-otp input');
36+
await expect(inputBoxes).toHaveCount(8);
37+
38+
await expect(inputBoxes.nth(0)).toHaveValue('1');
39+
await expect(inputBoxes.nth(1)).toHaveValue('2');
40+
await expect(inputBoxes.nth(2)).toHaveValue('3');
41+
await expect(inputBoxes.nth(3)).toHaveValue('4');
42+
await expect(inputBoxes.nth(4)).toHaveValue('5');
43+
await expect(inputBoxes.nth(5)).toHaveValue('6');
44+
await expect(inputBoxes.nth(6)).toHaveValue('7');
45+
await expect(inputBoxes.nth(7)).toHaveValue('8');
46+
47+
const inputOtp = page.locator('ion-input-otp');
48+
await expect(inputOtp).toHaveAttribute('value', '12345678');
49+
});
50+
51+
test('should accept numbers only by default', async ({ page }) => {
52+
await page.setContent(
53+
`
54+
<ion-input-otp>Description</ion-input-otp>
55+
`,
56+
config
57+
);
58+
59+
const firstInput = page.locator('ion-input-otp input').first();
60+
await firstInput.focus();
61+
62+
await page.keyboard.type('A2e468');
63+
64+
const inputBoxes = page.locator('ion-input-otp input');
65+
await expect(inputBoxes.nth(0)).toHaveValue('2');
66+
await expect(inputBoxes.nth(1)).toHaveValue('4');
67+
await expect(inputBoxes.nth(2)).toHaveValue('6');
68+
await expect(inputBoxes.nth(3)).toHaveValue('8');
69+
});
70+
71+
test('should accept text and numbers when type is set to text', async ({ page }) => {
72+
await page.setContent(
73+
`
74+
<ion-input-otp type="text">Description</ion-input-otp>
75+
`,
76+
config
77+
);
78+
79+
const firstInput = page.locator('ion-input-otp input').first();
80+
await firstInput.focus();
81+
82+
await page.keyboard.type('A2-B5');
83+
84+
const inputBoxes = page.locator('ion-input-otp input');
85+
await expect(inputBoxes.nth(0)).toHaveValue('A');
86+
await expect(inputBoxes.nth(1)).toHaveValue('2');
87+
await expect(inputBoxes.nth(2)).toHaveValue('B');
88+
await expect(inputBoxes.nth(3)).toHaveValue('5');
89+
});
90+
91+
test('should accept custom pattern when allowed-keys is set', async ({ page }) => {
92+
await page.setContent(
93+
`
94+
<ion-input-otp type="text" allowed-keys="[a-fA-F]">Description</ion-input-otp>
95+
`,
96+
config
97+
);
98+
99+
const firstInput = page.locator('ion-input-otp input').first();
100+
await firstInput.focus();
101+
102+
await page.keyboard.type('AGBZFD');
103+
104+
const inputBoxes = page.locator('ion-input-otp input');
105+
await expect(inputBoxes.nth(0)).toHaveValue('A');
106+
await expect(inputBoxes.nth(1)).toHaveValue('B');
107+
await expect(inputBoxes.nth(2)).toHaveValue('F');
108+
await expect(inputBoxes.nth(3)).toHaveValue('D');
109+
});
110+
});
111+
112+
test.describe(title('input-otp: focus functionality'), () => {
113+
test('should focus the first input box when tabbed to', async ({ page }) => {
114+
await page.setContent(
115+
`
116+
<ion-input-otp>Description</ion-input-otp>
117+
`,
118+
config
119+
);
120+
121+
await page.keyboard.press('Tab');
122+
123+
const firstInput = page.locator('ion-input-otp input').first();
124+
await expect(firstInput).toBeFocused();
125+
});
126+
127+
test('should focus the third input box when tabbed to with a default value of 2 digits', async ({ page }) => {
128+
await page.setContent(
129+
`
130+
<ion-input-otp value="12">Description</ion-input-otp>
131+
`,
132+
config
133+
);
134+
135+
await page.keyboard.press('Tab');
136+
137+
const thirdInput = page.locator('ion-input-otp input').nth(2);
138+
await expect(thirdInput).toBeFocused();
139+
});
140+
141+
test('should focus the last input box when tabbed to with a default value of 4 digits', async ({ page }) => {
142+
await page.setContent(
143+
`
144+
<ion-input-otp value="1234">Description</ion-input-otp>
145+
`,
146+
config
147+
);
148+
149+
await page.keyboard.press('Tab');
150+
151+
const lastInput = page.locator('ion-input-otp input').last();
152+
await expect(lastInput).toBeFocused();
153+
});
154+
});
155+
156+
test.describe(title('input-otp: backspace functionality'), () => {
157+
test('should backspace the first input box when backspace is pressed twice from the 2nd input box and the first input box has a value', async ({
158+
page,
159+
}) => {
160+
await page.setContent(
161+
`
162+
<ion-input-otp value="1">Description</ion-input-otp>
163+
`,
164+
config
165+
);
166+
167+
await page.keyboard.press('Tab');
168+
await page.keyboard.press('Backspace');
169+
await page.keyboard.press('Backspace');
170+
171+
const inputBoxes = page.locator('ion-input-otp input');
172+
await expect(inputBoxes.nth(0)).toHaveValue('');
173+
await expect(inputBoxes.nth(1)).toHaveValue('');
174+
await expect(inputBoxes.nth(2)).toHaveValue('');
175+
await expect(inputBoxes.nth(3)).toHaveValue('');
176+
});
177+
178+
test('should backspace the last input box when backspace is pressed and all values are filled', async ({
179+
page,
180+
}) => {
181+
await page.setContent(
182+
`
183+
<ion-input-otp value="1234">Description</ion-input-otp>
184+
`,
185+
config
186+
);
187+
188+
await page.keyboard.press('Tab');
189+
await page.keyboard.press('Backspace');
190+
191+
const inputBoxes = page.locator('ion-input-otp input');
192+
await expect(inputBoxes.nth(0)).toHaveValue('1');
193+
await expect(inputBoxes.nth(1)).toHaveValue('2');
194+
await expect(inputBoxes.nth(2)).toHaveValue('3');
195+
await expect(inputBoxes.nth(3)).toHaveValue('');
196+
});
197+
198+
test('should backspace the 2nd input box and fill it with the 3rd value when backspace is pressed and 3 values are filled', async ({
199+
page,
200+
}) => {
201+
await page.setContent(
202+
`
203+
<ion-input-otp value="123">Description</ion-input-otp>
204+
`,
205+
config
206+
);
207+
208+
await page.keyboard.press('Tab');
209+
await page.keyboard.press('ArrowLeft');
210+
await page.keyboard.press('ArrowLeft');
211+
await page.keyboard.press('Backspace');
212+
213+
const inputBoxes = page.locator('ion-input-otp input');
214+
await expect(inputBoxes.nth(0)).toHaveValue('1');
215+
await expect(inputBoxes.nth(1)).toHaveValue('3');
216+
await expect(inputBoxes.nth(2)).toHaveValue('');
217+
await expect(inputBoxes.nth(3)).toHaveValue('');
218+
});
219+
});
220+
});
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
4+
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
5+
test.describe(title('input-otp: color'), () => {
6+
// Test all colors with all fills
7+
['outline', 'solid'].forEach((fill) => {
8+
test(`color with ${fill} fill should not have visual regressions`, async ({ page }) => {
9+
await page.setContent(
10+
`
11+
<div id="container">
12+
<ion-input-otp color="primary" fill="${fill}" value="12"></ion-input-otp>
13+
<ion-input-otp color="secondary" fill="${fill}" value="12"></ion-input-otp>
14+
<ion-input-otp color="tertiary" fill="${fill}" value="12"></ion-input-otp>
15+
<ion-input-otp color="success" fill="${fill}" value="12"></ion-input-otp>
16+
<ion-input-otp color="warning" fill="${fill}" value="12"></ion-input-otp>
17+
<ion-input-otp color="danger" fill="${fill}" value="12"></ion-input-otp>
18+
<ion-input-otp color="light" fill="${fill}" value="12"></ion-input-otp>
19+
<ion-input-otp color="medium" fill="${fill}" value="12"></ion-input-otp>
20+
<ion-input-otp color="dark" fill="${fill}" value="12"></ion-input-otp>
21+
</div>
22+
`,
23+
config
24+
);
25+
26+
const container = page.locator('#container');
27+
await expect(container).toHaveScreenshot(screenshot(`input-otp-color-${fill}`));
28+
});
29+
test(`disabled color with ${fill} fill should not have visual regressions`, async ({ page }) => {
30+
await page.setContent(
31+
`npx
32+
<div id="container">
33+
<ion-input-otp color="primary" fill="${fill}" value="12" disabled></ion-input-otp>
34+
<ion-input-otp color="secondary" fill="${fill}" value="12" disabled></ion-input-otp>
35+
<ion-input-otp color="tertiary" fill="${fill}" value="12" disabled></ion-input-otp>
36+
<ion-input-otp color="success" fill="${fill}" value="12" disabled></ion-input-otp>
37+
<ion-input-otp color="warning" fill="${fill}" value="12" disabled></ion-input-otp>
38+
<ion-input-otp color="danger" fill="${fill}" value="12" disabled></ion-input-otp>
39+
<ion-input-otp color="light" fill="${fill}" value="12" disabled></ion-input-otp>
40+
<ion-input-otp color="medium" fill="${fill}" value="12" disabled></ion-input-otp>
41+
<ion-input-otp color="dark" fill="${fill}" value="12" disabled></ion-input-otp>
42+
</div>
43+
`,
44+
config
45+
);
46+
47+
const container = page.locator('#container');
48+
await expect(container).toHaveScreenshot(screenshot(`input-otp-color-${fill}-disabled`));
49+
});
50+
test(`readonly color with ${fill} fill should not have visual regressions`, async ({ page }) => {
51+
await page.setContent(
52+
`
53+
<div id="container">
54+
<ion-input-otp color="primary" fill="${fill}" value="12" readonly></ion-input-otp>
55+
<ion-input-otp color="secondary" fill="${fill}" value="12" readonly></ion-input-otp>
56+
<ion-input-otp color="tertiary" fill="${fill}" value="12" readonly></ion-input-otp>
57+
<ion-input-otp color="success" fill="${fill}" value="12" readonly></ion-input-otp>
58+
<ion-input-otp color="warning" fill="${fill}" value="12" readonly></ion-input-otp>
59+
<ion-input-otp color="danger" fill="${fill}" value="12" readonly></ion-input-otp>
60+
<ion-input-otp color="light" fill="${fill}" value="12" readonly></ion-input-otp>
61+
<ion-input-otp color="medium" fill="${fill}" value="12" readonly></ion-input-otp>
62+
<ion-input-otp color="dark" fill="${fill}" value="12" readonly></ion-input-otp>
63+
</div>
64+
`,
65+
config
66+
);
67+
68+
const container = page.locator('#container');
69+
await expect(container).toHaveScreenshot(screenshot(`input-otp-color-${fill}-readonly`));
70+
});
71+
});
72+
});
73+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
4+
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
5+
test.describe(title('input-otp: fill'), () => {
6+
['outline', 'solid'].forEach((fill) => {
7+
test(`${fill} fill should not have visual regressions`, async ({ page }) => {
8+
await page.setContent(
9+
`
10+
<ion-input-otp fill="${fill}" value="12">Description</ion-input-otp>
11+
`,
12+
config
13+
);
14+
15+
const inputOtp = page.locator('ion-input-otp');
16+
await expect(inputOtp).toHaveScreenshot(screenshot(`input-otp-${fill}`));
17+
});
18+
test(`disabled should not have visual regressions`, async ({ page }) => {
19+
await page.setContent(
20+
`
21+
<ion-input-otp fill="${fill}" value="12" disabled>Description</ion-input-otp>
22+
`,
23+
config
24+
);
25+
26+
const inputOtp = page.locator('ion-input-otp');
27+
await expect(inputOtp).toHaveScreenshot(screenshot(`input-otp-${fill}-disabled`));
28+
});
29+
test(`readonly should not have visual regressions`, async ({ page }) => {
30+
await page.setContent(
31+
`
32+
<ion-input-otp fill="${fill}" value="12" readonly>Description</ion-input-otp>
33+
`,
34+
config
35+
);
36+
37+
const inputOtp = page.locator('ion-input-otp');
38+
await expect(inputOtp).toHaveScreenshot(screenshot(`input-otp-${fill}-readonly`));
39+
});
40+
});
41+
});
42+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
4+
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
5+
test.describe(title('input-otp: separators'), () => {
6+
// Test separators with all sizes
7+
['small', 'medium', 'large'].forEach((size) => {
8+
test(`one separator with ${size} size should not have visual regressions`, async ({ page }) => {
9+
await page.setContent(
10+
`
11+
<ion-input-otp size="${size}" value="12" separators="1">Description</ion-input-otp>
12+
`,
13+
config
14+
);
15+
16+
const inputOtp = page.locator('ion-input-otp');
17+
await expect(inputOtp).toHaveScreenshot(screenshot(`input-otp-separators-one-${size}`));
18+
});
19+
20+
test(`two separators with ${size} size should not have visual regressions`, async ({ page }) => {
21+
await page.setContent(
22+
`
23+
<ion-input-otp size="${size}" value="12" length="6" separators="2,4">Description</ion-input-otp>
24+
`,
25+
config
26+
);
27+
28+
const inputOtp = page.locator('ion-input-otp');
29+
await expect(inputOtp).toHaveScreenshot(screenshot(`input-otp-separators-two-${size}`));
30+
});
31+
32+
test(`all separators with ${size} size should not have visual regressions`, async ({ page }) => {
33+
await page.setContent(
34+
`
35+
<ion-input-otp size="${size}" value="12" separators="all">Description</ion-input-otp>
36+
`,
37+
config
38+
);
39+
40+
const inputOtp = page.locator('ion-input-otp');
41+
await expect(inputOtp).toHaveScreenshot(screenshot(`input-otp-separators-all-${size}`));
42+
});
43+
});
44+
});
45+
});

0 commit comments

Comments
 (0)