@@ -93,6 +93,144 @@ describe('GitConfigForm', () => {
9393 false ,
9494 ) ;
9595 } ) ;
96+
97+ describe ( 'Error messages' , ( ) => {
98+ it ( 'should display error message for missing user section' , async ( ) => {
99+ renderComponent ( ) ;
100+
101+ const gitConfigField = screen . getByTestId ( 'submit-missing-user-section-git-config' ) ;
102+ await userEvent . click ( gitConfigField ) ;
103+
104+ expect (
105+ screen . getByText ( 'The [user] section with "name" and "email" fields is required.' ) ,
106+ ) . toBeInTheDocument ( ) ;
107+ } ) ;
108+
109+ it ( 'should display error message for invalid email format' , async ( ) => {
110+ renderComponent ( ) ;
111+
112+ const gitConfigField = screen . getByTestId ( 'submit-invalid-email-git-config' ) ;
113+ await userEvent . click ( gitConfigField ) ;
114+
115+ expect (
116+ screen . getByText ( 'User email must be a valid email address (e.g., user@example.com).' ) ,
117+ ) . toBeInTheDocument ( ) ;
118+ } ) ;
119+
120+ it ( 'should display error message for empty name when email is valid' , async ( ) => {
121+ renderComponent ( ) ;
122+
123+ const gitConfigField = screen . getByTestId ( 'submit-empty-name-git-config' ) ;
124+ await userEvent . click ( gitConfigField ) ;
125+
126+ // Name is now required
127+ expect ( screen . getByText ( 'Username is required.' ) ) . toBeInTheDocument ( ) ;
128+ } ) ;
129+
130+ it ( 'should display error message for name exceeding max length' , async ( ) => {
131+ renderComponent ( ) ;
132+
133+ const gitConfigField = screen . getByTestId ( 'submit-long-name-git-config' ) ;
134+ await userEvent . click ( gitConfigField ) ;
135+
136+ expect (
137+ screen . getByText ( 'User name must be between 1 and 128 characters.' ) ,
138+ ) . toBeInTheDocument ( ) ;
139+ } ) ;
140+
141+ it ( 'should display error message for empty email when name is valid' , async ( ) => {
142+ renderComponent ( ) ;
143+
144+ const gitConfigField = screen . getByTestId ( 'submit-empty-email-git-config' ) ;
145+ await userEvent . click ( gitConfigField ) ;
146+
147+ // Email is now required
148+ expect ( screen . getByText ( 'User email is required.' ) ) . toBeInTheDocument ( ) ;
149+ } ) ;
150+
151+ it ( 'should display error message for email exceeding max length' , async ( ) => {
152+ renderComponent ( ) ;
153+
154+ const gitConfigField = screen . getByTestId ( 'submit-long-email-git-config' ) ;
155+ await userEvent . click ( gitConfigField ) ;
156+
157+ expect (
158+ screen . getByText ( 'User email must be between 1 and 128 characters.' ) ,
159+ ) . toBeInTheDocument ( ) ;
160+ } ) ;
161+
162+ it ( 'should display error message for malformed config' , async ( ) => {
163+ renderComponent ( ) ;
164+
165+ const gitConfigField = screen . getByTestId ( 'submit-parse-error-git-config' ) ;
166+ await userEvent . click ( gitConfigField ) ;
167+
168+ // The multi-ini parser is lenient and may parse malformed content
169+ // but it should still fail validation and show an error message
170+ expect (
171+ screen . getByText ( 'The [user] section with "name" and "email" fields is required.' ) ,
172+ ) . toBeInTheDocument ( ) ;
173+ } ) ;
174+
175+ it ( 'should display error message for max length exceeded' , async ( ) => {
176+ renderComponent ( ) ;
177+
178+ const gitConfigField = screen . getByTestId ( 'submit-max-length-git-config' ) ;
179+ await userEvent . click ( gitConfigField ) ;
180+
181+ expect (
182+ screen . getByText ( 'The value is too long. The maximum length is 4096 characters.' ) ,
183+ ) . toBeInTheDocument ( ) ;
184+ } ) ;
185+
186+ it ( 'should not display error message for valid input' , async ( ) => {
187+ renderComponent ( ) ;
188+
189+ const gitConfigField = screen . getByTestId ( 'submit-valid-git-config' ) ;
190+ await userEvent . click ( gitConfigField ) ;
191+
192+ expect (
193+ screen . queryByText ( 'User email must be a valid email address (e.g., user@example.com).' ) ,
194+ ) . not . toBeInTheDocument ( ) ;
195+ expect (
196+ screen . queryByText ( 'The [user] section with "name" and "email" fields is required.' ) ,
197+ ) . not . toBeInTheDocument ( ) ;
198+ } ) ;
199+ } ) ;
200+
201+ describe ( 'Required field validation' , ( ) => {
202+ it ( 'should reject config with only name (email is required)' , async ( ) => {
203+ renderComponent ( ) ;
204+
205+ const gitConfigField = screen . getByTestId ( 'submit-only-name-git-config' ) ;
206+ await userEvent . click ( gitConfigField ) ;
207+
208+ expect ( mockOnChange ) . toHaveBeenCalledWith ( { user : { name : 'User One' } } , false ) ;
209+ expect ( screen . getByText ( 'User email is required.' ) ) . toBeInTheDocument ( ) ;
210+ } ) ;
211+
212+ it ( 'should reject config with only email (name is required)' , async ( ) => {
213+ renderComponent ( ) ;
214+
215+ const gitConfigField = screen . getByTestId ( 'submit-only-email-git-config' ) ;
216+ await userEvent . click ( gitConfigField ) ;
217+
218+ expect ( mockOnChange ) . toHaveBeenCalledWith ( { user : { email : 'user@test.com' } } , false ) ;
219+ expect ( screen . getByText ( 'Username is required.' ) ) . toBeInTheDocument ( ) ;
220+ } ) ;
221+
222+ it ( 'should reject config when both name and email are null' , async ( ) => {
223+ renderComponent ( ) ;
224+
225+ const gitConfigField = screen . getByTestId ( 'submit-both-null-git-config' ) ;
226+ await userEvent . click ( gitConfigField ) ;
227+
228+ expect ( mockOnChange ) . toHaveBeenCalledWith ( { user : { } } , false ) ;
229+ expect (
230+ screen . getByText ( 'The [user] section with "name" and "email" fields is required.' ) ,
231+ ) . toBeInTheDocument ( ) ;
232+ } ) ;
233+ } ) ;
96234} ) ;
97235
98236function getComponent ( gitConfig ?: GitConfigStore . GitConfig ) {
0 commit comments