Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CLNP-6003] test: Add tests for hooks in src/hooks #1283

Open
wants to merge 27 commits into
base: feat/state-mgmt-migration-1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d47d507
[CLNP-5043] Migrate MessageSearchProvider (#1216)
AhyoungRyu Sep 27, 2024
ffd1927
refactor: ChannelSettingsProvider migration (#1229)
HoonBaek Oct 11, 2024
4ad373d
[CLNP-5043] Add unit tests for improved MessageSearch module (#1228)
AhyoungRyu Oct 14, 2024
e344b3b
refactor: GroupChannelList migration (#1231)
git-babel Oct 17, 2024
dd4d887
refactor: Add tests for ChannelSettings migration (#1234)
HoonBaek Oct 22, 2024
2a92ef3
refactor: Add unit tests for new GroupChannelListProvider (#1233)
git-babel Oct 23, 2024
ccf5ce7
Fix build error of migration branch (#1245)
git-babel Nov 5, 2024
ee3b8e2
[CLNP-5047] Migrate GroupChannelProvider to new state management patt…
AhyoungRyu Nov 19, 2024
3f59614
[CLNP-5045] CreateChannelProvider Migration (#1243)
git-babel Nov 28, 2024
4611fe9
[CLNP-5046] Migrate ThreadProvider to the new state management patter…
git-babel Nov 28, 2024
700c39b
refactor: SendbirdProvider Migration (#1260)
HoonBaek Nov 29, 2024
45d808d
[CLNP-5907] fix: update group channel list state properly (#1261)
AhyoungRyu Nov 29, 2024
e4cf042
[CLNP-5817][CLNP-5918] fix: scroll & search message issues in GroupCh…
AhyoungRyu Dec 2, 2024
09a54b5
[CLNP-5914] Fix unit tests and UI error (#1267)
git-babel Dec 2, 2024
a618b44
Used useDeepCompareEffect for the updateState of SendbirdProvider (#1…
HoonBaek Dec 2, 2024
ca70cca
Resolve conflict after rebase from main
AhyoungRyu Dec 3, 2024
8d1bfaa
[CLNP-5974] Add more GroupChannel module custom hook unit tests (#1271)
AhyoungRyu Dec 5, 2024
8a4263a
Use useEffect instead of useDeepCompareEffect in GroupChannelListProv…
AhyoungRyu Dec 6, 2024
7590607
[CLNP-5981] fix blinking GroupChannel on switching to another (#1277)
AhyoungRyu Dec 6, 2024
5b35b02
chore: Add tests for SendbirdProvider migration (#1275)
HoonBaek Dec 6, 2024
b9e7602
Add basic test cases for the new `ThreadProvider` (#1274)
git-babel Dec 9, 2024
766d1d7
[CLNP-6010] Add more unit tests for existing message search custom ho…
AhyoungRyu Dec 9, 2024
aa9c1aa
Add unit tests for the hooks in 'src/hooks'
git-babel Dec 10, 2024
502f1a4
Fix lint errors
git-babel Dec 10, 2024
68e0cb8
[CLNP-6022] fix scroll position issue when switching GroupChannel (#1…
AhyoungRyu Dec 10, 2024
b34100b
Merge branch 'feat/state-mgmt-migration-1' into feat/add_hook_tests
AhyoungRyu Dec 10, 2024
e36e235
Remove ununsed hook and test
git-babel Dec 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import type { Preview } from '@storybook/react';
import { SendbirdSdkContext } from '../src/lib/SendbirdSdkContext';
import { SendbirdContext } from '../src/lib/Sendbird/context/SendbirdContext';

import '../src/lib/index.scss';
import './index.css';
Expand Down Expand Up @@ -28,9 +28,9 @@ const preview: Preview = {
decorators: [
(Story) => (
<div className="sendbird-theme--light">
<SendbirdSdkContext.Provider value={{} as any}>
<SendbirdContext.Provider value={{} as any}>
{Story()}
</SendbirdSdkContext.Provider>
</SendbirdContext.Provider>
</div>
),
],
Expand Down
2 changes: 1 addition & 1 deletion apps/testing/src/utils/paramsBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UIKitOptions } from '../../../../src/lib/types.ts';
import { UIKitOptions } from '../../../../src/lib/Sendbird/types';
import { useSearchParams } from 'react-router-dom';

export interface InitialParams {
Expand Down
5 changes: 5 additions & 0 deletions apps/testing/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import postcssRtlOptions from '../../postcssRtlOptions.mjs';
export default defineConfig({
plugins: [react(), vitePluginSvgr({ include: '**/*.svg' })],
css: {
preprocessorOptions: {
scss: {
silenceDeprecations: ['legacy-js-api'],
},
},
postcss: {
plugins: [postcssRtl(postcssRtlOptions)],
},
Expand Down
1 change: 1 addition & 0 deletions jest-setup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import './__mocks__/intersectionObserverMock';
import '@testing-library/jest-dom';

const { JSDOM } = require('jsdom');

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"ts-pattern": "^4.2.2",
"typedoc": "^0.25.13",
"typescript": "^5.4.5",
"use-sync-external-store": "^1.2.2",
"vite": "^5.1.5",
"vite-plugin-svgr": "^4.2.0"
},
Expand Down
9 changes: 5 additions & 4 deletions rollup.module-exports.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ export default {
App: 'src/modules/App/index.tsx',

// SendbirdProvider
SendbirdProvider: 'src/lib/Sendbird.tsx',
SendbirdProvider: 'src/lib/Sendbird/index.tsx',
sendbirdSelectors: 'src/lib/selectors.ts',
useSendbirdStateContext: 'src/hooks/useSendbirdStateContext.tsx',
withSendbird: 'src/lib/SendbirdSdkContext.tsx',
// TODO: Support below legacy exports
// useSendbirdStateContext: 'src/hooks/useSendbirdStateContext.tsx',
// withSendbird: 'src/lib/SendbirdSdkContext.tsx',

// Voice message
'VoiceRecorder/context': 'src/hooks/VoiceRecorder/index.tsx',
Expand Down Expand Up @@ -57,7 +58,7 @@ export default {

// ChannelSettings
ChannelSettings: 'src/modules/ChannelSettings/index.tsx',
'ChannelSettings/context': 'src/modules/ChannelSettings/context/ChannelSettingsProvider.tsx',
'ChannelSettings/context': 'src/modules/ChannelSettings/context/index.tsx',
'ChannelSettings/hooks/useMenuList': 'src/modules/ChannelSettings/components/ChannelSettingsUI/hooks/useMenuItems.tsx',
'ChannelSettings/components/ChannelProfile': 'src/modules/ChannelSettings/components/ChannelProfile/index.tsx',
'ChannelSettings/components/ChannelSettingsUI': 'src/modules/ChannelSettings/components/ChannelSettingsUI/index.tsx',
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/VoicePlayer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import {
VOICE_PLAYER_AUDIO_ID,
VOICE_PLAYER_ROOT_ID,
} from '../../utils/consts';
import useSendbirdStateContext from '../useSendbirdStateContext';
import { getParsedVoiceAudioFileInfo } from './utils';
import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';

// VoicePlayerProvider interface
export interface VoicePlayerProps {
Expand Down Expand Up @@ -64,7 +64,8 @@ export const VoicePlayerProvider = ({
currentPlayer,
audioStorage,
} = voicePlayerStore;
const { config } = useSendbirdStateContext();
const { state } = useSendbird();
const { config } = state;
const { logger } = config;

const stop = (text = '') => {
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/VoiceRecorder/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
VOICE_MESSAGE_MIME_TYPE,
VOICE_RECORDER_AUDIO_BIT_RATE,
} from '../../utils/consts';
import useSendbirdStateContext from '../useSendbirdStateContext';
import { type WebAudioUtils } from './WebAudioUtils';
import { noop } from '../../utils/utils';
import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';

// Input props of VoiceRecorder
export interface VoiceRecorderProps {
Expand All @@ -37,7 +37,8 @@ const Context = createContext<VoiceRecorderContext>({

export const VoiceRecorderProvider = (props: VoiceRecorderProps): React.ReactElement => {
const { children } = props;
const { config } = useSendbirdStateContext();
const { state } = useSendbird();
const { config } = state;
const { logger, groupChannel } = config;
const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);
const [isRecordable, setIsRecordable] = useState<boolean>(false);
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/VoiceRecorder/useVoiceRecorder.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { VoiceRecorderEventHandler, useVoiceRecorderContext } from '.';
import useSendbirdStateContext from '../useSendbirdStateContext';
import { noop } from '../../utils/utils';
import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';

// export interface UseVoiceRecorderProps extends VoiceRecorderEventHandler {
// /**
Expand Down Expand Up @@ -31,7 +31,8 @@ export const useVoiceRecorder = ({
onRecordingStarted = noop,
onRecordingEnded = noop,
}: VoiceRecorderEventHandler): UseVoiceRecorderContext => {
const { config } = useSendbirdStateContext();
const { state } = useSendbird();
const { config } = state;
const { voiceRecord } = config;
const maxRecordingTime = voiceRecord.maxRecordingTime;
const voiceRecorder = useVoiceRecorderContext();
Expand Down
44 changes: 44 additions & 0 deletions src/hooks/__tests__/useAsyncRequest.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { renderHook } from '@testing-library/react-hooks';
import { useAsyncRequest } from '../useAsyncRequest';

describe('useAsyncRequest', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('handle request with no response correctly', async () => {
const mockPromise = Promise.resolve();
const mockRequest = jest.fn().mockReturnValue(mockPromise);

const { result } = renderHook(() => useAsyncRequest(mockRequest));

await mockPromise;

expect(result.current.loading).toBe(false);
});

it('handle request with response correctly', async () => {
const mockResponse = { code: 'ok' };
const mockPromise = Promise.resolve(mockResponse);
const mockRequest = jest.fn().mockReturnValue(mockPromise);

const { result } = renderHook(() => useAsyncRequest(mockRequest));

await mockPromise;

expect(result.current.response).toBe(mockResponse);
expect(result.current.loading).toBe(false);
});

it('cancel request correctly', async () => {
const mockCancel = jest.fn();
const mockRequest = { cancel: mockCancel };

const { unmount } = renderHook(() => useAsyncRequest(mockRequest));

unmount();

expect(mockCancel).toBeCalled();
});

});
28 changes: 28 additions & 0 deletions src/hooks/__tests__/useDebounce.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { renderHook } from '@testing-library/react-hooks';
import { useDebounce } from '../useDebounce';

describe('useAsyncRequest', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('handle useDebounce correctly', async () => {
const mockFunction = jest.fn();
const { result } = renderHook(() => useDebounce(mockFunction, 1000));

const debounceFunction = result.current;

debounceFunction();
debounceFunction();
debounceFunction();
debounceFunction();
debounceFunction();

await new Promise(resolve => {
setTimeout(resolve, 1000);
});

expect(mockFunction).toBeCalledTimes(1);
});

});
63 changes: 63 additions & 0 deletions src/hooks/__tests__/useLongPress.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import useLongPress from '../useLongPress';
import { screen, fireEvent, render, waitFor } from '@testing-library/react';

describe('useLongPress', () => {

beforeEach(() => {
jest.clearAllMocks();
});

it('handle long press correctly', async () => {
const mockOnLongPress = jest.fn();
const mockOnClick = jest.fn();

const { result } = renderHook(() => useLongPress({
onLongPress: mockOnLongPress,
onClick: mockOnClick,
}));
const { onTouchStart, onTouchEnd } = result.current;

const targetComponent = <div id="target" onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}>touch this</div>;
render(targetComponent);

const element = screen.getByText('touch this');
fireEvent.touchStart(element);
await new Promise(resolve => {
setTimeout(resolve, 1000);
});
fireEvent.touchEnd(element);

await waitFor(() => {
expect(mockOnLongPress).toHaveBeenCalled();
});
});

it('cancel long press if touch is too short', async () => {
const mockOnLongPress = jest.fn();
const mockOnClick = jest.fn();

const { result } = renderHook(() => useLongPress({
onLongPress: mockOnLongPress,
onClick: mockOnClick,
}));
const { onTouchStart, onTouchEnd } = result.current;

const targetComponent = <div id="target" onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}>touch this</div>;
render(targetComponent);

const element = screen.getByText('touch this');
fireEvent.touchStart(element);
await new Promise(resolve => {
setTimeout(resolve, 100);
});
fireEvent.touchEnd(element);

await waitFor(() => {
expect(mockOnClick).toHaveBeenCalled();
expect(mockOnLongPress).not.toHaveBeenCalled();
});
});

});
38 changes: 38 additions & 0 deletions src/hooks/__tests__/useMouseHover.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { screen, fireEvent, render, waitFor } from '@testing-library/react';
import useMouseHover from '../useMouseHover';

describe('useMouseHover', () => {

beforeEach(() => {
jest.clearAllMocks();
});

it('handle mouse over and out correctly', async () => {
const mockSetHover = jest.fn();

const targetComponent = <div id="target">hover</div>;
render(targetComponent);

const hoverElement = screen.getByText('hover');
const ref = {
current: hoverElement,
};

renderHook(() => useMouseHover({
ref,
setHover: mockSetHover,
}));

fireEvent.mouseEnter(hoverElement);
fireEvent.mouseLeave(hoverElement);

await waitFor(() => {
expect(mockSetHover).toHaveBeenCalledTimes(2);
expect(mockSetHover).toHaveBeenCalledWith(true);
expect(mockSetHover).toHaveBeenCalledWith(false);
});
});

});
35 changes: 35 additions & 0 deletions src/hooks/__tests__/useOutsideAlerter.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { screen, fireEvent, render, waitFor } from '@testing-library/react';
import useOutsideAlerter from '../useOutsideAlerter';

describe('useOutsideAlerter', () => {

beforeEach(() => {
jest.clearAllMocks();
});

it('handle click outside correctly', async () => {
const mockClickOutside = jest.fn();

const targetComponent = <div id="target">inside</div>;
render(targetComponent);

const insideElement = screen.getByText('inside');
const ref = {
current: insideElement,
};

renderHook(() => useOutsideAlerter({
ref,
callback: mockClickOutside,
}));

fireEvent.mouseDown(insideElement);

await waitFor(() => {
expect(mockClickOutside).toHaveBeenCalledTimes(1);
});
});

});
Loading