Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React from 'react';
import * as useCreateChannelModule from '../../../context/useCreateChannel';
import { CHANNEL_TYPE } from '../../../types';
import { act, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { LocalizationContext } from '../../../../../lib/LocalizationContext';
import CreateChannelUI from '../index';

jest.mock('../../../../../hooks/useSendbirdStateContext', () => ({
__esModule: true,
default: jest.fn(() => ({
stores: {
userStore: {
user: {
userId: ' test-user-id',
},
},
sdkStore: {
sdk: {
currentUser: {
userId: 'test-user-id',
},
createApplicationUserListQuery: () => ({
next: () => Promise.resolve([{ userId: 'test-user-id' }]),
isLoading: false,
}),
},
initialized: true,
},
},
config: {
logger: console,
userId: 'test-user-id',
groupChannel: {
enableMention: true,
},
isOnline: true,
},
})),
}));
jest.mock('../../../context/useCreateChannel');

const mockStringSet = {
MODAL__CREATE_CHANNEL__TITLE: 'CREATE_CHANNEL',
MODAL__INVITE_MEMBER__SELECTED: 'USERS_SELECTED',
};

const mockLocalizationContext = {
stringSet: mockStringSet,
};

const defaultMockState = {
sdk: undefined,
userListQuery: undefined,
onCreateChannelClick: undefined,
onChannelCreated: undefined,
onBeforeCreateChannel: undefined,
pageStep: 0,
type: CHANNEL_TYPE.GROUP,
onCreateChannel: undefined,
overrideInviteUser: undefined,
};

const defaultMockActions = {
setPageStep: jest.fn(),
setType: jest.fn(),
};

describe('CreateChannelUI Integration Tests', () => {
const mockUseCreateChannel = useCreateChannelModule.default as jest.Mock;

const renderComponent = (mockState = {}, mockActions = {}) => {
mockUseCreateChannel.mockReturnValue({
state: { ...defaultMockState, ...mockState },
actions: { ...defaultMockActions, ...mockActions },
});

return render(
<LocalizationContext.Provider value={mockLocalizationContext as any}>
<CreateChannelUI />
</LocalizationContext.Provider>,
);
};

beforeEach(() => {
jest.clearAllMocks();
document.body.innerHTML = `
<div id='sendbird-modal-root' />
`;
});

it('display initial state correctly', () => {
renderComponent();

expect(screen.getByText('CREATE_CHANNEL')).toBeInTheDocument();
});

it('display SelectChannelType when pageStep is 0', () => {
renderComponent({ pageStep: 0 });

expect(screen.getByText('CREATE_CHANNEL')).toBeInTheDocument();
});

it('display InviteUsers when pageStep is 1', async () => {
await act(async () => {
renderComponent({ pageStep: 1 });
});

expect(screen.getByText('0 USERS_SELECTED')).toBeInTheDocument();
});

});
20 changes: 12 additions & 8 deletions src/modules/CreateChannel/components/CreateChannelUI/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import './create-channel-ui.scss';

import React from 'react';

import { useCreateChannelContext } from '../../context/CreateChannelProvider';
import InviteUsers from '../InviteUsers';

import SelectChannelType from '../SelectChannelType';
import useCreateChannel from '../../context/useCreateChannel';

export interface CreateChannelUIProps {
onCancel?(): void;
Expand All @@ -16,15 +16,19 @@ const CreateChannel: React.FC<CreateChannelUIProps> = (props: CreateChannelUIPro
const { onCancel, renderStepOne } = props;

const {
step,
setStep,
userListQuery,
} = useCreateChannelContext();
state: {
pageStep,
userListQuery,
},
actions: {
setPageStep,
},
} = useCreateChannel();

return (
<>
{
step === 0 && (
pageStep === 0 && (
renderStepOne?.() || (
<SelectChannelType
onCancel={onCancel}
Expand All @@ -33,11 +37,11 @@ const CreateChannel: React.FC<CreateChannelUIProps> = (props: CreateChannelUIPro
)
}
{
step === 1 && (
pageStep === 1 && (
<InviteUsers
userListQuery={userListQuery}
onCancel={() => {
setStep(0);
setPageStep(0);
onCancel?.();
}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,90 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import '@testing-library/jest-dom/matchers';
import InviteUsers from '../index';
import { ApplicationUserListQuery } from '@sendbird/chat';
import { SendbirdSdkContext } from '../../../../../lib/SendbirdSdkContext';
import { SendBirdState } from '../../../../../lib/types';

jest.mock('../../../context/CreateChannelProvider', () => ({
useCreateChannelContext: jest.fn(() => ({
onBeforeCreateChannel: jest.fn(),
onCreateChannel: jest.fn(),
overrideInviteUser: jest.fn(),
createChannel: jest.fn().mockResolvedValue({}),
type: 'group',
import { CHANNEL_TYPE } from '../../../types';
import * as useCreateChannelModule from '../../../context/useCreateChannel';
import { LocalizationContext } from '../../../../../lib/LocalizationContext';

jest.mock('../../../../../hooks/useSendbirdStateContext', () => ({
__esModule: true,
default: jest.fn(() => ({
stores: {
sdkStore: {
sdk: {
currentUser: {
userId: 'test-user-id',
},
},
initialized: true,
},
},
config: { logger: console },
})),
}));
jest.mock('../../../context/useCreateChannel');

// Mock createPortal function to render content directly without portal
jest.mock('react-dom', () => ({
...jest.requireActual('react-dom'),
createPortal: (node) => node,
}));

const mockStringSet = {
MODAL__CREATE_CHANNEL__TITLE: 'CREATE_CHANNEL',
MODAL__INVITE_MEMBER__SELECTED: 'USERS_SELECTED',
BUTTON__CREATE: 'CREATE',
};

const mockLocalizationContext = {
stringSet: mockStringSet,
};

const defaultMockState = {
sdk: undefined,
createChannel: undefined,
userListQuery: undefined,
onCreateChannelClick: undefined,
onChannelCreated: undefined,
onBeforeCreateChannel: undefined,
step: 0,
type: CHANNEL_TYPE.GROUP,
onCreateChannel: undefined,
overrideInviteUser: undefined,
};

const defaultMockActions = {
setStep: jest.fn(),
setType: jest.fn(),
};

const defaultMockInvitUserState = {
user: { userId: 'test-user-id' },
};

describe('InviteUsers', () => {
const mockUseCreateChannel = useCreateChannelModule.default as jest.Mock;

const renderComponent = (mockState = {}, mockActions = {}, mockInviteUsersState = {}) => {
mockUseCreateChannel.mockReturnValue({
state: { ...defaultMockState, ...mockState },
actions: { ...defaultMockActions, ...mockActions },
});

const inviteUserProps = { ...defaultMockInvitUserState, ...mockInviteUsersState };

return render(
<LocalizationContext.Provider value={mockLocalizationContext as any}>
<InviteUsers {...inviteUserProps}/>
</LocalizationContext.Provider>,
);
};

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

it('should enable the modal submit button when there is only the logged-in user is in the user list', async () => {
const userListQuery = jest.fn(
() => ({
Expand All @@ -32,13 +93,9 @@ describe('InviteUsers', () => {
} as unknown as ApplicationUserListQuery),
);

render(
<SendbirdSdkContext.Provider value={{} as SendBirdState}>
<InviteUsers userListQuery={userListQuery} />
</SendbirdSdkContext.Provider>,
);
renderComponent({}, {}, { userListQuery });

expect(await screen.findByText('Create')).toBeEnabled();
expect(await screen.findByText('CREATE')).toBeEnabled();
});

// TODO: add this case too
Expand Down
22 changes: 13 additions & 9 deletions src/modules/CreateChannel/components/InviteUsers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { GroupChannelCreateParams } from '@sendbird/chat/groupChannel';

import './invite-users.scss';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
import { useCreateChannelContext } from '../../context/CreateChannelProvider';
import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useMediaQueryContext } from '../../../../lib/MediaQueryContext';
import Modal from '../../../../ui/Modal';
Expand All @@ -15,6 +14,7 @@ import UserListItem from '../../../../ui/UserListItem';
import { createDefaultUserListQuery, filterUser, setChannelType } from './utils';
import { noop } from '../../../../utils/utils';
import { UserListQuery } from '../../../../types';
import useCreateChannel from '../../context/useCreateChannel';

export interface InviteUsersProps {
onCancel?: () => void;
Expand All @@ -28,14 +28,18 @@ const InviteUsers: React.FC<InviteUsersProps> = ({
userListQuery,
}: InviteUsersProps) => {
const {
onCreateChannelClick,
onBeforeCreateChannel,
onChannelCreated,
createChannel,
onCreateChannel,
overrideInviteUser,
type,
} = useCreateChannelContext();
state: {
onCreateChannelClick,
onBeforeCreateChannel,
onChannelCreated,
onCreateChannel,
overrideInviteUser,
type,
},
actions: {
createChannel,
},
} = useCreateChannel();

const globalStore = useSendbirdStateContext();
const userId = globalStore?.config?.userId;
Expand Down
Loading