@@ -78,10 +78,53 @@ describe('the user profile profile section', () => {
7878 const dialog = screen . getByRole ( 'dialog' , { name : 'Edit name' } ) ;
7979 await actor . clear ( within ( dialog ) . getByLabelText ( 'First name' ) ) ;
8080 await actor . type ( within ( dialog ) . getByLabelText ( 'First name' ) , 'Alicia' ) ;
81+ await actor . clear ( within ( dialog ) . getByLabelText ( 'Last name' ) ) ;
82+ await actor . type ( within ( dialog ) . getByLabelText ( 'Last name' ) , 'Jones' ) ;
8183 await actor . click ( within ( dialog ) . getByRole ( 'button' , { name : 'Save changes' } ) ) ;
8284
8385 await waitFor ( ( ) => expect ( screen . queryByRole ( 'dialog' ) ) . not . toBeInTheDocument ( ) ) ;
84- expect ( screen . getByText ( 'Alicia Smith' ) ) . toBeInTheDocument ( ) ;
86+ expect ( screen . getByText ( 'Alicia Jones' ) ) . toBeInTheDocument ( ) ;
87+ } ) ;
88+
89+ it ( 'puts a last name the server rejects on the last name field' , async ( ) => {
90+ const { actor } = await renderSection ( ) ;
91+ failsWith (
92+ '/v1/me' ,
93+ {
94+ code : 'form_param_format_invalid' ,
95+ message : 'Invalid' ,
96+ long_message : 'Last name contains invalid characters.' ,
97+ meta : { param_name : 'last_name' } ,
98+ } ,
99+ 422 ,
100+ ) ;
101+
102+ await actor . click ( screen . getByRole ( 'button' , { name : 'Edit name' } ) ) ;
103+ const dialog = screen . getByRole ( 'dialog' , { name : 'Edit name' } ) ;
104+ await actor . type ( within ( dialog ) . getByLabelText ( 'Last name' ) , '!' ) ;
105+ await actor . click ( within ( dialog ) . getByRole ( 'button' , { name : 'Save changes' } ) ) ;
106+
107+ const lastName = within ( dialog ) . getByLabelText ( 'Last name' ) ;
108+ await waitFor ( ( ) => expect ( lastName ) . toHaveAccessibleDescription ( 'Last name contains invalid characters.' ) ) ;
109+ expect ( lastName ) . toHaveAttribute ( 'aria-invalid' , 'true' ) ;
110+ expect ( within ( dialog ) . getByLabelText ( 'First name' ) ) . not . toHaveAttribute ( 'aria-invalid' , 'true' ) ;
111+ } ) ;
112+
113+ it ( 'keeps Save disabled while a required half of the name is empty' , async ( ) => {
114+ const { actor } = await renderSection (
115+ signedIn ( fapiEnvironment ( { attributes : { first_name : { required : true } , last_name : { required : true } } } ) ) ,
116+ ) ;
117+
118+ await actor . click ( screen . getByRole ( 'button' , { name : 'Edit name' } ) ) ;
119+ const dialog = screen . getByRole ( 'dialog' , { name : 'Edit name' } ) ;
120+ const save = within ( dialog ) . getByRole ( 'button' , { name : 'Save changes' } ) ;
121+ await actor . clear ( within ( dialog ) . getByLabelText ( / ^ F i r s t n a m e / ) ) ;
122+ expect ( save ) . toHaveAttribute ( 'aria-disabled' , 'true' ) ;
123+ await actor . type ( within ( dialog ) . getByLabelText ( / ^ F i r s t n a m e / ) , 'Alicia' ) ;
124+ await actor . clear ( within ( dialog ) . getByLabelText ( / ^ L a s t n a m e / ) ) ;
125+ expect ( save ) . toHaveAttribute ( 'aria-disabled' , 'true' ) ;
126+ await actor . type ( within ( dialog ) . getByLabelText ( / ^ L a s t n a m e / ) , 'Jones' ) ;
127+ expect ( save ) . not . toHaveAttribute ( 'aria-disabled' , 'true' ) ;
85128 } ) ;
86129
87130 it ( 'leaves the name out when the instance collects neither half of it' , async ( ) => {
@@ -223,6 +266,39 @@ describe('the user profile profile section', () => {
223266 expect ( profile ( ) ) . toHaveTextContent ( 'alicia' ) ;
224267 } ) ;
225268
269+ it ( 'keeps Save disabled while a required username is empty' , async ( ) => {
270+ const { actor } = await renderSection ( withUsername ( 'alicesmith' , { required : true } ) ) ;
271+
272+ await actor . click ( within ( profile ( ) ) . getByRole ( 'button' , { name : 'Edit username' } ) ) ;
273+ const dialog = screen . getByRole ( 'dialog' , { name : 'Edit username' } ) ;
274+ await actor . clear ( within ( dialog ) . getByLabelText ( / ^ U s e r n a m e / ) ) ;
275+
276+ expect ( within ( dialog ) . getByRole ( 'button' , { name : 'Save changes' } ) ) . toHaveAttribute ( 'aria-disabled' , 'true' ) ;
277+ } ) ;
278+
279+ it ( 'tells the user the username length the instance allows' , async ( ) => {
280+ const { actor } = await renderSection ( {
281+ ...withUsername ( 'alicesmith' ) ,
282+ environment : fapiEnvironment ( { user_settings : { username_settings : { min_length : 5 , max_length : 20 } } } ) ,
283+ } ) ;
284+ failsWith (
285+ '/v1/me' ,
286+ { code : 'form_username_invalid_length' , message : 'Invalid length' , meta : { param_name : 'username' } } ,
287+ 422 ,
288+ ) ;
289+
290+ await actor . click ( within ( profile ( ) ) . getByRole ( 'button' , { name : 'Edit username' } ) ) ;
291+ const dialog = screen . getByRole ( 'dialog' , { name : 'Edit username' } ) ;
292+ await actor . type ( within ( dialog ) . getByLabelText ( 'Username' ) , '2' ) ;
293+ await actor . click ( within ( dialog ) . getByRole ( 'button' , { name : 'Save changes' } ) ) ;
294+
295+ await waitFor ( ( ) =>
296+ expect ( within ( dialog ) . getByLabelText ( 'Username' ) ) . toHaveAccessibleDescription (
297+ 'Your username must be between 5 and 20 characters long.' ,
298+ ) ,
299+ ) ;
300+ } ) ;
301+
226302 it ( 'offers to set a username the user has not picked yet' , async ( ) => {
227303 await renderSection ( withUsername ( null ) ) ;
228304
0 commit comments