Skip to content

Commit 315e000

Browse files
committed
test: add unit tests according changes
1 parent 0469f1b commit 315e000

3 files changed

Lines changed: 233 additions & 1 deletion

File tree

src/field-renderer/tests/FieldRenderer.test.jsx

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,152 @@ describe('FieldRendererTests', () => {
200200

201201
expect(container.querySelector(`#${fieldData.name}-error`).textContent).toEqual('You must agree to our Honor Code');
202202
});
203+
204+
it('should render placeholder for text field', () => {
205+
const fieldData = {
206+
type: 'text',
207+
label: 'Company',
208+
name: 'company-field',
209+
placeholder: 'Enter your company name',
210+
};
211+
212+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
213+
const input = container.querySelector('input#company-field');
214+
215+
expect(input.placeholder).toEqual('Enter your company name');
216+
});
217+
218+
it('should render placeholder for textarea field', () => {
219+
const fieldData = {
220+
type: 'textarea',
221+
label: 'Goals',
222+
name: 'goals-field',
223+
placeholder: 'Share your learning goals',
224+
};
225+
226+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
227+
const input = container.querySelector('#goals-field');
228+
229+
expect(input.placeholder).toEqual('Share your learning goals');
230+
});
231+
232+
it('should apply maxLength restriction to text field', () => {
233+
const fieldData = {
234+
type: 'text',
235+
label: 'Company',
236+
name: 'company-field',
237+
restrictions: {
238+
max_length: 50,
239+
},
240+
};
241+
242+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
243+
const input = container.querySelector('input#company-field');
244+
245+
expect(input.maxLength).toEqual(50);
246+
});
247+
248+
it('should apply maxLength restriction to textarea field', () => {
249+
const fieldData = {
250+
type: 'textarea',
251+
label: 'Goals',
252+
name: 'goals-field',
253+
restrictions: {
254+
max_length: 200,
255+
},
256+
};
257+
258+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
259+
const input = container.querySelector('#goals-field');
260+
261+
expect(input.maxLength).toEqual(200);
262+
});
263+
264+
it('should show help text when field has focus and instructions are provided', () => {
265+
const fieldData = {
266+
type: 'text',
267+
label: 'Username',
268+
name: 'username-field',
269+
instructions: 'Username must be between 2-30 characters',
270+
};
271+
272+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
273+
const input = container.querySelector('input#username-field');
274+
275+
// Help text should not be visible initially
276+
expect(container.textContent).not.toContain('Username must be between 2-30 characters');
277+
278+
// Focus the field
279+
fireEvent.focus(input);
280+
281+
// Help text should now be visible
282+
expect(container.textContent).toContain('Username must be between 2-30 characters');
283+
284+
// Blur the field
285+
fireEvent.blur(input);
286+
287+
// Help text should be hidden again
288+
expect(container.textContent).not.toContain('Username must be between 2-30 characters');
289+
});
290+
291+
it('should show help text for textarea when focused', () => {
292+
const fieldData = {
293+
type: 'textarea',
294+
label: 'Goals',
295+
name: 'goals-field',
296+
instructions: 'Please describe your learning goals in detail',
297+
};
298+
299+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
300+
const input = container.querySelector('#goals-field');
301+
302+
// Help text should not be visible initially
303+
expect(container.textContent).not.toContain('Please describe your learning goals in detail');
304+
305+
// Focus the field
306+
fireEvent.focus(input);
307+
308+
// Help text should now be visible
309+
expect(container.textContent).toContain('Please describe your learning goals in detail');
310+
});
311+
312+
it('should not show help text if instructions are not provided', () => {
313+
const fieldData = {
314+
type: 'text',
315+
label: 'Company',
316+
name: 'company-field',
317+
};
318+
319+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
320+
const input = container.querySelector('input#company-field');
321+
322+
// Focus the field
323+
fireEvent.focus(input);
324+
325+
// No help text should be rendered since instructions are not provided
326+
const feedbackElement = container.querySelector('.form-control-feedback');
327+
expect(feedbackElement).toBeNull();
328+
});
329+
330+
it('should show help text for select field when focused', () => {
331+
const fieldData = {
332+
type: 'select',
333+
label: 'Country',
334+
name: 'country-field',
335+
options: [['us', 'United States'], ['ca', 'Canada']],
336+
instructions: 'Select your country of residence',
337+
};
338+
339+
const { container } = render(<FieldRenderer value={value} fieldData={fieldData} onChangeHandler={changeHandler} />);
340+
const select = container.querySelector('select#country-field');
341+
342+
// Help text should not be visible initially
343+
expect(container.textContent).not.toContain('Select your country of residence');
344+
345+
// Focus the field
346+
fireEvent.focus(select);
347+
348+
// Note: Select fields don't show help text in the current implementation
349+
// This test documents the current behavior
350+
});
203351
});

src/register/components/tests/ConfigurableRegistrationForm.test.jsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,5 +419,55 @@ describe('ConfigurableRegistrationForm', () => {
419419

420420
expect(professionErrorElement.textContent).toEqual(professionError);
421421
});
422+
423+
it('should normalize object-style error messages from backend', () => {
424+
const professionErrorMessage = { required: 'Enter your profession' };
425+
useThirdPartyAuthContext.mockReturnValue({
426+
currentProvider: null,
427+
platformName: '',
428+
providers: [],
429+
secondaryProviders: [],
430+
handleInstitutionLogin: jest.fn(),
431+
handleInstitutionLogout: jest.fn(),
432+
isInstitutionAuthActive: false,
433+
institutionLogin: false,
434+
pipelineDetails: {},
435+
thirdPartyAuthContext: {
436+
autoSubmitRegForm: false,
437+
currentProvider: null,
438+
finishAuthUrl: null,
439+
pipelineUserDetails: null,
440+
providers: [],
441+
secondaryProviders: [],
442+
errorMessage: null,
443+
},
444+
fieldDescriptions: {
445+
profession: {
446+
name: 'profession', type: 'text', label: 'Profession', error_message: professionErrorMessage,
447+
},
448+
},
449+
optionalFields: [],
450+
setThirdPartyAuthContextBegin: jest.fn(),
451+
setThirdPartyAuthContextSuccess: jest.fn(),
452+
setThirdPartyAuthContextFailure: jest.fn(),
453+
setEmailSuggestionContext: jest.fn(),
454+
clearThirdPartyAuthErrorMessage: jest.fn(),
455+
});
456+
457+
const { getByLabelText, container } = render(
458+
routerWrapper(renderWrapper(<RegistrationPage {...props} />)),
459+
);
460+
461+
const professionInput = getByLabelText('Profession');
462+
fireEvent.focus(professionInput);
463+
fireEvent.blur(professionInput);
464+
465+
const submitButton = container.querySelector('button.btn-brand');
466+
fireEvent.click(submitButton);
467+
468+
const professionErrorElement = container.querySelector('#profession-error');
469+
470+
expect(professionErrorElement.textContent).toEqual('Enter your profession');
471+
});
422472
});
423473
});

src/register/data/tests/utils.test.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,38 @@
1-
import { isFormValid } from '../utils';
1+
import { isFormValid, normalizeErrorMessage } from '../utils';
2+
3+
describe('normalizeErrorMessage', () => {
4+
it('should return the error message if it is a string', () => {
5+
const errorMessage = 'This field is required';
6+
expect(normalizeErrorMessage(errorMessage)).toBe('This field is required');
7+
});
8+
9+
it('should extract the first value from an object error message', () => {
10+
const errorMessage = { required: 'This field is required' };
11+
expect(normalizeErrorMessage(errorMessage)).toBe('This field is required');
12+
});
13+
14+
it('should handle multiple keys in object and return first value', () => {
15+
const errorMessage = { required: 'Required field', min_length: 'Too short' };
16+
const result = normalizeErrorMessage(errorMessage);
17+
expect(['Required field', 'Too short']).toContain(result);
18+
});
19+
20+
it('should return empty string if error message is null', () => {
21+
expect(normalizeErrorMessage(null)).toBe('');
22+
});
23+
24+
it('should return empty string if error message is undefined', () => {
25+
expect(normalizeErrorMessage(undefined)).toBe('');
26+
});
27+
28+
it('should return empty string if error message is an empty object', () => {
29+
expect(normalizeErrorMessage({})).toBe('');
30+
});
31+
32+
it('should return empty string if error message is an empty string', () => {
33+
expect(normalizeErrorMessage('')).toBe('');
34+
});
35+
});
236

337
describe('Payload validation', () => {
438
let formatMessage;

0 commit comments

Comments
 (0)