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