Skip to content

Commit e20a801

Browse files
authored
chore: add more unit tests (#7371)
* chore: add more unit tests * chore: text correction
1 parent 3e1c9cd commit e20a801

21 files changed

+626
-46
lines changed

apps/site/components/Common/ActiveLink/__tests__/index.test.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { render, screen } from '@testing-library/react';
22

33
import ActiveLink from '..';
44

5-
// mock usePathname, but retain all the other imports
65
jest.mock('@/navigation.mjs', () => ({
76
...jest.requireActual('@/navigation.mjs'),
87
usePathname: jest.fn(),

apps/site/jest.config.mjs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import nextJest from 'next/jest.js';
22

3-
const createJestConfig = nextJest({
4-
dir: './',
5-
});
3+
const createJestConfig = nextJest({ dir: './' });
64

75
/** @type {import('jest').Config} */
86
const customJestConfig = {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { render } from '@testing-library/react';
2+
3+
import { NavigationStateProvider } from '@/providers/navigationStateProvider';
4+
5+
describe('NavigationStateProvider', () => {
6+
it('should render without crashing', () => {
7+
const { container } = render(
8+
<NavigationStateProvider>
9+
<div />
10+
</NavigationStateProvider>
11+
);
12+
13+
expect(container).toBeDefined();
14+
});
15+
16+
it('should provide navigation state context', () => {
17+
const { getByText } = render(
18+
<NavigationStateProvider>
19+
<div>Navigation State</div>
20+
</NavigationStateProvider>
21+
);
22+
23+
expect(getByText('Navigation State')).toBeDefined();
24+
});
25+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { render } from '@testing-library/react';
2+
3+
import { ReleaseProvider, ReleasesProvider } from '@/providers/releaseProvider';
4+
5+
describe('ReleaseProvider', () => {
6+
it('should render without crashing', () => {
7+
const initialRelease = { versionWithPrefix: 'v14.17.0' };
8+
const releases = [initialRelease];
9+
const snippets = [];
10+
11+
const { container } = render(
12+
<ReleasesProvider releases={releases} snippets={snippets}>
13+
<ReleaseProvider initialRelease={initialRelease}>
14+
<div />
15+
</ReleaseProvider>
16+
</ReleasesProvider>
17+
);
18+
19+
expect(container).toBeDefined();
20+
});
21+
22+
it('should set version from parent provider', () => {
23+
const initialRelease = { versionWithPrefix: 'v14.17.0' };
24+
const releases = [initialRelease];
25+
const snippets = [];
26+
27+
const { getByText } = render(
28+
<ReleasesProvider releases={releases} snippets={snippets}>
29+
<ReleaseProvider initialRelease={initialRelease}>
30+
<ReleaseProvider>
31+
<div>Child Provider</div>
32+
</ReleaseProvider>
33+
</ReleaseProvider>
34+
</ReleasesProvider>
35+
);
36+
37+
expect(getByText('Child Provider')).toBeDefined();
38+
});
39+
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import reducer, { releaseState, getActions } from '@/reducers/releaseReducer';
2+
3+
describe('releaseReducer', () => {
4+
it('should return the initial state', () => {
5+
const initialState = releaseState;
6+
const action = { type: 'UNKNOWN_ACTION' };
7+
expect(reducer(initialState, action)).toEqual(initialState);
8+
});
9+
10+
it('should handle SET_VERSION action', () => {
11+
const initialState = releaseState;
12+
const action = { type: 'SET_VERSION', payload: 'v14.17.0' };
13+
const expectedState = { ...initialState, version: 'v14.17.0' };
14+
expect(reducer(initialState, action)).toEqual(expectedState);
15+
});
16+
17+
it('should handle SET_OS action', () => {
18+
const initialState = releaseState;
19+
const action = { type: 'SET_OS', payload: 'Linux' };
20+
const expectedState = { ...initialState, os: 'Linux' };
21+
expect(reducer(initialState, action)).toEqual(expectedState);
22+
});
23+
24+
it('should handle SET_PLATFORM action', () => {
25+
const initialState = releaseState;
26+
const action = { type: 'SET_PLATFORM', payload: 'arm64' };
27+
const expectedState = { ...initialState, platform: 'arm64' };
28+
expect(reducer(initialState, action)).toEqual(expectedState);
29+
});
30+
31+
it('should handle SET_INSTALL_METHOD action', () => {
32+
const initialState = releaseState;
33+
const action = { type: 'SET_INSTALL_METHOD', payload: 'binary' };
34+
const expectedState = { ...initialState, installMethod: 'binary' };
35+
expect(reducer(initialState, action)).toEqual(expectedState);
36+
});
37+
38+
it('should handle SET_MANAGER action', () => {
39+
const initialState = releaseState;
40+
const action = { type: 'SET_MANAGER', payload: 'Yarn' };
41+
const expectedState = { ...initialState, packageManager: 'Yarn' };
42+
expect(reducer(initialState, action)).toEqual(expectedState);
43+
});
44+
});
45+
46+
describe('getActions', () => {
47+
it('should create actions correctly', () => {
48+
const dispatch = jest.fn();
49+
const actions = getActions(dispatch);
50+
51+
actions.setVersion('v14.17.0');
52+
expect(dispatch).toHaveBeenCalledWith({
53+
type: 'SET_VERSION',
54+
payload: 'v14.17.0',
55+
});
56+
57+
actions.setOS('Linux');
58+
expect(dispatch).toHaveBeenCalledWith({ type: 'SET_OS', payload: 'Linux' });
59+
60+
actions.setPlatform('arm64');
61+
expect(dispatch).toHaveBeenCalledWith({
62+
type: 'SET_PLATFORM',
63+
payload: 'arm64',
64+
});
65+
66+
actions.setInstallMethod('binary');
67+
expect(dispatch).toHaveBeenCalledWith({
68+
type: 'SET_INSTALL_METHOD',
69+
payload: 'binary',
70+
});
71+
72+
actions.setPackageManager('Yarn');
73+
expect(dispatch).toHaveBeenCalledWith({
74+
type: 'SET_MANAGER',
75+
payload: 'Yarn',
76+
});
77+
});
78+
});

apps/site/util/__tests__/authorUtils.test.mjs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import {
22
mapAuthorToCardAuthors,
33
getAuthorWithId,
44
getAuthorWithName,
5-
} from '../authorUtils';
5+
getAuthors,
6+
} from '@/util/authorUtils';
67

78
describe('mapAuthorToCardAuthors', () => {
89
it('maps authors to card authors with default avatar source', () => {
@@ -96,3 +97,25 @@ describe('getAuthorWithName', () => {
9697
]);
9798
});
9899
});
100+
101+
describe('authorUtils', () => {
102+
test('mapAuthorToCardAuthors splits authors by common separators', () => {
103+
const result = mapAuthorToCardAuthors('Node, React & prepared by Vue');
104+
expect(result).toEqual(['Node', 'React', 'Vue']);
105+
});
106+
107+
test('getAuthorWithId returns objects with GitHub avatars', () => {
108+
const result = getAuthorWithId(['someUser'], false);
109+
expect(result[0].image).toContain('github');
110+
});
111+
112+
test('getAuthorWithName returns known author details or fallback to acronym', () => {
113+
const result = getAuthorWithName(['unknownAuthor'], true);
114+
expect(result[0].fallback).toBe('U');
115+
});
116+
117+
test('getAuthors uses getAuthorWithId if usernames array is provided', () => {
118+
const result = getAuthors({ usernames: ['testUser'] });
119+
expect(result[0].nickname).toBe('testUser');
120+
});
121+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { mapBlogCategoryToPreviewType } from '@/util/blogUtils';
2+
3+
describe('mapBlogCategoryToPreviewType', () => {
4+
test('returns the correct preview type for recognized categories', () => {
5+
expect(mapBlogCategoryToPreviewType('release')).toBe('release');
6+
expect(mapBlogCategoryToPreviewType('events')).toBe('announcements');
7+
});
8+
9+
test('defaults to announcements for unknown categories', () => {
10+
expect(mapBlogCategoryToPreviewType('random')).toBe('announcements');
11+
});
12+
});
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { dateIsBetween } from '@/util/dateUtils';
22

33
describe('dateIsBetween', () => {
4-
it('returns true when the current date is between start and end dates', () => {
4+
it('should return true when the current date is between start and end dates', () => {
55
const startDate = '2022-01-01T00:00:00.000Z';
66
const endDate = '2069-01-01T00:00:00.000Z';
77

@@ -10,7 +10,7 @@ describe('dateIsBetween', () => {
1010
expect(result).toBe(true);
1111
});
1212

13-
it('returns false when the current date is not between start and end dates', () => {
13+
it('should return false when the current date is not between start and end dates', () => {
1414
const startDate = '2010-01-01T00:00:00.000Z';
1515
const endDate = '2020-01-01T00:00:00.000Z';
1616

@@ -19,12 +19,22 @@ describe('dateIsBetween', () => {
1919
expect(result).toBe(false);
2020
});
2121

22-
it('throws when either start or end date is invalid', () => {
22+
it('should throw an error when either start or end date is invalid', () => {
2323
const invalidStartDate = 'Invalid Start Date';
2424
const validEndDate = '2024-01-01T00:00:00.000Z';
2525

2626
expect(() => dateIsBetween(invalidStartDate, validEndDate)).toThrow(
2727
'dateIsBetween got called with invalid dates'
2828
);
2929
});
30+
31+
it('should return true if now is between startDate and endDate', () => {
32+
const start = new Date(Date.now() - 1000).toISOString();
33+
const end = new Date(Date.now() + 1000).toISOString();
34+
expect(dateIsBetween(start, end)).toBe(true);
35+
});
36+
37+
it('should throw an error if dates are invalid', () => {
38+
expect(() => dateIsBetween('invalid', 'invalid')).toThrow();
39+
});
3040
});

apps/site/util/__tests__/debounce.test.mjs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { debounce } from '@/util/debounce';
22

3-
describe('debounce', () => {
4-
jest.useFakeTimers();
3+
jest.useFakeTimers();
54

5+
describe('debounce', () => {
66
it('should call the function only once', () => {
77
const fn = jest.fn();
88
const debouncedFn = debounce(fn, 1000);
@@ -28,4 +28,15 @@ describe('debounce', () => {
2828

2929
expect(fn).toHaveBeenCalledWith(3);
3030
});
31+
32+
it('should call the function after the delay', () => {
33+
const mockFn = jest.fn();
34+
const debouncedFn = debounce(mockFn, 500);
35+
36+
debouncedFn();
37+
expect(mockFn).not.toBeCalled();
38+
39+
jest.advanceTimersByTime(500);
40+
expect(mockFn).toBeCalled();
41+
});
3142
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import deepMerge from '@/util/deepMerge';
2+
3+
describe('deepMerge', () => {
4+
it('should merge nested objects', () => {
5+
const obj1 = { a: { b: 1 }, c: 2 };
6+
const obj2 = { a: { d: 3 }, e: 4 };
7+
const result = deepMerge(obj1, obj2);
8+
expect(result).toEqual({ a: { b: 1, d: 3 }, c: 2, e: 4 });
9+
});
10+
11+
it('should overwrite primitive properties', () => {
12+
const obj1 = { a: 1 };
13+
const obj2 = { a: 2 };
14+
const result = deepMerge(obj1, obj2);
15+
expect(result).toEqual({ a: 2 });
16+
});
17+
});

0 commit comments

Comments
 (0)