Skip to content

Commit 6d8ac7f

Browse files
VIDSOL-211-fixing unit test isolation
Unit tests were not isolated, tests were unstable, and reliability was compromised.
1 parent 96d0ff7 commit 6d8ac7f

File tree

15 files changed

+221
-273
lines changed

15 files changed

+221
-273
lines changed

frontend/src/App.spec.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { render, screen } from '@testing-library/react';
2-
import { describe, it, expect, vi, afterEach } from 'vitest';
2+
import { describe, it, expect, vi } from 'vitest';
33
import { PropsWithChildren } from 'react';
44
import App from './App';
55

@@ -36,10 +36,6 @@ vi.mock('./Context/ConfigProvider', () => ({
3636
default: ({ children }: PropsWithChildren) => children,
3737
}));
3838

39-
afterEach(() => {
40-
vi.clearAllMocks();
41-
});
42-
4339
describe('App routing', () => {
4440
it('renders LandingPage on unknown route', () => {
4541
window.history.pushState({}, '', '/unknown');

frontend/src/Context/BackgroundPublisherProvider/useBackgroundPublisher/useBackgroundPublisher.spec.tsx

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,21 @@
11
import { act, cleanup, renderHook } from '@testing-library/react';
22
import { afterAll, afterEach, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
3-
import {
4-
hasMediaProcessorSupport,
5-
initPublisher,
6-
Publisher,
7-
PublisherProperties,
8-
} from '@vonage/client-sdk-video';
3+
import { hasMediaProcessorSupport, initPublisher, Publisher } from '@vonage/client-sdk-video';
94
import EventEmitter from 'events';
10-
import useBackgroundPublisher from './useBackgroundPublisher';
5+
import useUserContext from '@hooks/useUserContext';
6+
import usePermissions from '@hooks/usePermissions';
7+
import useDevices from '@hooks/useDevices';
8+
import { allMediaDevices, defaultAudioDevice, defaultVideoDevice } from '@utils/mockData/device';
9+
import { DEVICE_ACCESS_STATUS } from '@utils/constants';
1110
import { UserContextType } from '../../user';
12-
import useUserContext from '../../../hooks/useUserContext';
13-
import usePermissions, { PermissionsHookType } from '../../../hooks/usePermissions';
14-
import useDevices from '../../../hooks/useDevices';
15-
import { AllMediaDevices } from '../../../types';
16-
import {
17-
allMediaDevices,
18-
defaultAudioDevice,
19-
defaultVideoDevice,
20-
} from '../../../utils/mockData/device';
21-
import { DEVICE_ACCESS_STATUS } from '../../../utils/constants';
11+
import useBackgroundPublisher from './useBackgroundPublisher';
2212
import usePublisherOptions from '../../PublisherProvider/usePublisherOptions';
2313

2414
vi.mock('@vonage/client-sdk-video');
25-
vi.mock('../../../hooks/useUserContext.tsx');
26-
vi.mock('../../../hooks/usePermissions.tsx');
27-
vi.mock('../../../hooks/useDevices.tsx');
15+
vi.mock('@hooks/useUserContext.tsx');
16+
vi.mock('@hooks/usePermissions.tsx');
17+
vi.mock('@hooks/useDevices.tsx');
2818
vi.mock('../../PublisherProvider/usePublisherOptions');
29-
const mockUseUserContext = useUserContext as Mock<[], UserContextType>;
30-
const mockUsePermissions = usePermissions as Mock<[], PermissionsHookType>;
31-
const mockUseDevices = useDevices as Mock<
32-
[],
33-
{ allMediaDevices: AllMediaDevices; getAllMediaDevices: () => void }
34-
>;
35-
const mockUsePublisherOptions = usePublisherOptions as Mock<[], PublisherProperties>;
3619

3720
const defaultSettings = {
3821
publishAudio: false,
@@ -56,25 +39,25 @@ describe('useBackgroundPublisher', () => {
5639
applyVideoFilter: vi.fn(),
5740
clearVideoFilter: vi.fn(),
5841
}) as unknown as Publisher;
42+
5943
const mockedInitPublisher = vi.fn();
6044
const mockedHasMediaProcessorSupport = vi.fn();
61-
const consoleErrorSpy = vi.spyOn(console, 'error');
6245
const mockSetAccessStatus = vi.fn();
6346

6447
beforeEach(() => {
65-
vi.resetAllMocks();
66-
mockUseUserContext.mockImplementation(() => mockUserContextWithDefaultSettings);
48+
vi.spyOn(console, 'error');
49+
vi.mocked(useUserContext).mockImplementation(() => mockUserContextWithDefaultSettings);
6750
(initPublisher as Mock).mockImplementation(mockedInitPublisher);
6851
(hasMediaProcessorSupport as Mock).mockImplementation(mockedHasMediaProcessorSupport);
69-
mockUseDevices.mockReturnValue({
52+
vi.mocked(useDevices).mockReturnValue({
7053
getAllMediaDevices: vi.fn(),
7154
allMediaDevices,
7255
});
73-
mockUsePermissions.mockReturnValue({
56+
vi.mocked(usePermissions).mockReturnValue({
7457
accessStatus: DEVICE_ACCESS_STATUS.PENDING,
7558
setAccessStatus: mockSetAccessStatus,
7659
});
77-
mockUsePublisherOptions.mockReturnValue({
60+
vi.mocked(usePublisherOptions).mockReturnValue({
7861
publishVideo: true,
7962
});
8063
});
@@ -104,7 +87,7 @@ describe('useBackgroundPublisher', () => {
10487

10588
const { result } = renderHook(() => useBackgroundPublisher());
10689
await result.current.initBackgroundLocalPublisher();
107-
expect(consoleErrorSpy).toHaveBeenCalledWith('initPublisher error: ', error);
90+
expect(console.error).toHaveBeenCalledWith('initPublisher error: ', error);
10891
});
10992

11093
it('should apply background high blur when initialized and changed background', async () => {
@@ -195,7 +178,7 @@ describe('useBackgroundPublisher', () => {
195178
await res.current.changeBackground('low-blur');
196179
});
197180

198-
expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to apply background filter.');
181+
expect(console.error).toHaveBeenCalledWith('Failed to apply background filter.');
199182
});
200183
});
201184

@@ -261,7 +244,7 @@ describe('useBackgroundPublisher', () => {
261244
expect(emitAccessDeniedError).not.toThrow();
262245
});
263246

264-
expect(consoleErrorSpy).toHaveBeenCalledWith(
247+
expect(console.error).toHaveBeenCalledWith(
265248
'Failed to query device permission for microphone: Error: Whoops'
266249
);
267250
});

frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
1+
import { describe, expect, it, vi, beforeEach } from 'vitest';
22
import { renderHook, waitFor } from '@testing-library/react';
33
import useConfig, { AppConfig } from './useConfig';
44

55
describe('useConfig', () => {
6-
let nativeFetch: typeof global.fetch;
76
const defaultConfig: AppConfig = {
87
videoSettings: {
98
allowCameraControl: true,
@@ -30,25 +29,11 @@ describe('useConfig', () => {
3029
showParticipantList: true,
3130
},
3231
};
33-
const consoleErrorSpy = vi.spyOn(console, 'error');
34-
const consoleInfoSpy = vi.spyOn(console, 'info');
35-
36-
beforeAll(() => {
37-
nativeFetch = global.fetch;
38-
});
3932

4033
beforeEach(() => {
41-
global.fetch = vi.fn().mockResolvedValue({
42-
json: async () => ({}),
43-
});
44-
});
45-
46-
afterEach(() => {
47-
vi.resetAllMocks();
48-
});
49-
50-
afterAll(() => {
51-
global.fetch = nativeFetch;
34+
vi.spyOn(console, 'log').mockImplementation(vi.fn());
35+
vi.spyOn(console, 'info').mockImplementation(vi.fn());
36+
vi.spyOn(console, 'error').mockImplementation(vi.fn());
5237
});
5338

5439
it('returns the default config when no config.json is loaded', async () => {
@@ -87,12 +72,14 @@ describe('useConfig', () => {
8772
showParticipantList: false,
8873
},
8974
};
90-
global.fetch = vi.fn().mockResolvedValue({
75+
76+
vi.spyOn(global, 'fetch').mockResolvedValue({
9177
json: async () => mockConfig,
9278
headers: {
9379
get: () => 'application/json',
9480
},
95-
});
81+
} as unknown as Response);
82+
9683
const { result } = renderHook(() => useConfig());
9784

9885
await waitFor(() => {
@@ -102,30 +89,33 @@ describe('useConfig', () => {
10289

10390
it('falls back to defaultConfig if fetch fails', async () => {
10491
const mockFetchError = new Error('mocking a failure to fetch');
105-
global.fetch = vi.fn().mockRejectedValue(mockFetchError);
92+
93+
vi.spyOn(global, 'fetch').mockRejectedValue(mockFetchError as unknown as Response);
94+
10695
const { result } = renderHook(() => useConfig());
10796

10897
await waitFor(() => {
10998
expect(result.current).toEqual(defaultConfig);
11099
});
111-
expect(consoleErrorSpy).toHaveBeenCalledWith('Error loading config:', expect.any(Error));
100+
expect(console.error).toHaveBeenCalledWith('Error loading config:', expect.any(Error));
112101
});
113102

114103
it('falls back to defaultConfig if no config.json is found', async () => {
115-
global.fetch = vi.fn().mockResolvedValue({
104+
vi.spyOn(global, 'fetch').mockResolvedValue({
116105
ok: false,
117106
status: 404,
118107
statusText: 'Not Found',
119108
headers: {
120109
get: () => 'text/html',
121110
},
122-
});
111+
} as unknown as Response);
112+
123113
const { result } = renderHook(() => useConfig());
124114

125115
await waitFor(() => {
126116
expect(result.current).toEqual(defaultConfig);
127117
});
128-
expect(consoleInfoSpy).toHaveBeenCalledWith('No valid JSON found, using default config');
129-
expect(consoleErrorSpy).not.toHaveBeenCalled();
118+
expect(console.info).toHaveBeenCalledWith('No valid JSON found, using default config');
119+
expect(console.error).not.toHaveBeenCalled();
130120
});
131121
});

frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.spec.tsx

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,19 @@
1-
import { act, cleanup, renderHook } from '@testing-library/react';
2-
import { afterAll, afterEach, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
1+
import { act, renderHook } from '@testing-library/react';
2+
import { afterAll, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
33
import { hasMediaProcessorSupport, initPublisher, Publisher } from '@vonage/client-sdk-video';
44
import EventEmitter from 'events';
5-
import usePreviewPublisher from './usePreviewPublisher';
5+
import useUserContext from '@hooks/useUserContext';
6+
import usePermissions from '@hooks/usePermissions';
7+
import useDevices from '@hooks/useDevices';
8+
import { allMediaDevices, defaultAudioDevice, defaultVideoDevice } from '@utils/mockData/device';
9+
import { DEVICE_ACCESS_STATUS } from '@utils/constants';
610
import { UserContextType } from '../../user';
7-
import useUserContext from '../../../hooks/useUserContext';
8-
import usePermissions, { PermissionsHookType } from '../../../hooks/usePermissions';
9-
import useDevices from '../../../hooks/useDevices';
10-
import { AllMediaDevices } from '../../../types';
11-
import {
12-
allMediaDevices,
13-
defaultAudioDevice,
14-
defaultVideoDevice,
15-
} from '../../../utils/mockData/device';
16-
import { DEVICE_ACCESS_STATUS } from '../../../utils/constants';
11+
import usePreviewPublisher from './usePreviewPublisher';
1712

1813
vi.mock('@vonage/client-sdk-video');
19-
vi.mock('../../../hooks/useUserContext.tsx');
20-
vi.mock('../../../hooks/usePermissions.tsx');
21-
vi.mock('../../../hooks/useDevices.tsx');
22-
const mockUseUserContext = useUserContext as Mock<[], UserContextType>;
23-
const mockUsePermissions = usePermissions as Mock<[], PermissionsHookType>;
24-
const mockUseDevices = useDevices as Mock<
25-
[],
26-
{ allMediaDevices: AllMediaDevices; getAllMediaDevices: () => void }
27-
>;
14+
vi.mock('@hooks/useUserContext.tsx');
15+
vi.mock('@hooks/usePermissions.tsx');
16+
vi.mock('@hooks/useDevices.tsx');
2817

2918
const defaultSettings = {
3019
publishAudio: false,
@@ -50,28 +39,24 @@ describe('usePreviewPublisher', () => {
5039
}) as unknown as Publisher;
5140
const mockedInitPublisher = vi.fn();
5241
const mockedHasMediaProcessorSupport = vi.fn();
53-
const consoleErrorSpy = vi.spyOn(console, 'error');
5442
const mockSetAccessStatus = vi.fn();
5543

5644
beforeEach(() => {
57-
vi.resetAllMocks();
58-
mockUseUserContext.mockImplementation(() => mockUserContextWithDefaultSettings);
45+
vi.spyOn(console, 'error').mockImplementation(vi.fn());
46+
47+
vi.mocked(useUserContext).mockImplementation(() => mockUserContextWithDefaultSettings);
5948
(initPublisher as Mock).mockImplementation(mockedInitPublisher);
6049
(hasMediaProcessorSupport as Mock).mockImplementation(mockedHasMediaProcessorSupport);
61-
mockUseDevices.mockReturnValue({
50+
vi.mocked(useDevices).mockReturnValue({
6251
getAllMediaDevices: vi.fn(),
6352
allMediaDevices,
6453
});
65-
mockUsePermissions.mockReturnValue({
54+
vi.mocked(usePermissions).mockReturnValue({
6655
accessStatus: DEVICE_ACCESS_STATUS.PENDING,
6756
setAccessStatus: mockSetAccessStatus,
6857
});
6958
});
7059

71-
afterEach(() => {
72-
cleanup();
73-
});
74-
7560
describe('initLocalPublisher', () => {
7661
it('should call initLocalPublisher', async () => {
7762
mockedInitPublisher.mockReturnValue(mockPublisher);
@@ -93,7 +78,7 @@ describe('usePreviewPublisher', () => {
9378

9479
const { result } = renderHook(() => usePreviewPublisher());
9580
await result.current.initLocalPublisher();
96-
expect(consoleErrorSpy).toHaveBeenCalledWith('initPublisher error: ', error);
81+
expect(console.error).toHaveBeenCalledWith('initPublisher error: ', error);
9782
});
9883

9984
it('should apply background high blur when initialized and changed background', async () => {
@@ -180,7 +165,7 @@ describe('usePreviewPublisher', () => {
180165
await res.current.changeBackground('low-blur');
181166
});
182167

183-
expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to apply background filter.');
168+
expect(console.error).toHaveBeenCalledWith('Failed to apply background filter.');
184169
});
185170
});
186171

@@ -246,7 +231,7 @@ describe('usePreviewPublisher', () => {
246231
expect(emitAccessDeniedError).not.toThrow();
247232
});
248233

249-
expect(consoleErrorSpy).toHaveBeenCalledWith(
234+
expect(console.error).toHaveBeenCalledWith(
250235
'Failed to query device permission for microphone: Error: Whoops'
251236
);
252237
});

0 commit comments

Comments
 (0)