@@ -156,4 +156,181 @@ describe("basic signup form", () => {
156156 mockConsoleError ( ) ;
157157 await assertErrorAlert ( "Permission denied" ) ;
158158 } ) ;
159+
160+ describe ( "name validation" , ( ) => {
161+ it ( "rejects names shorter than 2 characters" , async ( ) => {
162+ render ( < BasicForm /> , { wrapper } ) ;
163+
164+ const user = userEvent . setup ( ) ;
165+ const nameInput = await screen . findByLabelText (
166+ t ( "auth:basic_form.name.field_label" ) ,
167+ ) ;
168+
169+ await user . type ( nameInput , "A" ) ;
170+ await user . tab ( ) ; // Trigger blur to validate
171+
172+ await waitFor ( ( ) => {
173+ expect (
174+ screen . getByText ( t ( "auth:basic_form.name.min_length_error" ) ) ,
175+ ) . toBeInTheDocument ( ) ;
176+ } ) ;
177+
178+ await user . type (
179+ await screen . findByLabelText ( t ( "auth:basic_form.email.field_label" ) ) ,
180+ "test@example.com" ,
181+ ) ;
182+ await user . click (
183+ await screen . findByRole ( "button" , { name : t ( "global:continue" ) } ) ,
184+ ) ;
185+
186+ await waitFor ( ( ) => {
187+ expect ( startSignupMock ) . not . toHaveBeenCalled ( ) ;
188+ } ) ;
189+ } ) ;
190+
191+ it ( "rejects names longer than 100 characters" , async ( ) => {
192+ render ( < BasicForm /> , { wrapper } ) ;
193+
194+ const user = userEvent . setup ( ) ;
195+ const nameInput = await screen . findByLabelText (
196+ t ( "auth:basic_form.name.field_label" ) ,
197+ ) ;
198+
199+ const longName = "A" . repeat ( 101 ) ;
200+ await user . type ( nameInput , longName ) ;
201+ await user . tab ( ) ; // Trigger blur to validate
202+
203+ await waitFor ( ( ) => {
204+ expect (
205+ screen . getByText ( t ( "auth:basic_form.name.max_length_error" ) ) ,
206+ ) . toBeInTheDocument ( ) ;
207+ } ) ;
208+
209+ await user . type (
210+ await screen . findByLabelText ( t ( "auth:basic_form.email.field_label" ) ) ,
211+ "test@example.com" ,
212+ ) ;
213+ await user . click (
214+ await screen . findByRole ( "button" , { name : t ( "global:continue" ) } ) ,
215+ ) ;
216+
217+ await waitFor ( ( ) => {
218+ expect ( startSignupMock ) . not . toHaveBeenCalled ( ) ;
219+ } ) ;
220+ } ) ;
221+
222+ it ( "rejects names with invalid characters like !@#$" , async ( ) => {
223+ render ( < BasicForm /> , { wrapper } ) ;
224+
225+ const user = userEvent . setup ( ) ;
226+ const nameInput = await screen . findByLabelText (
227+ t ( "auth:basic_form.name.field_label" ) ,
228+ ) ;
229+
230+ await user . type ( nameInput , "John!@#$" ) ;
231+ await user . tab ( ) ; // Trigger blur to validate
232+
233+ await waitFor ( ( ) => {
234+ expect (
235+ screen . getByText ( t ( "auth:basic_form.name.invalid_characters_error" ) ) ,
236+ ) . toBeInTheDocument ( ) ;
237+ } ) ;
238+
239+ await user . type (
240+ await screen . findByLabelText ( t ( "auth:basic_form.email.field_label" ) ) ,
241+ "test@example.com" ,
242+ ) ;
243+ await user . click (
244+ await screen . findByRole ( "button" , { name : t ( "global:continue" ) } ) ,
245+ ) ;
246+
247+ await waitFor ( ( ) => {
248+ expect ( startSignupMock ) . not . toHaveBeenCalled ( ) ;
249+ } ) ;
250+ } ) ;
251+
252+ it ( "accepts names with hyphens and apostrophes" , async ( ) => {
253+ startSignupMock . mockResolvedValue ( stateAfterStart ) ;
254+ render ( < BasicForm /> , { wrapper } ) ;
255+
256+ const user = userEvent . setup ( ) ;
257+
258+ await user . type (
259+ await screen . findByLabelText ( t ( "auth:basic_form.name.field_label" ) ) ,
260+ "Anne-Marie O'Connor" ,
261+ ) ;
262+ await user . type (
263+ await screen . findByLabelText ( t ( "auth:basic_form.email.field_label" ) ) ,
264+ "anne@example.com" ,
265+ ) ;
266+
267+ await user . click (
268+ await screen . findByRole ( "button" , { name : t ( "global:continue" ) } ) ,
269+ ) ;
270+
271+ await waitFor ( ( ) => {
272+ expect ( startSignupMock ) . toHaveBeenCalledWith (
273+ "Anne-Marie O'Connor" ,
274+ "anne@example.com" ,
275+ undefined ,
276+ ) ;
277+ } ) ;
278+ } ) ;
279+
280+ it ( "accepts names with Unicode characters (Cyrillic)" , async ( ) => {
281+ startSignupMock . mockResolvedValue ( stateAfterStart ) ;
282+ render ( < BasicForm /> , { wrapper } ) ;
283+
284+ const user = userEvent . setup ( ) ;
285+
286+ await user . type (
287+ await screen . findByLabelText ( t ( "auth:basic_form.name.field_label" ) ) ,
288+ "Иван Иванов" ,
289+ ) ;
290+ await user . type (
291+ await screen . findByLabelText ( t ( "auth:basic_form.email.field_label" ) ) ,
292+ "ivan@example.com" ,
293+ ) ;
294+
295+ await user . click (
296+ await screen . findByRole ( "button" , { name : t ( "global:continue" ) } ) ,
297+ ) ;
298+
299+ await waitFor ( ( ) => {
300+ expect ( startSignupMock ) . toHaveBeenCalledWith (
301+ "Иван Иванов" ,
302+ "ivan@example.com" ,
303+ undefined ,
304+ ) ;
305+ } ) ;
306+ } ) ;
307+
308+ it ( "accepts names at minimum length (2 characters)" , async ( ) => {
309+ startSignupMock . mockResolvedValue ( stateAfterStart ) ;
310+ render ( < BasicForm /> , { wrapper } ) ;
311+
312+ const user = userEvent . setup ( ) ;
313+
314+ await user . type (
315+ await screen . findByLabelText ( t ( "auth:basic_form.name.field_label" ) ) ,
316+ "Li" ,
317+ ) ;
318+ await user . type (
319+ await screen . findByLabelText ( t ( "auth:basic_form.email.field_label" ) ) ,
320+ "li@example.com" ,
321+ ) ;
322+
323+ await user . click (
324+ await screen . findByRole ( "button" , { name : t ( "global:continue" ) } ) ,
325+ ) ;
326+
327+ await waitFor ( ( ) => {
328+ expect ( startSignupMock ) . toHaveBeenCalledWith (
329+ "Li" ,
330+ "li@example.com" ,
331+ undefined ,
332+ ) ;
333+ } ) ;
334+ } ) ;
335+ } ) ;
159336} ) ;
0 commit comments