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-4657] Provider migration - P0 items #1269

Merged
merged 46 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
67105ee
[CLNP-5043] Migrate MessageSearchProvider (#1216)
AhyoungRyu Sep 27, 2024
77f5395
refactor: ChannelSettingsProvider migration (#1229)
HoonBaek Oct 11, 2024
4689d79
[CLNP-5043] Add unit tests for improved MessageSearch module (#1228)
AhyoungRyu Oct 14, 2024
1e980b8
refactor: GroupChannelList migration (#1231)
git-babel Oct 17, 2024
3bd9b40
refactor: Add tests for ChannelSettings migration (#1234)
HoonBaek Oct 22, 2024
0cc69d5
refactor: Add unit tests for new GroupChannelListProvider (#1233)
git-babel Oct 23, 2024
2720797
[CLNP-5047] Migrate GroupChannelProvider to new state management patt…
AhyoungRyu Nov 19, 2024
6a88cc9
[CLNP-5045] CreateChannelProvider Migration (#1243)
git-babel Nov 28, 2024
9931db0
[CLNP-5046] Migrate ThreadProvider to the new state management patter…
git-babel Nov 28, 2024
1abf238
refactor: SendbirdProvider Migration (#1260)
HoonBaek Nov 29, 2024
3a5c833
[CLNP-5907] fix: update group channel list state properly (#1261)
AhyoungRyu Nov 29, 2024
bfd8141
[CLNP-5817][CLNP-5918] fix: scroll & search message issues in GroupCh…
AhyoungRyu Dec 2, 2024
a689dd3
[CLNP-5914] Fix unit tests and UI error (#1267)
git-babel Dec 2, 2024
99a765f
Used useDeepCompareEffect for the updateState of SendbirdProvider (#1…
HoonBaek Dec 2, 2024
9d6558f
Resolve conflict after rebase from main
AhyoungRyu Dec 3, 2024
c92fd25
[CLNP-5974] Add more GroupChannel module custom hook unit tests (#1271)
AhyoungRyu Dec 5, 2024
6e4a14a
Use useEffect instead of useDeepCompareEffect in GroupChannelListProv…
AhyoungRyu Dec 6, 2024
37f0f25
[CLNP-5981] fix blinking GroupChannel on switching to another (#1277)
AhyoungRyu Dec 6, 2024
db30b62
chore: Add tests for SendbirdProvider migration (#1275)
HoonBaek Dec 6, 2024
6f0e194
Add basic test cases for the new `ThreadProvider` (#1274)
git-babel Dec 9, 2024
dc48275
[CLNP-6010] Add more unit tests for existing message search custom ho…
AhyoungRyu Dec 9, 2024
4101889
[CLNP-6022] fix scroll position issue when switching GroupChannel (#1…
AhyoungRyu Dec 10, 2024
21a625d
Resolve conflicts
AhyoungRyu Dec 11, 2024
5890933
used useSendbird for mocking instead of useSendbirdStateContext
HoonBaek Dec 11, 2024
9c9f520
Fix migration test failure (#1285)
git-babel Dec 12, 2024
38ff25b
[CLNP-6003] test: Add tests for hooks in `src/hooks` (#1283)
git-babel Dec 13, 2024
9c2f8b3
Merge branch 'main' into feat/state-mgmt-migration-1
git-babel Dec 13, 2024
7d4b638
Fix merge error
git-babel Dec 13, 2024
8ca7861
Fix lint error
git-babel Dec 13, 2024
2c0387f
[CLNP-6022] Memoize useGroupChannel actions to prevent unnecessary re…
AhyoungRyu Dec 16, 2024
82a93b4
Add minor util tests (#1294)
git-babel Jan 9, 2025
f25d29f
fix: update and propagate `groupChannel` state properly (#1298)
git-babel Jan 14, 2025
98f1626
react 19 fix
chrisallo Feb 3, 2025
81cf8db
Merge branch 'main' into feat/state-mgmt-migration-1
git-babel Feb 5, 2025
58d18a5
Revert useSyncExternalStore shim
git-babel Feb 5, 2025
a44e25a
Replace the deprecated @testing-library/react-hooks package
git-babel Feb 5, 2025
803d732
Revert "Replace the deprecated @testing-library/react-hooks package"
git-babel Feb 6, 2025
2de2016
Fix the failed test cases
git-babel Feb 6, 2025
95a97b4
Merge branch 'main' into feat/state-mgmt-migration-1
git-babel Feb 6, 2025
aa503f9
Fix flaky test
git-babel Feb 6, 2025
ce30e68
Fix flaky test 2
git-babel Feb 6, 2025
5c8752b
Fire CI
git-babel Feb 6, 2025
79de69c
Fire CI 2
git-babel Feb 6, 2025
97c84fe
Fix flaky tests 3
git-babel Feb 6, 2025
4185743
Use 'use-sync-external-store-shim' instead of React built-in
git-babel Feb 7, 2025
6d8085b
Update export setup for the custom hooks
git-babel Feb 7, 2025
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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "^22.7.2",
"@types/use-sync-external-store": "^0.0.6",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"autoprefixer": "^9.7.4",
Expand Down Expand Up @@ -148,6 +149,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
19 changes: 10 additions & 9 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 @@ -49,7 +50,7 @@ export default {

// GroupChannelList
GroupChannelList: 'src/modules/GroupChannelList/index.tsx',
'GroupChannelList/context': 'src/modules/GroupChannelList/context/GroupChannelListProvider.tsx',
'GroupChannelList/context': 'src/modules/GroupChannelList/context/index.tsx',
'GroupChannelList/components/AddGroupChannel': 'src/modules/GroupChannelList/components/AddGroupChannel/index.tsx',
'GroupChannelList/components/GroupChannelListUI': 'src/modules/GroupChannelList/components/GroupChannelListUI/index.tsx',
'GroupChannelList/components/GroupChannelListHeader': 'src/modules/GroupChannelList/components/GroupChannelListHeader/index.tsx',
Expand All @@ -58,7 +59,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 Expand Up @@ -93,7 +94,7 @@ export default {
'Channel/components/SuggestedMentionList': 'src/modules/Channel/components/SuggestedMentionList/index.tsx',

GroupChannel: 'src/modules/GroupChannel/index.tsx',
'GroupChannel/context': 'src/modules/GroupChannel/context/GroupChannelProvider.tsx',
'GroupChannel/context': 'src/modules/GroupChannel/context/index.tsx',
'GroupChannel/components/GroupChannelHeader': 'src/modules/GroupChannel/components/GroupChannelHeader/index.tsx',
'GroupChannel/components/GroupChannelUI': 'src/modules/GroupChannel/components/GroupChannelUI/index.tsx',
'GroupChannel/components/FileViewer': 'src/modules/GroupChannel/components/FileViewer/index.tsx',
Expand Down Expand Up @@ -139,7 +140,7 @@ export default {

// MessageSearch
MessageSearch: 'src/modules/MessageSearch/index.tsx',
'MessageSearch/context': 'src/modules/MessageSearch/context/MessageSearchProvider.tsx',
'MessageSearch/context': 'src/modules/MessageSearch/context/index.tsx',
'MessageSearch/components/MessageSearchUI': 'src/modules/MessageSearch/components/MessageSearchUI/index.tsx',

// Message
Expand All @@ -148,7 +149,7 @@ export default {

// Thread
Thread: 'src/modules/Thread/index.tsx',
'Thread/context': 'src/modules/Thread/context/ThreadProvider.tsx',
'Thread/context': 'src/modules/Thread/context/index.tsx',
'Thread/context/types': 'src/modules/Thread/types.tsx',
'Thread/components/ThreadUI': 'src/modules/Thread/components/ThreadUI/index.tsx',
'Thread/components/ThreadHeader': 'src/modules/Thread/components/ThreadHeader/index.tsx',
Expand All @@ -160,7 +161,7 @@ export default {

// CreateChannel
CreateChannel: 'src/modules/CreateChannel/index.tsx',
'CreateChannel/context': 'src/modules/CreateChannel/context/CreateChannelProvider.tsx',
'CreateChannel/context': 'src/modules/CreateChannel/context/index.tsx',
'CreateChannel/components/CreateChannelUI': 'src/modules/CreateChannel/components/CreateChannelUI/index.tsx',
'CreateChannel/components/InviteUsers': 'src/modules/CreateChannel/components/InviteUsers/index.tsx',
'CreateChannel/components/SelectChannelType': 'src/modules/CreateChannel/components/SelectChannelType.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
48 changes: 48 additions & 0 deletions src/hooks/__tests__/useAsyncRequest.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { act, renderHook } from '@testing-library/react';
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 act(async () => {
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 act(async () => {
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';
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);
});

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

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();
});
});

});
37 changes: 37 additions & 0 deletions src/hooks/__tests__/useMouseHover.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { renderHook, 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);
});
});

});
34 changes: 34 additions & 0 deletions src/hooks/__tests__/useOutsideAlerter.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { renderHook, 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