@@ -5,60 +5,293 @@ test.describe('Form', () => {
55    await  page . goto ( '/lazy/form' ) ; 
66  } ) ; 
77
8-   test ( 'should have form control initial value' ,  async  ( {  page } )  =>  { 
9-     await  expect ( page . locator ( 'ion-input.required input' ) ) . toHaveValue ( '' ) ; 
8+   test . describe ( 'status updates' ,  ( )  =>  { 
9+     test ( 'should update Ionic form classes when calling form methods programmatically' ,  async  ( {  page } )  =>  { 
10+       await  page . locator ( '#input-touched' ) . click ( ) ; 
11+       await  expect ( page . locator ( '#touched-input-test' ) ) . toHaveClass ( / i o n - t o u c h e d / ) ; 
12+       await  page . locator ( '#input-otp-touched' ) . click ( ) ; 
13+       await  expect ( page . locator ( '#touched-input-otp-number-test' ) ) . toHaveClass ( / i o n - t o u c h e d / ) ; 
14+     } ) ; 
15+ 
16+     test ( 'markAllAsTouched should apply .ion-touched to nearest ion-item' ,  async  ( {  page } )  =>  { 
17+       await  page . locator ( '#mark-all-touched-button' ) . click ( ) ; 
18+       const  items  =  page . locator ( 'form ion-item' ) ; 
19+       const  count  =  await  items . count ( ) ; 
20+       for  ( let  i  =  0 ;  i  <  count ;  i ++ )  { 
21+         await  expect ( items . nth ( i ) ) . toHaveClass ( / i o n - t o u c h e d / ) ; 
22+       } 
23+     } ) ; 
1024  } ) ; 
1125
12-   test ( 'should reflect Ionic form control status classes' ,  async  ( {  page } )  =>  { 
13-     // Control is initially invalid 
14-     await  expect ( page . locator ( 'ion-input.required' ) ) . toHaveClass ( / i o n - i n v a l i d / ) ; 
15-     await  expect ( page . locator ( 'ion-input.required' ) ) . toHaveClass ( / i o n - p r i s t i n e / ) ; 
16-     await  expect ( page . locator ( 'ion-input.required' ) ) . toHaveClass ( / i o n - u n t o u c h e d / ) ; 
26+   test . describe ( 'change' ,  ( )  =>  { 
27+     test ( 'should have default values' ,  async  ( {  page } )  =>  { 
28+       await  testStatus ( page ,  'INVALID' ) ; 
29+       await  expect ( page . locator ( '#submit' ) ) . toHaveText ( 'false' ) ; 
30+       await  testData ( page ,  { 
31+         datetime : '2010-08-20' , 
32+         select : null , 
33+         toggle : false , 
34+         input : '' , 
35+         input2 : 'Default Value' , 
36+         inputMin : 1 , 
37+         inputMax : 1 , 
38+         inputOtp : null , 
39+         inputOtpText : '' , 
40+         inputOtp2 : 1234 , 
41+         checkbox : false , 
42+         radio : null 
43+       } ) ; 
44+     } ) ; 
1745
18-     // Fill the input to make it valid 
19-     await  page . locator ( 'ion-input.required input' ) . fill ( 'Some value' ) ; 
20-     await  page . locator ( 'ion-input.required input' ) . blur ( ) ; 
46+     test ( 'should become valid' ,   async   ( {  page  } )   =>   { 
47+        await  page . locator ( 'ion-input.required input' ) . fill ( 'Some value' ) ; 
48+        await  page . locator ( 'ion-input.required input' ) . blur ( ) ; 
2149
22-     await  expect ( page . locator ( 'ion-input.required' ) ) . toHaveClass ( / i o n - v a l i d / ) ; 
23-     await  expect ( page . locator ( 'ion-input.required' ) ) . toHaveClass ( / i o n - d i r t y / ) ; 
24-     await  expect ( page . locator ( 'ion-input.required' ) ) . toHaveClass ( / i o n - t o u c h e d / ) ; 
25-   } ) ; 
50+       // Test number OTP input 
51+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 0 ) . fill ( '5' ) ; 
52+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 1 ) . fill ( '6' ) ; 
53+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 2 ) . fill ( '7' ) ; 
54+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 3 ) . fill ( '8' ) ; 
55+       await  page . locator ( '#touched-input-otp-number-test input' ) . last ( ) . focus ( ) ; 
56+       await  page . locator ( '#touched-input-otp-number-test input' ) . last ( ) . blur ( ) ; 
2657
27-   test ( 'should become valid when filled' ,  async  ( {  page } )  =>  { 
28-     await  page . locator ( 'ion-input.required input' ) . fill ( 'Some value' ) ; 
29-     await  page . locator ( 'ion-input.required input' ) . blur ( ) ; 
58+       // Test text OTP input 
59+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 0 ) . fill ( 'A' ) ; 
60+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 1 ) . fill ( 'B' ) ; 
61+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 2 ) . fill ( 'C' ) ; 
62+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 3 ) . fill ( 'D' ) ; 
63+       await  page . locator ( '#touched-input-otp-text-test input' ) . last ( ) . focus ( ) ; 
64+       await  page . locator ( '#touched-input-otp-text-test input' ) . last ( ) . blur ( ) ; 
3065
31-     // Test number OTP input 
32-     await  page . locator ( 'ion-input-otp input' ) . nth ( 0 ) . fill ( '1' ) ; 
33-     await  page . locator ( 'ion-input-otp input' ) . nth ( 1 ) . fill ( '2' ) ; 
34-     await  page . locator ( 'ion-input-otp input' ) . nth ( 2 ) . fill ( '3' ) ; 
35-     await  page . locator ( 'ion-input-otp input' ) . nth ( 3 ) . fill ( '4' ) ; 
66+       await  testStatus ( page ,  'INVALID' ) ; 
3667
37-     // Check that the OTP input is valid 
38-     await  expect ( page . locator ( '#touched-input-otp-number-test' ) ) . toHaveClass ( / i o n - v a l i d / ) ; 
39-   } ) ; 
68+       await  page . locator ( 'ion-select' ) . click ( ) ; 
69+       await  expect ( page . locator ( 'ion-alert' ) ) . toBeVisible ( ) ; 
70+       // NES option 
71+       await  page . locator ( 'ion-alert .alert-radio-button' ) . nth ( 1 ) . click ( ) ; 
72+       // Click confirm button 
73+       await  page . locator ( 'ion-alert .alert-button:not(.alert-button-role-cancel)' ) . click ( ) ; 
74+ 
75+       await  testStatus ( page ,  'VALID' ) ; 
76+ 
77+       await  testData ( page ,  { 
78+         datetime : '2010-08-20' , 
79+         select : 'nes' , 
80+         toggle : false , 
81+         input : 'Some value' , 
82+         input2 : 'Default Value' , 
83+         inputMin : 1 , 
84+         inputMax : 1 , 
85+         inputOtp : 5678 , 
86+         inputOtpText : 'ABCD' , 
87+         inputOtp2 : 1234 , 
88+         checkbox : false , 
89+         radio : null 
90+       } ) ; 
91+     } ) ; 
92+ 
93+     test ( 'ion-toggle should change' ,  async  ( {  page } )  =>  { 
94+       await  page . locator ( 'form ion-toggle' ) . click ( ) ; 
95+       await  testData ( page ,  { 
96+         datetime : '2010-08-20' , 
97+         select : null , 
98+         toggle : true , 
99+         input : '' , 
100+         input2 : 'Default Value' , 
101+         inputMin : 1 , 
102+         inputMax : 1 , 
103+         inputOtp : null , 
104+         inputOtpText : '' , 
105+         inputOtp2 : 1234 , 
106+         checkbox : false , 
107+         radio : null 
108+       } ) ; 
109+     } ) ; 
110+ 
111+     test ( 'ion-checkbox should change' ,  async  ( {  page } )  =>  { 
112+       await  page . locator ( 'ion-checkbox' ) . click ( ) ; 
113+       await  testData ( page ,  { 
114+         datetime : '2010-08-20' , 
115+         select : null , 
116+         toggle : false , 
117+         input : '' , 
118+         input2 : 'Default Value' , 
119+         inputMin : 1 , 
120+         inputMax : 1 , 
121+         inputOtp : null , 
122+         inputOtpText : '' , 
123+         inputOtp2 : 1234 , 
124+         checkbox : true , 
125+         radio : null 
126+       } ) ; 
127+     } ) ; 
128+ 
129+     test ( 'ion-radio should change' ,  async  ( {  page } )  =>  { 
130+       await  page . locator ( 'ion-radio' ) . click ( ) ; 
131+       await  testData ( page ,  { 
132+         datetime : '2010-08-20' , 
133+         select : null , 
134+         toggle : false , 
135+         input : '' , 
136+         input2 : 'Default Value' , 
137+         inputMin : 1 , 
138+         inputMax : 1 , 
139+         inputOtp : null , 
140+         inputOtpText : '' , 
141+         inputOtp2 : 1234 , 
142+         checkbox : false , 
143+         radio : 'nes' , 
144+       } ) ; 
145+     } ) ; 
146+ 
147+     test ( 'ion-input-otp should change' ,  async  ( {  page } )  =>  { 
148+       // Test number OTP input 
149+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 0 ) . fill ( '5' ) ; 
150+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 1 ) . fill ( '6' ) ; 
151+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 2 ) . fill ( '7' ) ; 
152+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 3 ) . fill ( '8' ) ; 
153+       await  page . locator ( '#touched-input-otp-number-test input' ) . last ( ) . focus ( ) ; 
154+       await  page . locator ( '#touched-input-otp-number-test input' ) . last ( ) . blur ( ) ; 
155+ 
156+       // Test text OTP input 
157+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 0 ) . fill ( 'A' ) ; 
158+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 1 ) . fill ( 'B' ) ; 
159+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 2 ) . fill ( 'C' ) ; 
160+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 3 ) . fill ( 'D' ) ; 
161+       await  page . locator ( '#touched-input-otp-text-test input' ) . last ( ) . focus ( ) ; 
162+       await  page . locator ( '#touched-input-otp-text-test input' ) . last ( ) . blur ( ) ; 
163+ 
164+       await  testData ( page ,  { 
165+         datetime : '2010-08-20' , 
166+         select : null , 
167+         toggle : false , 
168+         input : '' , 
169+         input2 : 'Default Value' , 
170+         inputMin : 1 , 
171+         inputMax : 1 , 
172+         inputOtp : 5678 , 
173+         inputOtpText : 'ABCD' , 
174+         inputOtp2 : 1234 , 
175+         checkbox : false , 
176+         radio : null 
177+       } ) ; 
178+     } ) ; 
40179
41-   test ( 'ion-input should error with min set' ,  async  ( {  page } )  =>  { 
42-     const  control  =  page . locator ( 'form ion-input[formControlName="inputMin"]' ) ; 
180+     test ( 'should submit' ,  async  ( {  page } )  =>  { 
181+       await  page . locator ( '#set-values' ) . click ( ) ; 
182+       await  page . locator ( '#submit-button' ) . click ( ) ; 
183+       await  expect ( page . locator ( '#submit' ) ) . toHaveText ( 'true' ) ; 
184+     } ) ; 
43185
44-     // Control is initially valid 
45-     await  expect ( control ) . toHaveClass ( / n g - v a l i d / ) ; 
186+     test ( 'ion-input-otp should validate both number and text types' ,  async  ( {  page } )  =>  { 
187+       // Test number OTP validation 
188+       await  expect ( page . locator ( '#touched-input-otp-number-test' ) ) . toHaveClass ( / n g - i n v a l i d / ) ; 
189+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 0 ) . fill ( '5' ) ; 
190+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 1 ) . fill ( '6' ) ; 
191+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 2 ) . fill ( '7' ) ; 
192+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 3 ) . fill ( '8' ) ; 
193+       await  page . locator ( '#touched-input-otp-number-test input' ) . last ( ) . focus ( ) ; 
194+       await  page . locator ( '#touched-input-otp-number-test input' ) . last ( ) . blur ( ) ; 
195+       await  expect ( page . locator ( '#touched-input-otp-number-test' ) ) . toHaveClass ( / n g - v a l i d / ) ; 
46196
47-     await  control . locator ( 'input' ) . fill ( '0' ) ; 
48-     await  control . locator ( 'input' ) . blur ( ) ; 
197+       // Test text OTP validation 
198+       await  expect ( page . locator ( '#touched-input-otp-text-test' ) ) . toHaveClass ( / n g - i n v a l i d / ) ; 
199+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 0 ) . fill ( 'A' ) ; 
200+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 1 ) . fill ( 'B' ) ; 
201+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 2 ) . fill ( 'C' ) ; 
202+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 3 ) . fill ( 'D' ) ; 
203+       await  page . locator ( '#touched-input-otp-text-test input' ) . last ( ) . focus ( ) ; 
204+       await  page . locator ( '#touched-input-otp-text-test input' ) . last ( ) . blur ( ) ; 
205+       await  expect ( page . locator ( '#touched-input-otp-text-test' ) ) . toHaveClass ( / n g - v a l i d / ) ; 
206+     } ) ; 
49207
50-     await  expect ( control ) . toHaveClass ( / n g - i n v a l i d / ) ; 
208+     test ( 'ion-input-otp should remain invalid when partially filled' ,  async  ( {  page } )  =>  { 
209+       // Test number OTP with only first digit 
210+       await  expect ( page . locator ( '#touched-input-otp-number-test' ) ) . toHaveClass ( / n g - i n v a l i d / ) ; 
211+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 0 ) . fill ( '5' ) ; 
212+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 1 ) . focus ( ) ; 
213+       await  page . locator ( '#touched-input-otp-number-test input' ) . nth ( 1 ) . blur ( ) ; 
214+       await  expect ( page . locator ( '#touched-input-otp-number-test' ) ) . toHaveClass ( / n g - i n v a l i d / ) ; 
215+ 
216+       // Test text OTP with only first character 
217+       await  expect ( page . locator ( '#touched-input-otp-text-test' ) ) . toHaveClass ( / n g - i n v a l i d / ) ; 
218+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 0 ) . fill ( 'A' ) ; 
219+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 1 ) . focus ( ) ; 
220+       await  page . locator ( '#touched-input-otp-text-test input' ) . nth ( 1 ) . blur ( ) ; 
221+       await  expect ( page . locator ( '#touched-input-otp-text-test' ) ) . toHaveClass ( / n g - i n v a l i d / ) ; 
222+ 
223+       // Verify form status is still invalid 
224+       await  testStatus ( page ,  'INVALID' ) ; 
225+     } ) ; 
51226  } ) ; 
52227
53-   test ( 'ion-input should error with max set' ,  async  ( {  page } )  =>  { 
54-     const  control  =  page . locator ( 'form ion-input[formControlName="inputMax"]' ) ; 
228+   test . describe ( 'blur' ,  ( )  =>  { 
229+     test ( 'ion-toggle should change only after blur' ,  async  ( {  page } )  =>  { 
230+       await  page . locator ( 'form ion-toggle' ) . click ( ) ; 
231+       await  testData ( page ,  { 
232+         datetime : '2010-08-20' , 
233+         select : null , 
234+         toggle : true , 
235+         input : '' , 
236+         input2 : 'Default Value' , 
237+         inputMin : 1 , 
238+         inputMax : 1 , 
239+         inputOtp : null , 
240+         inputOtpText : '' , 
241+         inputOtp2 : 1234 , 
242+         checkbox : false , 
243+         radio : null 
244+       } ) ; 
245+       await  page . locator ( 'ion-checkbox' ) . click ( ) ; 
246+       await  testData ( page ,  { 
247+         datetime : '2010-08-20' , 
248+         select : null , 
249+         toggle : true , 
250+         input : '' , 
251+         input2 : 'Default Value' , 
252+         inputMin : 1 , 
253+         inputMax : 1 , 
254+         inputOtp : null , 
255+         inputOtpText : '' , 
256+         inputOtp2 : 1234 , 
257+         checkbox : true , 
258+         radio : null 
259+       } ) ; 
260+     } ) ; 
261+   } ) ; 
262+ 
263+   test . describe ( 'validators' ,  ( )  =>  { 
264+     test ( 'ion-input should error with min set' ,  async  ( {  page } )  =>  { 
265+       const  control  =  page . locator ( 'form ion-input[formControlName="inputMin"]' ) ; 
266+ 
267+       await  expect ( control ) . toHaveClass ( / n g - v a l i d / ) ; 
55268
56-     // Control is initially valid 
57-     await  expect ( control ) . toHaveClass ( / n g - v a l i d / ) ; 
269+        await   control . locator ( 'input' ) . fill ( '0' ) ; 
270+        await  control . locator ( 'input' ) . blur ( ) ; 
58271
59-     await  control . locator ( 'input' ) . fill ( '2' ) ; 
60-     await   control . locator ( 'input' ) . blur ( ) ; 
272+        await  expect ( control ) . toHaveClass ( / n g - i n v a l i d / ) ; 
273+     } ) ; 
61274
62-     await  expect ( control ) . toHaveClass ( / n g - i n v a l i d / ) ; 
275+     test ( 'ion-input should error with max set' ,  async  ( {  page } )  =>  { 
276+       const  control  =  page . locator ( 'form ion-input[formControlName="inputMax"]' ) ; 
277+ 
278+       await  expect ( control ) . toHaveClass ( / n g - v a l i d / ) ; 
279+ 
280+       await  control . locator ( 'input' ) . fill ( '2' ) ; 
281+       await  control . locator ( 'input' ) . blur ( ) ; 
282+ 
283+       await  expect ( control ) . toHaveClass ( / n g - i n v a l i d / ) ; 
284+     } ) ; 
63285  } ) ; 
286+ 
287+   // Helper functions 
288+   async  function  testStatus ( page : any ,  status : string )  { 
289+     await  expect ( page . locator ( '#status' ) ) . toHaveText ( status ) ; 
290+   } 
291+ 
292+   async  function  testData ( page : any ,  data : any )  { 
293+     const  text  =  await  page . locator ( '#data' ) . textContent ( ) ; 
294+     const  value  =  JSON . parse ( text ! ) ; 
295+     expect ( value ) . toEqual ( data ) ; 
296+   } 
64297} ) ; 
0 commit comments