Skip to content

Commit 5c3d8f5

Browse files
committed
frontend/tests: move some mocks to test-setup file
1 parent ab58b61 commit 5c3d8f5

File tree

2 files changed

+108
-29
lines changed

2 files changed

+108
-29
lines changed

frontend/src/components/__tests__/register.test.tsx

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,6 @@ vi.mock("../Navbar", () => {
3434
};
3535
});
3636

37-
vi.mock('../PasswordComponent', () => ({
38-
PasswordComponent: ({ onChange, isInvalid, invalidMessage, controlId }: {
39-
onChange: (value: string) => void;
40-
isInvalid: boolean;
41-
invalidMessage: string;
42-
controlId: string;
43-
}) => {
44-
return <div>
45-
<input
46-
type="textbox"
47-
data-testid="password-input"
48-
onChange={(e) => onChange((e.target as HTMLInputElement).value)}
49-
id={controlId}
50-
className={isInvalid ? 'invalid' : ''}
51-
/>
52-
{isInvalid && <div data-testid="password-error">{invalidMessage}</div>}
53-
</div>;
54-
},
55-
}));
56-
5737
vi.mock('../recovery_data_component', () => ({
5838
RecoveryDataComponent: ({ show, email, secret }: {
5939
show: { value: boolean };

frontend/src/test-setup.ts

Lines changed: 108 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,17 @@ interface FormControlProps extends MockComponentProps {
2222
type?: string;
2323
as?: string;
2424
controlId?: string;
25+
disabled?: boolean;
26+
required?: boolean;
2527
}
2628

2729
interface FormCheckProps extends MockComponentProps {
2830
checked?: boolean;
2931
label?: string;
3032
isInvalid?: boolean;
33+
disabled?: boolean;
34+
id?: string;
35+
type?: string;
3136
}
3237

3338
interface FormFeedbackProps extends MockComponentProps {
@@ -60,6 +65,9 @@ interface AlertProps extends MockComponentProps {
6065

6166
interface ButtonProps extends MockComponentProps {
6267
type?: string;
68+
variant?: string;
69+
disabled?: boolean;
70+
onClick?: () => void;
6371
}
6472

6573
// Mock react-bootstrap components with simple HTML elements
@@ -70,6 +78,9 @@ vi.mock('react-bootstrap', () => {
7078
Form.Group = ({ children, controlId, ...props }: MockComponentProps) => {
7179
if (children && Array.isArray(children)) {
7280
children = children.map((child) => {
81+
if (typeof child !== "object") {
82+
return child;
83+
}
7384
child.props = { ...child.props, controlId };
7485
return child;
7586
})
@@ -81,14 +92,16 @@ vi.mock('react-bootstrap', () => {
8192
Form.Label = ({ children, controlId, ...props }: MockComponentProps) =>
8293
h('label', { ...props, htmlFor: controlId }, children);
8394

84-
Form.Control = ({ onChange, value, isInvalid, type, as, controlId, ...props }: FormControlProps) => {
95+
Form.Control = ({ onChange, value, isInvalid, type, as, controlId, disabled, required, ...props }: FormControlProps) => {
8596
if (as === 'textarea') {
8697
return h('textarea', {
8798
...props,
8899
role: 'textbox',
89100
value,
90101
onChange,
91102
id: controlId,
103+
disabled,
104+
required,
92105
className: isInvalid ? 'invalid' : '',
93106
'data-testid': `${type || 'textarea'}-input`
94107
});
@@ -99,22 +112,30 @@ vi.mock('react-bootstrap', () => {
99112
value,
100113
onChange,
101114
id: controlId,
115+
disabled,
116+
required,
102117
className: isInvalid ? 'invalid' : '',
103118
'data-testid': `${type}-input`
104119
});
105120
};
106121

107-
Form.Check = ({ checked, label, isInvalid, ...props }: FormCheckProps) =>
108-
h('div', {}, [
122+
Form.Check = ({ checked, label, isInvalid, disabled, id, type, ...props }: FormCheckProps) => {
123+
return h('div', {}, [
109124
h('input', {
110125
...props,
111-
type: 'checkbox',
126+
type: type || 'checkbox',
112127
checked,
128+
disabled,
129+
id,
113130
className: isInvalid ? 'invalid' : '',
114131
'data-testid': 'checkbox'
115132
}),
116-
h('label', {}, label)
133+
h('label', { htmlFor: id }, label)
117134
]);
135+
};
136+
137+
Form.Text = ({ children, ...props }: MockComponentProps) =>
138+
h('div', { ...props, 'data-testid': 'form-text' }, children);
118139

119140
// eslint-disable-next-line @typescript-eslint/no-explicit-any
120141
(Form.Control as any).Feedback = ({ children, type, ...props }: FormFeedbackProps) =>
@@ -193,7 +214,14 @@ vi.mock('react-bootstrap', () => {
193214

194215
return {
195216
Alert,
196-
Button: ({ children, type, ...props }: ButtonProps) => h('button', { ...props, type, 'data-testid': 'submit-button' }, children),
217+
Button: ({ children, type, variant, disabled, onClick, ...props }: ButtonProps) => h('button', {
218+
...props,
219+
type,
220+
disabled,
221+
onClick,
222+
className: variant ? `btn btn-${variant}` : 'btn',
223+
'data-testid': 'submit-button'
224+
}, children),
197225
ButtonGroup: ({ children, ...props }: MockComponentProps) => h('div', { ...props }, children),
198226
Card,
199227
Col: ({ children, ...props }: MockComponentProps) => h('div', { ...props, className: 'col' }, children),
@@ -220,6 +248,7 @@ vi.mock('react-feather', () => ({
220248
ChevronUp: () => h('svg', { 'data-testid': 'chevron-up' }),
221249
Edit: () => h('svg', { 'data-testid': 'edit-icon' }),
222250
Eye: () => h('svg', { 'data-testid': 'eye-icon' }),
251+
EyeOff: () => h('svg', { 'data-testid': 'eye-off-icon' }),
223252
Monitor: () => h('svg', { 'data-testid': 'monitor-icon' }),
224253
Trash2: () => h('svg', { 'data-testid': 'trash-icon', className: 'feather-trash-2' }),
225254
}));
@@ -247,6 +276,7 @@ vi.mock('libsodium-wrappers', () => ({
247276
crypto_box_seal: vi.fn(),
248277
crypto_box_keypair: vi.fn(),
249278
crypto_secretbox_easy: vi.fn(),
279+
crypto_secretbox_open_easy: vi.fn(),
250280
crypto_secretbox_NONCEBYTES: 24,
251281
crypto_secretbox_KEYBYTES: 32,
252282
},
@@ -266,19 +296,27 @@ vi.mock('js-base64', () => ({
266296
}));
267297

268298
// Mock utils
269-
vi.mock('../utils', () => ({
299+
vi.mock('./utils', () => ({
270300
fetchClient: {
271301
GET: vi.fn(),
272302
POST: vi.fn(),
303+
PUT: vi.fn(),
273304
DELETE: vi.fn(),
274305
},
275306
get_decrypted_secret: vi.fn(),
276307
pub_key: new Uint8Array(),
277308
secret: new Uint8Array(),
309+
PASSWORD_PATTERN: /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}/,
310+
generate_hash: vi.fn(),
311+
generate_random_bytes: vi.fn(),
312+
get_salt: vi.fn(),
313+
get_salt_for_user: vi.fn(),
314+
concat_salts: vi.fn(),
315+
isDebugMode: { value: false },
278316
}));
279317

280318
// Mock Alert component
281-
vi.mock('../components/Alert', () => ({
319+
vi.mock('./components/Alert', () => ({
282320
showAlert: vi.fn(),
283321
}));
284322

@@ -314,10 +352,71 @@ vi.mock('./i18n', () => ({
314352
}));
315353

316354
// Mock Circle component
317-
vi.mock('../components/Circle', () => ({
355+
vi.mock('./components/Circle', () => ({
318356
Circle: vi.fn(() => null),
319357
}));
320358

359+
// Mock Navbar component
360+
vi.mock('./components/Navbar', () => ({
361+
logout: vi.fn(),
362+
}));
363+
364+
// Mock PasswordComponent
365+
vi.mock('./components/PasswordComponent', () => ({
366+
PasswordComponent: ({ onChange, isInvalid, invalidMessage, controlId }: {
367+
onChange: (value: string) => void;
368+
isInvalid: boolean;
369+
invalidMessage: string;
370+
controlId: string;
371+
}) => {
372+
return h('div', {}, [
373+
h('input', {
374+
type: 'textbox',
375+
'data-testid': 'password-input',
376+
onChange: (e: Event) => onChange((e.target as HTMLInputElement).value),
377+
id: controlId,
378+
className: isInvalid ? 'invalid' : '',
379+
}),
380+
isInvalid && h('div', { 'data-testid': 'password-error' }, invalidMessage)
381+
]);
382+
},
383+
}));
384+
385+
// Mock @preact/signals
386+
vi.mock('@preact/signals', async (useOriginal) => {
387+
const original = await useOriginal();
388+
return {
389+
...(typeof original === 'object' && original !== null ? original : {}),
390+
signal: (value: unknown) => ({
391+
value,
392+
}),
393+
}
394+
});
395+
321396
beforeAll(() => {
322397
// Setup any global test configuration here
398+
399+
// Mock localStorage
400+
const localStorageMock = {
401+
getItem: vi.fn(),
402+
setItem: vi.fn(),
403+
removeItem: vi.fn(),
404+
clear: vi.fn(),
405+
};
406+
Object.defineProperty(window, 'localStorage', {
407+
value: localStorageMock,
408+
});
409+
410+
// Mock window.location.reload
411+
Object.defineProperty(window, 'location', {
412+
value: {
413+
reload: vi.fn(),
414+
href: 'http://localhost:3000',
415+
},
416+
writable: true,
417+
});
418+
419+
// Mock console methods to reduce noise in tests
420+
vi.spyOn(console, 'warn').mockImplementation(() => {});
421+
vi.spyOn(console, 'error').mockImplementation(() => {});
323422
});

0 commit comments

Comments
 (0)