chore: Upgrade React (#32288)

pull/34987/head^2
Tasso Evangelista 3 months ago committed by GitHub
parent d222467a95
commit 8e2c989105
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 830
      .yarn/patches/@tanstack-react-query-npm-5.60.5-04c500b172.patch
  2. 12
      apps/meteor/app/ui-message/client/messageBox/messageBoxFormatting.ts
  3. 5
      apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useAuditMenu.spec.tsx
  4. 8
      apps/meteor/client/NavBarV2/NavBarPagesToolbar/hooks/useMarketPlaceMenu.spec.tsx
  5. 2
      apps/meteor/client/NavBarV2/NavBarSettingsToolbar/hooks/useAdministrationMenu.spec.tsx
  6. 8
      apps/meteor/client/components/CustomScrollbars/CustomScrollbars.tsx
  7. 10
      apps/meteor/client/components/CustomScrollbars/VirtuosoScrollbars.tsx
  8. 1
      apps/meteor/client/components/GenericModal/GenericModal.spec.tsx
  9. 12
      apps/meteor/client/components/InfoPanel/InfoPanel.stories.tsx
  10. 2
      apps/meteor/client/components/InfoPanel/RetentionPolicyCallout.spec.tsx
  11. 2
      apps/meteor/client/components/MarkdownText.spec.tsx
  12. 2
      apps/meteor/client/components/Omnichannel/hooks/useDepartmentsList.spec.ts
  13. 2
      apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx
  14. 6
      apps/meteor/client/components/Omnichannel/modals/TranscriptModal.spec.tsx
  15. 6
      apps/meteor/client/components/Page/Page.stories.tsx
  16. 2
      apps/meteor/client/components/SidebarToggler/SidebarTogglerBadge.tsx
  17. 3
      apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated.tsx
  18. 3
      apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultipleOptions.tsx
  19. 4
      apps/meteor/client/components/UserStatusMenu.tsx
  20. 1
      apps/meteor/client/components/WarningModal.spec.tsx
  21. 13
      apps/meteor/client/components/message/content/ThreadMetrics.spec.tsx
  22. 2
      apps/meteor/client/components/message/content/reactions/useToggleReactionMutation.spec.tsx
  23. 3
      apps/meteor/client/components/message/variants/RoomMessage.spec.tsx
  24. 8
      apps/meteor/client/hooks/roomActions/useE2EERoomAction.spec.ts
  25. 5
      apps/meteor/client/hooks/useAirGappedRestriction.spec.ts
  26. 8
      apps/meteor/client/hooks/useDecryptedMessage.spec.ts
  27. 8
      apps/meteor/client/hooks/useOTR.spec.tsx
  28. 13
      apps/meteor/client/hooks/usePruneWarningMessage.spec.ts
  29. 2
      apps/meteor/client/hooks/useRoomIcon.tsx
  30. 3
      apps/meteor/client/hooks/useSortQueryOptions.spec.tsx
  31. 10
      apps/meteor/client/lib/createReactiveSubscriptionFactory.ts
  32. 1
      apps/meteor/client/omnichannel/cannedResponses/CannedResponseEdit.tsx
  33. 6
      apps/meteor/client/omnichannel/cannedResponses/components/CannedResponseForm.tsx
  34. 2
      apps/meteor/client/omnichannel/cannedResponses/contextualBar/CannedResponse/CannedResponseList.tsx
  35. 3
      apps/meteor/client/omnichannel/cannedResponses/modals/CreateCannedResponse/CreateCannedResponseModal.tsx
  36. 1
      apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx
  37. 11
      apps/meteor/client/sidebar/Item/Condensed.tsx
  38. 19
      apps/meteor/client/sidebar/Item/Extended.tsx
  39. 11
      apps/meteor/client/sidebar/Item/Medium.tsx
  40. 1
      apps/meteor/client/sidebar/RoomMenu.spec.tsx
  41. 1
      apps/meteor/client/sidebar/header/MatrixFederationSearch/MatrixFederationSearch.spec.tsx
  42. 2
      apps/meteor/client/sidebar/header/actions/hooks/useAdministrationItems.spec.tsx
  43. 8
      apps/meteor/client/sidebar/header/actions/hooks/useAppsItems.spec.tsx
  44. 5
      apps/meteor/client/sidebar/header/actions/hooks/useAuditItems.spec.tsx
  45. 2
      apps/meteor/client/sidebar/header/actions/hooks/useGroupingListItems.spec.tsx
  46. 2
      apps/meteor/client/sidebar/header/actions/hooks/useSortModeItems.spec.tsx
  47. 2
      apps/meteor/client/sidebar/header/actions/hooks/useViewModeItems.spec.tsx
  48. 5
      apps/meteor/client/sidebar/sections/BannerSection.spec.tsx
  49. 11
      apps/meteor/client/sidebarv2/Item/Condensed.tsx
  50. 11
      apps/meteor/client/sidebarv2/Item/Extended.tsx
  51. 11
      apps/meteor/client/sidebarv2/Item/Medium.tsx
  52. 2
      apps/meteor/client/sidebarv2/header/actions/hooks/useGroupingListItems.spec.tsx
  53. 2
      apps/meteor/client/sidebarv2/header/actions/hooks/useSortModeItems.spec.tsx
  54. 2
      apps/meteor/client/sidebarv2/header/actions/hooks/useViewModeItems.spec.tsx
  55. 15
      apps/meteor/client/sidebarv2/hooks/useRoomList.spec.tsx
  56. 19
      apps/meteor/client/sidebarv2/hooks/useUnreadDisplay.spec.tsx
  57. 5
      apps/meteor/client/sidebarv2/sections/BannerSection.spec.tsx
  58. 7
      apps/meteor/client/startup/appRoot.tsx
  59. 3
      apps/meteor/client/views/admin/customEmoji/CustomEmoji.spec.tsx
  60. 10
      apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.spec.tsx
  61. 6
      apps/meteor/client/views/admin/settings/Setting/inputs/TimespanSettingInput.tsx
  62. 3
      apps/meteor/client/views/admin/settings/groups/OAuthGroupPage/CreateOAuthModal.spec.tsx
  63. 5
      apps/meteor/client/views/admin/subscription/components/CancelSubscriptionModal.spec.tsx
  64. 5
      apps/meteor/client/views/admin/subscription/components/cards/AppsUsageCard/AppsUsageCard.spec.tsx
  65. 3
      apps/meteor/client/views/admin/subscription/hooks/useCancelSubscriptionModal.spec.tsx
  66. 12
      apps/meteor/client/views/admin/users/UsersPageHeaderContent.spec.tsx
  67. 4
      apps/meteor/client/views/admin/users/UsersTable/UsersTable.spec.tsx
  68. 5
      apps/meteor/client/views/admin/users/voip/AssignExtensionModal.spec.tsx
  69. 4
      apps/meteor/client/views/admin/users/voip/RemoveExtensionModal.spec.tsx
  70. 8
      apps/meteor/client/views/composer/EmojiPicker/ToneSelector/ToneSelectorWrapper.tsx
  71. 7
      apps/meteor/client/views/directory/RoomTags.tsx
  72. 5
      apps/meteor/client/views/directory/tabs/users/UsersTable/UsersTable.tsx
  73. 1
      apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.spec.tsx
  74. 1
      apps/meteor/client/views/marketplace/AppMenu.spec.tsx
  75. 4
      apps/meteor/client/views/marketplace/AppsPage/PrivateEmptyState.spec.tsx
  76. 2
      apps/meteor/client/views/marketplace/AppsPage/UnsupportedEmptyState.spec.tsx
  77. 3
      apps/meteor/client/views/marketplace/components/EnabledAppsCount.spec.tsx
  78. 10
      apps/meteor/client/views/modal/ModalRegion.tsx
  79. 11
      apps/meteor/client/views/modal/uikit/ModalBlock.tsx
  80. 5
      apps/meteor/client/views/notFound/NotFoundPage.spec.tsx
  81. 6
      apps/meteor/client/views/omnichannel/businessHours/BusinessHoursMultiplePage.tsx
  82. 4
      apps/meteor/client/views/room/Header/RoomToolbox/hooks/useRoomToolboxActions.spec.ts
  83. 4
      apps/meteor/client/views/room/HeaderV2/RoomToolbox/hooks/useRoomToolboxActions.spec.ts
  84. 4
      apps/meteor/client/views/room/MessageList/hooks/useKatex.spec.ts
  85. 8
      apps/meteor/client/views/room/RoomAnnouncement/AnnouncementComponent.tsx
  86. 2
      apps/meteor/client/views/room/body/RetentionPolicyWarning.spec.tsx
  87. 4
      apps/meteor/client/views/room/body/hooks/useGetMore.spec.ts
  88. 6
      apps/meteor/client/views/room/body/hooks/useRestoreScrollPosition.spec.ts
  89. 1
      apps/meteor/client/views/room/composer/messageBox/MessageBoxHint.spec.tsx
  90. 6
      apps/meteor/client/views/room/contextualBar/RoomMembers/RoomMembers.tsx
  91. 6
      apps/meteor/client/views/room/contextualBar/VideoConference/hooks/useVideoConfOpenCall.spec.tsx
  92. 4
      apps/meteor/client/views/room/hooks/useE2EEResetRoomKey.spec.ts
  93. 4
      apps/meteor/client/views/room/hooks/useRetentionPolicy.spec.ts
  94. 2
      apps/meteor/client/views/room/hooks/useToggleFavoriteMutation.spec.tsx
  95. 1
      apps/meteor/client/views/room/modals/FileUploadModal/FileUploadModal.spec.tsx
  96. 2
      apps/meteor/client/views/room/providers/UserCardProvider.tsx
  97. 44
      apps/meteor/client/views/room/providers/hooks/useChatMessagesInstance.spec.ts
  98. 3
      apps/meteor/client/views/room/providers/hooks/useDepsMatch.spec.ts
  99. 4
      apps/meteor/client/views/room/providers/hooks/useInstance.spec.ts
  100. 2
      apps/meteor/client/views/root/MainLayout/LoginPage.tsx
  101. Some files were not shown because too many files have changed in this diff Show More

File diff suppressed because one or more lines are too long

@ -1,5 +1,6 @@
import type { Keys as IconName } from '@rocket.chat/icons';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { flushSync } from 'react-dom';
import AddLinkComposerActionModal from './AddLinkComposerActionModal';
import type { ComposerAPI } from '../../../../client/lib/chats/ChatAPI';
@ -72,9 +73,14 @@ export const formattingButtons: ReadonlyArray<FormattingButton> = [
};
const onConfirm = (url: string, text: string) => {
onClose();
composerApi.replaceText(`[${text}](${url})`, selection);
composerApi.setCursorToEnd();
// Composer API can't handle the selection of the text while the modal is open
flushSync(() => {
onClose();
});
flushSync(() => {
composerApi.replaceText(`[${text}](${url})`, selection);
composerApi.setCursorToEnd();
});
};
imperativeModal.open({ component: AddLinkComposerActionModal, props: { onConfirm, selectedText, onClose } });

@ -5,7 +5,6 @@ import { useAuditMenu } from './useAuditMenu';
it('should return an empty array of items if doesn`t have license', async () => {
const { result } = renderHook(() => useAuditMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error: just for testing
@ -24,7 +23,6 @@ it('should return an empty array of items if doesn`t have license', async () =>
it('should return an empty array of items if have license and not have permissions', async () => {
const { result } = renderHook(() => useAuditMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@ -46,7 +44,6 @@ it('should return an empty array of items if have license and not have permissio
it('should return auditItems if have license and permissions', async () => {
const { result } = renderHook(() => useAuditMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@ -81,7 +78,6 @@ it('should return auditItems if have license and permissions', async () => {
it('should return auditMessages item if have license and can-audit permission', async () => {
const { result } = renderHook(() => useAuditMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@ -109,7 +105,6 @@ it('should return auditMessages item if have license and can-audit permission',
it('should return audiLogs item if have license and can-audit-log permission', async () => {
const { result } = renderHook(() => useAuditMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {

@ -6,7 +6,6 @@ import { useMarketPlaceMenu } from './useMarketPlaceMenu';
it('should return and empty array if the user does not have `manage-apps` and `access-marketplace` permission', () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.build(),
@ -17,7 +16,6 @@ it('should return and empty array if the user does not have `manage-apps` and `a
it('should return `explore` and `installed` items if the user has `access-marketplace` permission', () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.withPermission('access-marketplace')
@ -39,7 +37,6 @@ it('should return `explore` and `installed` items if the user has `access-market
it('should return `explore`, `installed` and `requested` items if the user has `manage-apps` permission', () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.withEndpoint('GET', '/apps/app-request/stats', () => ({
@ -73,7 +70,6 @@ it('should return `explore`, `installed` and `requested` items if the user has `
it('should return one action from the server with no conditions', async () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -117,7 +113,6 @@ it('should return one action from the server with no conditions', async () => {
describe('Marketplace menu with role conditions', () => {
it('should return the action if the user has admin role', async () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -165,7 +160,6 @@ describe('Marketplace menu with role conditions', () => {
it('should return filter the action if the user doesn`t have admin role', async () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -213,7 +207,6 @@ describe('Marketplace menu with role conditions', () => {
describe('Marketplace menu with permission conditions', () => {
it('should return the action if the user has manage-apps permission', async () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -259,7 +252,6 @@ describe('Marketplace menu with permission conditions', () => {
it('should return filter the action if the user doesn`t have `any` permission', async () => {
const { result } = renderHook(() => useMarketPlaceMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{

@ -5,7 +5,6 @@ import { useAdministrationMenu } from './useAdministrationMenu';
it('should return omnichannel item if has `view-livechat-manager` permission ', async () => {
const { result } = renderHook(() => useAdministrationMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error this is a mock
@ -31,7 +30,6 @@ it('should return omnichannel item if has `view-livechat-manager` permission ',
it('should show administration item if has at least one admin permission', async () => {
const { result } = renderHook(() => useAdministrationMenu(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error this is a mock

@ -1,13 +1,13 @@
import { Palette } from '@rocket.chat/fuselage';
import type { ScrollValues } from 'rc-scrollbars';
import { Scrollbars } from 'rc-scrollbars';
import type { MutableRefObject, CSSProperties, ReactNode } from 'react';
import type { MutableRefObject, CSSProperties, ReactNode, HTMLAttributes } from 'react';
import { memo, forwardRef, useCallback, useMemo } from 'react';
export type CustomScrollbarsProps = {
overflowX?: boolean;
style?: CSSProperties;
children?: ReactNode;
children?: HTMLAttributes<HTMLElement>['children'];
onScroll?: (values: ScrollValues) => void;
renderView?: typeof Scrollbars.defaultProps.renderView;
renderTrackHorizontal?: typeof Scrollbars.defaultProps.renderTrackHorizontal;
@ -26,7 +26,7 @@ const CustomScrollbars = forwardRef<HTMLElement, CustomScrollbarsProps>(function
const scrollbarsStyle = useMemo(() => ({ ...style, ...styleDefault }), [style]);
const refSetter = useCallback(
(scrollbarRef: Scrollbars) => {
(scrollbarRef: Scrollbars | null) => {
if (ref && scrollbarRef) {
if (typeof ref === 'function') {
ref(scrollbarRef.view ?? null);
@ -52,7 +52,7 @@ const CustomScrollbars = forwardRef<HTMLElement, CustomScrollbarsProps>(function
renderThumbVertical={({ style, ...props }) => (
<div {...props} style={{ ...style, backgroundColor: Palette.stroke['stroke-dark'].toString(), borderRadius: '4px' }} />
)}
children={children}
children={children as ReactNode} // workaround for incompatible types between react-virtuoso and react-i18next
ref={refSetter}
/>
);

@ -1,13 +1,13 @@
import type { ComponentProps, Ref } from 'react';
import type { ComponentPropsWithoutRef } from 'react';
import { forwardRef } from 'react';
import CustomScrollbars from './CustomScrollbars';
type VirtuosoScrollbarsProps = ComponentProps<typeof CustomScrollbars>;
type VirtuosoScrollbarsProps = ComponentPropsWithoutRef<typeof CustomScrollbars>;
const VirtuosoScrollbars = forwardRef(function VirtuosoScrollbars(
{ style, children, ...props }: VirtuosoScrollbarsProps,
ref: Ref<HTMLDivElement>,
const VirtuosoScrollbars = forwardRef<HTMLDivElement, VirtuosoScrollbarsProps>(function VirtuosoScrollbars(
{ style, children, ...props },
ref,
) {
return (
<CustomScrollbars style={style} ref={ref} renderView={(viewProps) => <div {...viewProps} {...props} tabIndex={-1} />}>

@ -11,7 +11,6 @@ const renderModal = (modalElement: ReactElement) => {
const {
result: { current: setModal },
} = renderHook(() => useSetModal(), {
legacyRoot: true,
wrapper: ({ children }) => (
<Suspense fallback={null}>
<ModalProviderWithRegion>{children}</ModalProviderWithRegion>

@ -20,12 +20,12 @@ export default {
component: InfoPanel,
subcomponents: {
InfoPanelAction: InfoPanelAction as ComponentType<any>,
InfoPanelActionGroup,
InfoPanelAvatar,
InfoPanelField,
InfoPanelLabel,
InfoPanelSection,
InfoPanelText,
InfoPanelActionGroup: InfoPanelActionGroup as ComponentType<any>,
InfoPanelAvatar: InfoPanelAvatar as ComponentType<any>,
InfoPanelField: InfoPanelField as ComponentType<any>,
InfoPanelLabel: InfoPanelLabel as ComponentType<any>,
InfoPanelSection: InfoPanelSection as ComponentType<any>,
InfoPanelText: InfoPanelText as ComponentType<any>,
InfoPanelTitle: InfoPanelTitle as ComponentType<any>,
RetentionPolicyCallout: RetentionPolicyCallout as ComponentType<any>,
},

@ -14,7 +14,6 @@ describe('RetentionPolicyCallout', () => {
it('Should render callout if settings are valid', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
render(<RetentionPolicyCallout room={fakeRoom} />, {
legacyRoot: true,
wrapper: createMock({ appliesToChannels: true, TTLChannels: 60000 }),
});
expect(screen.getByRole('alert')).toHaveTextContent('a minute June 1, 2024 at 12:30 AM');
@ -23,7 +22,6 @@ describe('RetentionPolicyCallout', () => {
it('Should not render callout if settings are invalid', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
render(<RetentionPolicyCallout room={fakeRoom} />, {
legacyRoot: true,
wrapper: createMock({ appliesToChannels: true, TTLChannels: 60000, advancedPrecisionCron: '* * * 12 *', advancedPrecision: true }),
});
expect(screen.queryByRole('alert')).not.toBeInTheDocument();

@ -43,7 +43,6 @@ const markdownText = `
it('should render html elements as expected using default parser', async () => {
const { container } = render(<MarkdownText content={markdownText} variant='document' />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
const normalizedHtml = normalizeHtml(container.innerHTML);
@ -73,7 +72,6 @@ it('should render html elements as expected using default parser', async () => {
it('should render html elements as expected using inline parser', async () => {
const { container } = render(<MarkdownText content={markdownText} variant='inline' />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
const normalizedHtml = normalizeHtml(container.innerHTML);

@ -39,7 +39,6 @@ it('should not fetch and add selected department if it is already in the departm
selectedDepartment: '5',
}),
{
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/livechat/department', () => ({
count: 25,
@ -90,7 +89,6 @@ it('should fetch and add selected department if it is not part of departments li
selectedDepartment: '56f5be8bcf8cd67f9e9bcfdc',
}),
{
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/livechat/department', () => ({
count: 25,

@ -80,7 +80,7 @@ const CloseChatModal = ({ department, visitorEmail, onCancel, onConfirm }: Close
};
const onSubmit = useCallback(
({ comment, tags, transcriptPDF, transcriptEmail, subject }: CloseChatModalFormData): void => {
({ comment, tags, transcriptPDF, transcriptEmail, subject }: CloseChatModalFormData) => {
const preferences = {
omnichannelTranscriptPDF: !!transcriptPDF,
omnichannelTranscriptEmail: alwaysSendTranscript ? true : !!transcriptEmail,

@ -24,7 +24,7 @@ const defaultProps = {
it('should show Undo request button when roomOpen is true and transcriptRequest exist', async () => {
const onDiscardMock = jest.fn();
render(<TranscriptModal {...defaultProps} onDiscard={onDiscardMock} />, { legacyRoot: true });
render(<TranscriptModal {...defaultProps} onDiscard={onDiscardMock} />);
const undoRequestButton = await screen.findByText('Undo_request');
await userEvent.click(undoRequestButton);
@ -33,14 +33,14 @@ it('should show Undo request button when roomOpen is true and transcriptRequest
});
it('should show Request button when roomOpen is true and transcriptRequest not exist', async () => {
render(<TranscriptModal {...{ ...defaultProps, room: { ...room, transcriptRequest: undefined } }} />, { legacyRoot: true });
render(<TranscriptModal {...{ ...defaultProps, room: { ...room, transcriptRequest: undefined } }} />);
const requestBtn = await screen.findByRole('button', { name: 'request-button' });
expect(requestBtn).toBeInTheDocument();
});
it('should show Send button when roomOpen is false', async () => {
render(<TranscriptModal {...{ ...defaultProps, room: { ...room, open: false } }} />, { legacyRoot: true });
render(<TranscriptModal {...{ ...defaultProps, room: { ...room, open: false } }} />);
const sendBtn = await screen.findByRole('button', { name: 'send-button' });
expect(sendBtn).toBeInTheDocument();

@ -8,10 +8,10 @@ export default {
title: 'Components/Page',
component: Page,
subcomponents: {
PageContent,
PageContent: PageContent as ComponentType<any>,
PageHeader: PageHeader as ComponentType<any>,
PageScrollableContent,
PageScrollableContentWithShadow,
PageScrollableContent: PageScrollableContent as ComponentType<any>,
PageScrollableContentWithShadow: PageScrollableContentWithShadow as ComponentType<any>,
},
parameters: {
layout: 'fullscreen',

@ -15,7 +15,7 @@ const SidebarTogglerBadge = ({ children }: SidebarTogglerBadgeProps) => (
right: 3px;
`}
>
<Badge variant='danger' children={children} />
<Badge variant='danger'>{children}</Badge>
</Box>
);

@ -1,3 +1,4 @@
import type { OptionType } from '@rocket.chat/fuselage';
import { MultiSelectFiltered, Icon, Box, Chip } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import { UserAvatar } from '@rocket.chat/ui-avatar';
@ -93,7 +94,7 @@ const UserAutoCompleteMultipleFederated = ({
);
return (
<OptionsContext.Provider value={{ options }}>
<OptionsContext.Provider value={{ options: options as unknown as OptionType[] }}>
<MultiSelectFiltered
{...props}
data-qa-type='user-auto-complete-input'

@ -1,3 +1,4 @@
import type { OptionType } from '@rocket.chat/fuselage';
import { Options } from '@rocket.chat/fuselage';
import type { ComponentProps, ReactElement, Ref } from 'react';
import { forwardRef, createContext, useContext } from 'react';
@ -9,7 +10,7 @@ import UserAutoCompleteMultipleOption from './UserAutoCompleteMultipleOption';
// but we also need to pass internal state to this renderer, as well as the props that also come from the Select.
type OptionsContextValue = {
options: ComponentProps<typeof Options>['options'];
options: OptionType[];
};
export const OptionsContext = createContext<OptionsContextValue>({

@ -75,7 +75,9 @@ const UserStatusMenu = ({
[hide, reset],
);
useEffect(() => onChange(status), [status, onChange]);
useEffect(() => {
onChange(status);
}, [status, onChange]);
return (
<>

@ -5,7 +5,6 @@ import WarningModal from './WarningModal';
it('should look good', async () => {
render(<WarningModal text='text' confirmText='confirm' cancelText='cancel' confirm={() => undefined} close={() => undefined} />, {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});

@ -93,7 +93,6 @@ describe('Thread Metrics', () => {
.withSetting('Message_TimeFormat', 'LT')
.withTranslations(...mockedTranslations)
.buildWithRouter(navigateCallback),
legacyRoot: true,
},
);
@ -151,7 +150,6 @@ describe('Thread Metrics', () => {
.withSetting('Message_TimeFormat', 'LT')
.withTranslations(...mockedTranslations)
.buildWithRouter(navigateCallback),
legacyRoot: true,
},
);
const followButton = screen.getByTitle('Not_following');
@ -184,7 +182,6 @@ describe('Thread Metrics', () => {
toggleFollowMock(() => undefined),
)
.build(),
legacyRoot: true,
});
const followButton = screen.getByTitle('Not_following');
expect(followButton).toBeVisible();
@ -199,7 +196,6 @@ describe('Thread Metrics', () => {
toggleFollowMock(() => undefined),
)
.build(),
legacyRoot: true,
});
const followButton = screen.getByTitle('Following');
expect(followButton).toBeVisible();
@ -208,7 +204,6 @@ describe('Thread Metrics', () => {
it('should render unread badge', () => {
render(<ThreadMetricsFollow unread={true} mention={false} all={false} mid='mid' rid='rid' following={false} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
const badge = screen.getByTitle('Unread');
expect(badge).toBeVisible();
@ -216,7 +211,6 @@ describe('Thread Metrics', () => {
it('should render mention-all badge', () => {
render(<ThreadMetricsFollow unread={true} mention={false} all={true} mid='mid' rid='rid' following={false} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
const badge = screen.getByTitle('mention-all');
expect(badge).toBeVisible();
@ -224,7 +218,6 @@ describe('Thread Metrics', () => {
it('should render Mentions_you badge', () => {
render(<ThreadMetricsFollow unread={true} mention={true} all={false} mid='mid' rid='rid' following={false} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
const badge = screen.getByTitle('Mentions_you');
expect(badge).toBeVisible();
@ -237,7 +230,6 @@ describe('Thread Metrics', () => {
.withUserPreference('displayAvatars', true)
.withTranslations(...mockedTranslations)
.build(),
legacyRoot: true,
});
expect(screen.getByTitle('follower')).toBeVisible();
const avatars = screen.getAllByRole('figure');
@ -250,7 +242,6 @@ describe('Thread Metrics', () => {
.withUserPreference('displayAvatars', true)
.withTranslations(...mockedTranslations)
.build(),
legacyRoot: true,
});
expect(screen.getByTitle('followers')).toBeVisible();
const avatars = screen.getAllByRole('figure');
@ -263,7 +254,6 @@ describe('Thread Metrics', () => {
.withUserPreference('displayAvatars', true)
.withTranslations(...mockedTranslations)
.build(),
legacyRoot: true,
});
expect(screen.getByTitle('followers')).toBeVisible();
const avatars = screen.getAllByRole('figure');
@ -277,7 +267,6 @@ describe('Thread Metrics', () => {
.withUserPreference('displayAvatars', true)
.withTranslations(...mockedTranslations)
.build(),
legacyRoot: true,
});
expect(screen.getByTitle('followers')).toBeVisible();
@ -294,7 +283,6 @@ describe('Thread Metrics', () => {
.withUserPreference('displayAvatars', false)
.withTranslations(...mockedTranslations)
.build(),
legacyRoot: true,
});
const follower = screen.getByTitle('follower');
expect(follower).toBeVisible();
@ -311,7 +299,6 @@ describe('Thread Metrics', () => {
.withUserPreference('displayAvatars', false)
.withTranslations(...mockedTranslations)
.build(),
legacyRoot: true,
});
const follower = screen.getByTitle('followers');
expect(follower).toBeVisible();

@ -7,7 +7,6 @@ it('should be call rest `POST /v1/chat.react` method', async () => {
const fn = jest.fn();
const { result } = renderHook(() => useToggleReactionMutation(), {
legacyRoot: true,
wrapper: mockAppRoot().withEndpoint('POST', '/v1/chat.react', fn).withJohnDoe().build(),
});
@ -25,7 +24,6 @@ it('should not work for non-logged in users', async () => {
const fn = jest.fn();
const { result } = renderHook(() => useToggleReactionMutation(), {
legacyRoot: true,
wrapper: mockAppRoot().withEndpoint('POST', '/v1/chat.react', fn).build(),
});

@ -56,7 +56,6 @@ it('should show normal message', () => {
showUserAvatar={true}
/>,
{
legacyRoot: true,
wrapper: mockAppRoot().build(),
},
);
@ -78,7 +77,6 @@ it('should show fallback content for ignored user', () => {
showUserAvatar={true}
/>,
{
legacyRoot: true,
wrapper: mockAppRoot().build(),
},
);
@ -100,7 +98,6 @@ it('should show ignored message', () => {
showUserAvatar={true}
/>,
{
legacyRoot: true,
wrapper: mockAppRoot().build(),
},
);

@ -84,7 +84,7 @@ describe('useE2EERoomAction', () => {
it('should dispatch error toast message when otrState is ESTABLISHED', async () => {
(useOTR as jest.Mock).mockReturnValue({ otrState: OtrRoomState.ESTABLISHED });
const { result } = renderHook(() => useE2EERoomAction(), { legacyRoot: true });
const { result } = renderHook(() => useE2EERoomAction());
await act(async () => {
await result?.current?.action?.();
@ -96,7 +96,7 @@ describe('useE2EERoomAction', () => {
it('should dispatch error toast message when otrState is ESTABLISHING', async () => {
(useOTR as jest.Mock).mockReturnValue({ otrState: OtrRoomState.ESTABLISHING });
const { result } = renderHook(() => useE2EERoomAction(), { legacyRoot: true });
const { result } = renderHook(() => useE2EERoomAction());
act(() => {
result?.current?.action?.();
@ -108,7 +108,7 @@ describe('useE2EERoomAction', () => {
it('should dispatch error toast message when otrState is REQUESTED', async () => {
(useOTR as jest.Mock).mockReturnValue({ otrState: OtrRoomState.REQUESTED });
const { result } = renderHook(() => useE2EERoomAction(), { legacyRoot: true });
const { result } = renderHook(() => useE2EERoomAction());
act(() => {
result?.current?.action?.();
@ -120,7 +120,7 @@ describe('useE2EERoomAction', () => {
it('should open Enable E2EE confirmation modal', async () => {
(useOTR as jest.Mock).mockReturnValue({ otrState: OtrRoomState.NOT_STARTED });
const { result } = renderHook(() => useE2EERoomAction(), { legacyRoot: true });
const { result } = renderHook(() => useE2EERoomAction());
act(() => {
result?.current?.action?.();
});

@ -7,7 +7,6 @@ import { useAirGappedRestriction } from './useAirGappedRestriction';
describe('useAirGappedRestriction hook', () => {
it('should return [false, false, -1] if setting value is not a number', () => {
const { result } = renderHook(() => useAirGappedRestriction(), {
legacyRoot: true,
wrapper: mockAppRoot().withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', -1).build(),
});
@ -16,7 +15,6 @@ describe('useAirGappedRestriction hook', () => {
it('should return [false, false, -1] if user has a license (remaining days is a negative value)', () => {
const { result } = renderHook(() => useAirGappedRestriction(), {
legacyRoot: true,
wrapper: mockAppRoot().withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', -1).build(),
});
@ -25,7 +23,6 @@ describe('useAirGappedRestriction hook', () => {
it('should return [false, false, 8] if not on warning or restriction phase', () => {
const { result } = renderHook(() => useAirGappedRestriction(), {
legacyRoot: true,
wrapper: mockAppRoot().withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', 8).build(),
});
@ -34,7 +31,6 @@ describe('useAirGappedRestriction hook', () => {
it('should return [true, false, 7] if on warning phase', () => {
const { result } = renderHook(() => useAirGappedRestriction(), {
legacyRoot: true,
wrapper: mockAppRoot().withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', 7).build(),
});
@ -43,7 +39,6 @@ describe('useAirGappedRestriction hook', () => {
it('should return [true, false, 0] if on restriction phase', () => {
const { result } = renderHook(() => useAirGappedRestriction(), {
legacyRoot: true,
wrapper: mockAppRoot().withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', 0).build(),
});

@ -30,7 +30,7 @@ describe('useDecryptedMessage', () => {
(isE2EEMessage as jest.MockedFunction<typeof isE2EEMessage>).mockReturnValue(false);
const message = { msg: 'Hello, world!' };
const { result } = renderHook(() => useDecryptedMessage(message as any), { legacyRoot: true });
const { result } = renderHook(() => useDecryptedMessage(message as any));
expect(result.current).toBe('Hello, world!');
expect(e2e.decryptMessage).not.toHaveBeenCalled();
@ -40,7 +40,7 @@ describe('useDecryptedMessage', () => {
(isE2EEMessage as jest.MockedFunction<typeof isE2EEMessage>).mockReturnValue(true);
(e2e.decryptMessage as jest.Mock).mockResolvedValue({ msg: 'Decrypted message' });
const message = { msg: 'Encrypted message' };
const { result } = renderHook(() => useDecryptedMessage(message as any), { legacyRoot: true });
const { result } = renderHook(() => useDecryptedMessage(message as any));
await waitFor(() => {
expect(result.current).not.toBe('E2E_message_encrypted_placeholder');
@ -57,7 +57,7 @@ describe('useDecryptedMessage', () => {
});
const message = { msg: 'Encrypted message with attachment' };
const { result } = renderHook(() => useDecryptedMessage(message as any), { legacyRoot: true });
const { result } = renderHook(() => useDecryptedMessage(message as any));
await waitFor(() => {
expect(result.current).toBe('E2E_message_encrypted_placeholder');
@ -74,7 +74,7 @@ describe('useDecryptedMessage', () => {
});
const message = { msg: 'Encrypted message with attachment' };
const { result } = renderHook(() => useDecryptedMessage(message as any), { legacyRoot: true });
const { result } = renderHook(() => useDecryptedMessage(message as any));
await waitFor(() => {
expect(result.current).toBe('E2E_message_encrypted_placeholder');

@ -27,7 +27,7 @@ describe('useOTR', () => {
(useUserId as jest.Mock).mockReturnValue(undefined);
(useRoom as jest.Mock).mockReturnValue({ _id: 'roomId' });
const { result } = renderHook(() => useOTR(), { legacyRoot: true });
const { result } = renderHook(() => useOTR());
expect(result.current.otr).toBeUndefined();
expect(result.current.otrState).toBe(OtrRoomState.ERROR);
@ -37,7 +37,7 @@ describe('useOTR', () => {
(useUserId as jest.Mock).mockReturnValue('userId');
(useRoom as jest.Mock).mockReturnValue(undefined);
const { result } = renderHook(() => useOTR(), { legacyRoot: true });
const { result } = renderHook(() => useOTR());
expect(result.current.otr).toBeUndefined();
expect(result.current.otrState).toBe(OtrRoomState.ERROR);
@ -48,7 +48,7 @@ describe('useOTR', () => {
(useRoom as jest.Mock).mockReturnValue({ _id: 'roomId' });
(OTR.getInstanceByRoomId as jest.Mock).mockReturnValue(undefined);
const { result } = renderHook(() => useOTR(), { legacyRoot: true });
const { result } = renderHook(() => useOTR());
expect(result.current.otr).toBeUndefined();
expect(result.current.otrState).toBe(OtrRoomState.ERROR);
@ -62,7 +62,7 @@ describe('useOTR', () => {
(useRoom as jest.Mock).mockReturnValue({ _id: 'roomId' });
(OTR.getInstanceByRoomId as jest.Mock).mockReturnValue(mockOtrInstance);
const { result } = renderHook(() => useOTR(), { legacyRoot: true });
const { result } = renderHook(() => useOTR());
expect(result.current.otr).toBe(mockOtrInstance);
expect(result.current.otrState).toBe(OtrRoomState.NOT_STARTED);

@ -33,7 +33,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should update the message after the nextRunDate has passaed', async () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -47,7 +46,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the default warning with precision set to every_hour', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -60,7 +58,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the default warning with precision set to every_six_hours', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -73,7 +70,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the default warning with precision set to every_day', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -86,7 +82,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the default warning with advanced precision', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -102,7 +97,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the default warning', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -114,7 +108,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the unpinned messages warning', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -128,7 +121,6 @@ describe('usePruneWarningMessage hook', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -142,7 +134,6 @@ describe('usePruneWarningMessage hook', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock({
appliesToChannels: true,
TTLChannels: 60000,
@ -158,7 +149,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the default warning', () => {
const fakeRoom = createFakeRoom({ t: 'p', ...getRetentionRoomProps() });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock(),
});
expect(result.current).toEqual('30 days June 1, 2024 at 12:30 AM');
@ -167,7 +157,6 @@ describe('usePruneWarningMessage hook', () => {
it('Should return the unpinned messages warning', () => {
const fakeRoom = createFakeRoom({ t: 'p', ...getRetentionRoomProps({ excludePinned: true }) });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock(),
});
expect(result.current).toEqual('Unpinned 30 days June 1, 2024 at 12:30 AM');
@ -177,7 +166,6 @@ describe('usePruneWarningMessage hook', () => {
const fakeRoom = createFakeRoom({ t: 'p', ...getRetentionRoomProps({ filesOnly: true }) });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock(),
});
expect(result.current).toEqual('FilesOnly 30 days June 1, 2024 at 12:30 AM');
@ -187,7 +175,6 @@ describe('usePruneWarningMessage hook', () => {
const fakeRoom = createFakeRoom({ t: 'p', ...getRetentionRoomProps({ excludePinned: true, filesOnly: true }) });
const { result } = renderHook(() => usePruneWarningMessage(fakeRoom), {
legacyRoot: true,
wrapper: createMock(),
});
expect(result.current).toEqual('UnpinnedFilesOnly 30 days June 1, 2024 at 12:30 AM');

@ -7,7 +7,7 @@ import { ReactiveUserStatus } from '../components/UserStatus';
export const useRoomIcon = (
room: Pick<IRoom, 't' | 'prid' | 'teamMain' | 'uids' | 'u'>,
): ReactElement | ComponentProps<typeof Icon> | null => {
): ComponentProps<typeof Icon> | ReactElement | null => {
if (isRoomFederated(room)) {
return { name: 'globe' };
}

@ -5,7 +5,6 @@ import { useSortQueryOptions } from './useSortQueryOptions';
it("should return query option to sort by last message when user preference is 'activity'", () => {
const { result } = renderHook(() => useSortQueryOptions(), {
legacyRoot: true,
wrapper: mockAppRoot().withUserPreference('sidebarSortby', 'activity').build(),
});
expect(result.current.sort).toHaveProperty('lm', -1);
@ -13,7 +12,6 @@ it("should return query option to sort by last message when user preference is '
it("should return query option to sort by name when user preference is 'name'", () => {
const { result } = renderHook(() => useSortQueryOptions(), {
legacyRoot: true,
wrapper: mockAppRoot().withUserPreference('sidebarSortby', 'name').build(),
});
expect(result.current.sort).toHaveProperty('lowerCaseName', 1);
@ -21,7 +19,6 @@ it("should return query option to sort by name when user preference is 'name'",
it("should return query option to sort by fname when user preference is 'name' and showRealName is true", () => {
const { result } = renderHook(() => useSortQueryOptions(), {
legacyRoot: true,
wrapper: mockAppRoot().withUserPreference('sidebarSortby', 'name').withSetting('UI_Use_Real_Name', true).build(),
});
expect(result.current.sort).toHaveProperty('lowerCaseFName', 1);

@ -24,14 +24,16 @@ export const createReactiveSubscriptionFactory =
let computation: Tracker.Computation | undefined;
queueMicrotask(() => {
computation = Tracker.autorun(reactiveFn);
});
return [
(callback): (() => void) => {
callbacks.add(callback);
queueMicrotask(() => {
if (!computation || computation.stopped) {
computation = Tracker.autorun(reactiveFn);
}
});
return (): void => {
callbacks.delete(callback);

@ -56,6 +56,7 @@ const CannedResponseEdit = ({ cannedResponseData }: CannedResponseEditProps) =>
try {
await saveCannedResponse({
...data,
_id: cannedResponseData?._id ?? data._id,
...(departmentId && { departmentId }),
});
dispatchToastMessage({

@ -100,7 +100,11 @@ const CannedResponseForm = () => {
)}
</Field>
<Field>
<Controller name='tags' control={control} render={({ field: { value, onChange } }) => <Tags handler={onChange} tags={value} />} />
<Controller
name='tags'
control={control}
render={({ field: { value, onChange } }) => <Tags handler={onChange} tags={value as unknown as string[]} />} // FIXME: fix types
/>
</Field>
{(hasManagerPermission || hasMonitorPermission) && (
<>

@ -27,7 +27,7 @@ type CannedResponseListProps = {
loading: boolean;
options: [string, string][];
text: string;
setText: FormEventHandler<HTMLOrSVGElement>;
setText: FormEventHandler<HTMLInputElement>;
type: string;
setType: Dispatch<SetStateAction<string>>;
isRoomOverMacLimit: boolean;

@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
import GenericModal from '../../../../components/GenericModal';
import CannedResponseForm from '../../components/CannedResponseForm';
type CreateCannedResponseModalFormData = {
export type CreateCannedResponseModalFormData = {
_id: string;
shortcut: string;
text: string;
@ -57,6 +57,7 @@ const CreateCannedResponseModal = ({ cannedResponseData, onClose, reloadCannedLi
try {
await saveCannedResponse({
...data,
_id: cannedResponseData?._id ?? data._id,
...(departmentId && { departmentId }),
});
dispatchToastMessage({

@ -11,7 +11,6 @@ import ModalRegion from '../../views/modal/ModalRegion';
const renderWithSuspense = (ui: ReactElement) =>
render(ui, {
legacyRoot: true,
wrapper: ({ children }) => <Suspense fallback={null}>{children}</Suspense>,
});

@ -1,5 +1,4 @@
import { IconButton, Sidebar } from '@rocket.chat/fuselage';
import { usePrefersReducedMotion } from '@rocket.chat/fuselage-hooks';
import type { Keys as IconName } from '@rocket.chat/icons';
import type { ReactElement } from 'react';
import { memo, useState } from 'react';
@ -21,14 +20,12 @@ type CondensedProps = {
const Condensed = ({ icon, title = '', avatar, actions, href, unread, menu, badges, ...props }: CondensedProps) => {
const [menuVisibility, setMenuVisibility] = useState(!!window.DISABLE_ANIMATION);
const isReduceMotionEnabled = usePrefersReducedMotion();
const handleMenuEvent = {
[isReduceMotionEnabled ? 'onMouseEnter' : 'onTransitionEnd']: setMenuVisibility,
};
const handleFocus = () => setMenuVisibility(true);
const handlePointerEnter = () => setMenuVisibility(true);
return (
<Sidebar.Item {...props} {...({ href } as any)} clickable={!!href}>
<Sidebar.Item {...props} {...({ href } as any)} clickable={!!href} onFocus={handleFocus} onPointerEnter={handlePointerEnter}>
{avatar && <Sidebar.Item.Avatar>{avatar}</Sidebar.Item.Avatar>}
<Sidebar.Item.Content>
<Sidebar.Item.Wrapper>
@ -39,7 +36,7 @@ const Condensed = ({ icon, title = '', avatar, actions, href, unread, menu, badg
</Sidebar.Item.Wrapper>
{badges && <Sidebar.Item.Badge>{badges}</Sidebar.Item.Badge>}
{menu && (
<Sidebar.Item.Menu {...handleMenuEvent}>
<Sidebar.Item.Menu>
{menuVisibility ? menu() : <IconButton tabIndex={-1} aria-hidden mini rcx-sidebar-item__menu icon='kebab' />}
</Sidebar.Item.Menu>
)}

@ -1,5 +1,4 @@
import { Sidebar, IconButton } from '@rocket.chat/fuselage';
import { usePrefersReducedMotion } from '@rocket.chat/fuselage-hooks';
import type { Keys as IconName } from '@rocket.chat/icons';
import type { ReactNode } from 'react';
import { memo, useState } from 'react';
@ -42,14 +41,20 @@ const Extended = ({
}: ExtendedProps) => {
const formatDate = useShortTimeAgo();
const [menuVisibility, setMenuVisibility] = useState(!!window.DISABLE_ANIMATION);
const isReduceMotionEnabled = usePrefersReducedMotion();
const handleMenuEvent = {
[isReduceMotionEnabled ? 'onMouseEnter' : 'onTransitionEnd']: setMenuVisibility,
};
const handleFocus = () => setMenuVisibility(true);
const handlePointerEnter = () => setMenuVisibility(true);
return (
<Sidebar.Item selected={selected} highlighted={unread} {...props} {...({ href } as any)} clickable={!!href}>
<Sidebar.Item
selected={selected}
highlighted={unread}
{...props}
{...({ href } as any)}
clickable={!!href}
onFocus={handleFocus}
onPointerEnter={handlePointerEnter}
>
{avatar && <Sidebar.Item.Avatar>{avatar}</Sidebar.Item.Avatar>}
<Sidebar.Item.Content>
<Sidebar.Item.Content>
@ -66,7 +71,7 @@ const Extended = ({
<Sidebar.Item.Subtitle className={(unread && 'rcx-sidebar-item--highlighted') as string}>{subtitle}</Sidebar.Item.Subtitle>
<Sidebar.Item.Badge>{badges}</Sidebar.Item.Badge>
{menu && (
<Sidebar.Item.Menu {...handleMenuEvent}>
<Sidebar.Item.Menu>
{menuVisibility ? menu() : <IconButton tabIndex={-1} aria-hidden mini rcx-sidebar-item__menu icon='kebab' />}
</Sidebar.Item.Menu>
)}

@ -1,5 +1,4 @@
import { Sidebar, IconButton } from '@rocket.chat/fuselage';
import { usePrefersReducedMotion } from '@rocket.chat/fuselage-hooks';
import type { ReactNode } from 'react';
import { memo, useState } from 'react';
@ -19,14 +18,12 @@ type MediumProps = {
const Medium = ({ icon, title = '', avatar, actions, href, badges, unread, menu, ...props }: MediumProps) => {
const [menuVisibility, setMenuVisibility] = useState(!!window.DISABLE_ANIMATION);
const isReduceMotionEnabled = usePrefersReducedMotion();
const handleMenuEvent = {
[isReduceMotionEnabled ? 'onMouseEnter' : 'onTransitionEnd']: setMenuVisibility,
};
const handleFocus = () => setMenuVisibility(true);
const handlePointerEnter = () => setMenuVisibility(true);
return (
<Sidebar.Item {...props} href={href} clickable={!!href}>
<Sidebar.Item {...props} href={href} clickable={!!href} onFocus={handleFocus} onPointerEnter={handlePointerEnter}>
{avatar && <Sidebar.Item.Avatar>{avatar}</Sidebar.Item.Avatar>}
<Sidebar.Item.Content>
<Sidebar.Item.Wrapper>
@ -37,7 +34,7 @@ const Medium = ({ icon, title = '', avatar, actions, href, badges, unread, menu,
</Sidebar.Item.Wrapper>
{badges && <Sidebar.Item.Badge>{badges}</Sidebar.Item.Badge>}
{menu && (
<Sidebar.Item.Menu {...handleMenuEvent}>
<Sidebar.Item.Menu>
{menuVisibility ? menu() : <IconButton tabIndex={-1} aria-hidden mini rcx-sidebar-item__menu icon='kebab' />}
</Sidebar.Item.Menu>
)}

@ -39,7 +39,6 @@ const renderOptions = {
.withPermission('leave-c')
.withPermission('leave-p')
.build(),
legacyRoot: true,
};
it('should display all the menu options for regular rooms', async () => {

@ -17,7 +17,6 @@ const renderMatrixFederationSearch = (
],
) => {
return render(<></>, {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/federation/listServersByUser', () => ({
servers: serverList,

@ -5,7 +5,6 @@ import { useAdministrationItems } from './useAdministrationItems';
it('should return omnichannel item if has `view-livechat-manager` permission ', async () => {
const { result } = renderHook(() => useAdministrationItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error this is a mock
@ -31,7 +30,6 @@ it('should return omnichannel item if has `view-livechat-manager` permission ',
it('should show administration item if has at least one admin permission', async () => {
const { result } = renderHook(() => useAdministrationItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error this is a mock

@ -6,7 +6,6 @@ import { useAppsItems } from './useAppsItems';
it('should return and empty array if the user does not have `manage-apps` and `access-marketplace` permission', () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.build(),
@ -17,7 +16,6 @@ it('should return and empty array if the user does not have `manage-apps` and `a
it('should return `marketplace` and `installed` items if the user has `access-marketplace` permission', () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.withPermission('access-marketplace')
@ -39,7 +37,6 @@ it('should return `marketplace` and `installed` items if the user has `access-ma
it('should return `marketplace` and `installed` items if the user has `manage-apps` permission', () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [])
.withEndpoint('GET', '/apps/app-request/stats', () => ({
@ -73,7 +70,6 @@ it('should return `marketplace` and `installed` items if the user has `manage-ap
it('should return one action from the server with no conditions', async () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -117,7 +113,6 @@ it('should return one action from the server with no conditions', async () => {
describe('User Dropdown actions with role conditions', () => {
it('should return the action if the user has admin role', async () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -165,7 +160,6 @@ describe('User Dropdown actions with role conditions', () => {
it('should return filter the action if the user doesn`t have admin role', async () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -213,7 +207,6 @@ describe('User Dropdown actions with role conditions', () => {
describe('User Dropdown actions with permission conditions', () => {
it('should return the action if the user has manage-apps permission', async () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{
@ -259,7 +252,6 @@ describe('User Dropdown actions with permission conditions', () => {
it('should return filter the action if the user doesn`t have `any` permission', async () => {
const { result } = renderHook(() => useAppsItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/actionButtons', () => [
{

@ -5,7 +5,6 @@ import { useAuditItems } from './useAuditItems';
it('should return an empty array if doesn`t have license', async () => {
const { result } = renderHook(() => useAuditItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
// @ts-expect-error: just for testing
@ -24,7 +23,6 @@ it('should return an empty array if doesn`t have license', async () => {
it('should return an empty array if have license and not have permissions', async () => {
const { result } = renderHook(() => useAuditItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@ -46,7 +44,6 @@ it('should return an empty array if have license and not have permissions', asyn
it('should return auditItems if have license and permissions', async () => {
const { result } = renderHook(() => useAuditItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@ -81,7 +78,6 @@ it('should return auditItems if have license and permissions', async () => {
it('should return auditMessages item if have license and can-audit permission', async () => {
const { result } = renderHook(() => useAuditItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {
@ -109,7 +105,6 @@ it('should return auditMessages item if have license and can-audit permission',
it('should return audiLogs item if have license and can-audit-log permission', async () => {
const { result } = renderHook(() => useAuditItems(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/licenses.info', () => ({
license: {

@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { useGroupingListItems } from './useGroupingListItems';
it('should render groupingList items', async () => {
const { result } = renderHook(() => useGroupingListItems(), { legacyRoot: true });
const { result } = renderHook(() => useGroupingListItems());
expect(result.current[0]).toEqual(
expect.objectContaining({

@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { useSortModeItems } from './useSortModeItems';
it('should render sortMode items', async () => {
const { result } = renderHook(() => useSortModeItems(), { legacyRoot: true });
const { result } = renderHook(() => useSortModeItems());
expect(result.current[0]).toEqual(
expect.objectContaining({

@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { useViewModeItems } from './useViewModeItems';
it('should render viewMode items', async () => {
const { result } = renderHook(() => useViewModeItems(), { legacyRoot: true });
const { result } = renderHook(() => useViewModeItems());
expect(result.current[0]).toEqual(
expect.objectContaining({

@ -7,7 +7,6 @@ import BannerSection from './BannerSection';
describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render null if restricted and not admin', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe({ roles: ['user'] })
.withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', 0)
@ -19,7 +18,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render null if admin and not restricted or warning', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', 8).build(),
});
@ -28,7 +26,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render warning message if admin and warning phase', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe()
.withRole('admin')
@ -41,7 +38,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render restriction message if admin and restricted phase', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe()
.withRole('admin')
@ -54,7 +50,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render restriction message instead of another banner', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe()
.withRole('admin')

@ -1,5 +1,4 @@
import { IconButton, SidebarV2Item, SidebarV2ItemAvatarWrapper, SidebarV2ItemMenu, SidebarV2ItemTitle } from '@rocket.chat/fuselage';
import { usePrefersReducedMotion } from '@rocket.chat/fuselage-hooks';
import type { Keys as IconName } from '@rocket.chat/icons';
import type { HTMLAttributes, ReactElement } from 'react';
import { memo, useState } from 'react';
@ -21,21 +20,19 @@ type CondensedProps = {
const Condensed = ({ icon, title, avatar, actions, unread, menu, badges, ...props }: CondensedProps) => {
const [menuVisibility, setMenuVisibility] = useState(!!window.DISABLE_ANIMATION);
const isReduceMotionEnabled = usePrefersReducedMotion();
const handleMenuEvent = {
[isReduceMotionEnabled ? 'onMouseEnter' : 'onTransitionEnd']: setMenuVisibility,
};
const handleFocus = () => setMenuVisibility(true);
const handlePointerEnter = () => setMenuVisibility(true);
return (
<SidebarV2Item {...props}>
<SidebarV2Item {...props} onFocus={handleFocus} onPointerEnter={handlePointerEnter}>
{avatar && <SidebarV2ItemAvatarWrapper>{avatar}</SidebarV2ItemAvatarWrapper>}
{icon && icon}
<SidebarV2ItemTitle unread={unread}>{title}</SidebarV2ItemTitle>
{badges && badges}
{actions && actions}
{menu && (
<SidebarV2ItemMenu {...handleMenuEvent}>
<SidebarV2ItemMenu>
{menuVisibility ? menu() : <IconButton tabIndex={-1} aria-hidden mini rcx-sidebar-v2-item__menu icon='kebab' />}
</SidebarV2ItemMenu>
)}

@ -9,7 +9,6 @@ import {
SidebarV2ItemMenu,
IconButton,
} from '@rocket.chat/fuselage';
import { usePrefersReducedMotion } from '@rocket.chat/fuselage-hooks';
import type { Keys as IconName } from '@rocket.chat/icons';
import type { HTMLAttributes, ReactNode } from 'react';
import { memo, useState } from 'react';
@ -52,14 +51,12 @@ const Extended = ({
}: ExtendedProps) => {
const formatDate = useShortTimeAgo();
const [menuVisibility, setMenuVisibility] = useState(!!window.DISABLE_ANIMATION);
const isReduceMotionEnabled = usePrefersReducedMotion();
const handleMenuEvent = {
[isReduceMotionEnabled ? 'onMouseEnter' : 'onTransitionEnd']: setMenuVisibility,
};
const handleFocus = () => setMenuVisibility(true);
const handlePointerEnter = () => setMenuVisibility(true);
return (
<SidebarV2Item href={href} selected={selected} {...props}>
<SidebarV2Item href={href} selected={selected} {...props} onFocus={handleFocus} onPointerEnter={handlePointerEnter}>
{avatar && <SidebarV2ItemAvatarWrapper>{avatar}</SidebarV2ItemAvatarWrapper>}
<SidebarV2ItemCol>
<SidebarV2ItemRow>
@ -72,7 +69,7 @@ const Extended = ({
{badges && badges}
{actions && actions}
{menu && (
<SidebarV2ItemMenu {...handleMenuEvent}>
<SidebarV2ItemMenu>
{menuVisibility ? menu() : <IconButton tabIndex={-1} aria-hidden mini rcx-sidebar-v2-item__menu icon='kebab' />}
</SidebarV2ItemMenu>
)}

@ -1,5 +1,4 @@
import { IconButton, SidebarV2Item, SidebarV2ItemAvatarWrapper, SidebarV2ItemMenu, SidebarV2ItemTitle } from '@rocket.chat/fuselage';
import { usePrefersReducedMotion } from '@rocket.chat/fuselage-hooks';
import type { Keys as IconName } from '@rocket.chat/icons';
import type { HTMLAttributes, ReactNode } from 'react';
import { memo, useState } from 'react';
@ -20,21 +19,19 @@ type MediumProps = {
const Medium = ({ icon, title, avatar, actions, badges, unread, menu, ...props }: MediumProps) => {
const [menuVisibility, setMenuVisibility] = useState(!!window.DISABLE_ANIMATION);
const isReduceMotionEnabled = usePrefersReducedMotion();
const handleMenuEvent = {
[isReduceMotionEnabled ? 'onMouseEnter' : 'onTransitionEnd']: setMenuVisibility,
};
const handleFocus = () => setMenuVisibility(true);
const handlePointerEnter = () => setMenuVisibility(true);
return (
<SidebarV2Item {...props}>
<SidebarV2Item {...props} onFocus={handleFocus} onPointerEnter={handlePointerEnter}>
<SidebarV2ItemAvatarWrapper>{avatar}</SidebarV2ItemAvatarWrapper>
{icon && icon}
<SidebarV2ItemTitle unread={unread}>{title}</SidebarV2ItemTitle>
{badges && badges}
{actions && actions}
{menu && (
<SidebarV2ItemMenu {...handleMenuEvent}>
<SidebarV2ItemMenu>
{menuVisibility ? menu() : <IconButton tabIndex={-1} aria-hidden mini rcx-sidebar-v2-item__menu icon='kebab' />}
</SidebarV2ItemMenu>
)}

@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { useGroupingListItems } from './useGroupingListItems';
it('should render groupingList items', async () => {
const { result } = renderHook(() => useGroupingListItems(), { legacyRoot: true });
const { result } = renderHook(() => useGroupingListItems());
expect(result.current[0]).toEqual(
expect.objectContaining({

@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { useSortModeItems } from './useSortModeItems';
it('should render sortMode items', async () => {
const { result } = renderHook(() => useSortModeItems(), { legacyRoot: true });
const { result } = renderHook(() => useSortModeItems());
expect(result.current[0]).toEqual(
expect.objectContaining({

@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { useViewModeItems } from './useViewModeItems';
it('should render viewMode items', async () => {
const { result } = renderHook(() => useViewModeItems(), { legacyRoot: true });
const { result } = renderHook(() => useViewModeItems());
expect(result.current[0]).toEqual(
expect.objectContaining({

@ -104,7 +104,6 @@ it('should return roomList, groupsCount and groupsList', async () => {
current: { roomList, groupsList, groupsCount },
},
} = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({}).build(),
});
@ -119,7 +118,6 @@ it('should return groupsCount with the correct count', async () => {
current: { groupsCount, roomList },
},
} = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({}).build(),
});
@ -135,7 +133,6 @@ it('should return roomList with the subscribed rooms and the correct length', as
current: { roomList },
},
} = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({}).build(),
});
expect(roomList).toContain(fakeRooms[0]);
@ -148,7 +145,6 @@ it('should return groupsList with "Conversations" if preference sidebarGroupByTy
current: { groupsList },
},
} = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({}).build(),
});
expect(groupsList).toContain('Conversations');
@ -161,7 +157,6 @@ it('should return groupsList with "Teams" if sidebarGroupByType is enabled and r
current: { groupsList, groupsCount },
},
} = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ sidebarGroupByType: true }).build(),
});
@ -176,7 +171,6 @@ it('should return groupsList with "Favorites" if sidebarShowFavorites is enabled
current: { groupsList, groupsCount },
},
} = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ sidebarShowFavorites: true, sidebarGroupByType: true }).build(),
});
@ -191,7 +185,6 @@ it('should return groupsList with "Discussions" if isDiscussionEnabled is enable
current: { groupsList, groupsCount },
},
} = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ isDiscussionEnabled: true, sidebarGroupByType: true }).build(),
});
@ -202,7 +195,6 @@ it('should return groupsList with "Discussions" if isDiscussionEnabled is enable
it('should return groupsList without "Discussions" if isDiscussionEnabled is disabled', async () => {
const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ isDiscussionEnabled: false, sidebarGroupByType: true }).build(),
});
expect(result.current.groupsList).not.toContain('Discussions');
@ -214,7 +206,6 @@ it('should remove corresponding items from roomList and return groupCount 0 when
current: { roomList, groupsCount, groupsList },
},
} = renderHook(() => useRoomList({ collapsedGroups: ['Channels'] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ sidebarGroupByType: true }).build(),
});
const channelsIndex = groupsList.indexOf('Channels');
@ -224,7 +215,6 @@ it('should remove corresponding items from roomList and return groupCount 0 when
it('should always return groupsCount and groupsList with the same length', async () => {
const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ sidebarGroupByType: true }).build(),
});
expect(result.current.groupsCount.length).toEqual(result.current.groupsList.length);
@ -232,7 +222,6 @@ it('should always return groupsCount and groupsList with the same length', async
it('should return "Unread" group with the correct items if sidebarShowUnread is enabled', async () => {
const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ sidebarShowUnread: true, sidebarGroupByType: true }).build(),
});
const unreadIndex = result.current.groupsList.indexOf('Unread');
@ -242,7 +231,6 @@ it('should return "Unread" group with the correct items if sidebarShowUnread is
it('should not include unread room in unread group if hideUnreadStatus is enabled', async () => {
const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({
sidebarShowUnread: true,
sidebarGroupByType: true,
@ -261,7 +249,6 @@ it('should not include unread room in unread group if hideUnreadStatus is enable
it('should accumulate unread data into `groupedUnreadInfo` when group is collapsed', async () => {
const { result } = renderHook(() => useRoomList({ collapsedGroups: ['Channels'] }), {
legacyRoot: true,
wrapper: getWrapperSettings({ sidebarGroupByType: true }).build(),
});
@ -281,7 +268,6 @@ it('should add to unread group when has thread unread, even if alert is false',
} as unknown as SubscriptionWithRoom;
const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({
sidebarGroupByType: true,
sidebarShowUnread: true,
@ -299,7 +285,6 @@ it('should not add room to unread group if thread unread is an empty array', asy
} as unknown as SubscriptionWithRoom;
const { result } = renderHook(() => useRoomList({ collapsedGroups: [] }), {
legacyRoot: true,
wrapper: getWrapperSettings({
sidebarGroupByType: true,
sidebarShowUnread: true,

@ -107,7 +107,6 @@ const wrapper = mockAppRoot()
it('should return correct unread data for [Direct message unread]', async () => {
const { result } = renderHook(() => useUnreadDisplay(dmUnread), {
legacyRoot: true,
wrapper,
});
expect(result.current.unreadVariant).toBe('secondary');
@ -121,7 +120,6 @@ it('should return correct unread data for [Direct message unread]', async () =>
it('should return correct unread data for [Direct message with thread unread]', async () => {
const { result } = renderHook(() => useUnreadDisplay(dmThread), {
legacyRoot: true,
wrapper,
});
expect(result.current.unreadVariant).toBe('primary');
@ -135,7 +133,6 @@ it('should return correct unread data for [Direct message with thread unread]',
it('should return correct unread data for [Channel with unread messages alert only]', async () => {
const { result } = renderHook(() => useUnreadDisplay(alert), {
legacyRoot: true,
wrapper,
});
@ -150,7 +147,6 @@ it('should return correct unread data for [Channel with unread messages alert on
it('should return correct unread data for [Mention and group mention]', async () => {
const { result } = renderHook(() => useUnreadDisplay(mentionAndGroupMention), {
legacyRoot: true,
wrapper,
});
expect(result.current.unreadVariant).toBe('danger');
@ -164,7 +160,6 @@ it('should return correct unread data for [Mention and group mention]', async ()
it('should return correct unread data for [Group mention]', async () => {
const { result } = renderHook(() => useUnreadDisplay(groupMention), {
legacyRoot: true,
wrapper,
});
expect(result.current.unreadVariant).toBe('warning');
@ -178,7 +173,6 @@ it('should return correct unread data for [Group mention]', async () => {
it('should return correct unread data for [Thread unread]', async () => {
const { result } = renderHook(() => useUnreadDisplay(tunread), {
legacyRoot: true,
wrapper,
});
expect(result.current.unreadVariant).toBe('primary');
@ -192,7 +186,6 @@ it('should return correct unread data for [Thread unread]', async () => {
it('should return correct unread data for [Thread and thread user mention]', async () => {
const { result } = renderHook(() => useUnreadDisplay(tunreadUser), {
legacyRoot: true,
wrapper,
});
expect(result.current.unreadVariant).toBe('danger');
@ -205,27 +198,21 @@ it('should return correct unread data for [Thread and thread user mention]', asy
});
it('should not highlight unread if hideUnreadStatus is enabled', async () => {
const { result } = renderHook(() => useUnreadDisplay(hideUnreadStatus), {
legacyRoot: true,
});
const { result } = renderHook(() => useUnreadDisplay(hideUnreadStatus));
expect(result.current.highlightUnread).toBe(false);
expect(result.current.showUnread).toBe(true);
});
it('should not show unread if hideUnreadStatus and hideMentionStatus is enabled', async () => {
const { result } = renderHook(() => useUnreadDisplay(hideUnreadAndMention), {
legacyRoot: true,
});
const { result } = renderHook(() => useUnreadDisplay(hideUnreadAndMention));
expect(result.current.highlightUnread).toBe(false);
expect(result.current.showUnread).toBe(false);
});
it("should not show unread if there isn't any unread message", async () => {
const { result } = renderHook(() => useUnreadDisplay(noUnread), {
legacyRoot: true,
});
const { result } = renderHook(() => useUnreadDisplay(noUnread));
expect(result.current.highlightUnread).toBe(false);
expect(result.current.showUnread).toBe(false);

@ -7,7 +7,6 @@ import BannerSection from './BannerSection';
describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render null if restricted and not admin', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe({ roles: ['user'] })
.withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', 0)
@ -19,7 +18,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render null if admin and not restricted or warning', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withSetting('Cloud_Workspace_AirGapped_Restrictions_Remaining_Days', 8).build(),
});
@ -28,7 +26,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render warning message if admin and warning phase', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe()
.withRole('admin')
@ -41,7 +38,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render restriction message if admin and restricted phase', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe()
.withRole('admin')
@ -54,7 +50,6 @@ describe('Sidebar -> BannerSection -> Airgapped restriction', () => {
it('Should render restriction message instead of another banner', () => {
render(<BannerSection />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe()
.withRole('admin')

@ -1,5 +1,5 @@
import { StrictMode } from 'react';
import { render } from 'react-dom';
import { createRoot } from 'react-dom/client';
import AppRoot from '../views/root/AppRoot';
@ -17,9 +17,10 @@ const createContainer = (): Element => {
const container = createContainer();
render(
const root = createRoot(container);
root.render(
<StrictMode>
<AppRoot />
</StrictMode>,
container,
);

@ -28,7 +28,6 @@ describe('CustomEmoji Component', () => {
it('renders emoji list', async () => {
render(<CustomEmoji onClick={mockOnClick} reload={mockRef} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -39,7 +38,6 @@ describe('CustomEmoji Component', () => {
it("renders emoji's aliases as comma-separated values when aliases is an array", async () => {
render(<CustomEmoji onClick={mockOnClick} reload={mockRef} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -50,7 +48,6 @@ describe('CustomEmoji Component', () => {
it("renders emoji's aliases values when aliases is a string", async () => {
render(<CustomEmoji onClick={mockOnClick} reload={mockRef} />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/v1/emoji-custom.all', () => ({
count: 1,

@ -52,7 +52,7 @@ describe('TimespanSettingInput component', () => {
placeholder='Enter timespan'
onChangeValue={onChangeValueMock}
/>,
{ wrapper: mockAppRoot().build(), legacyRoot: true },
{ wrapper: mockAppRoot().build() },
);
const numberInput = screen.getByRole('spinbutton');
@ -74,7 +74,7 @@ describe('TimespanSettingInput component', () => {
placeholder='Enter timespan'
onChangeValue={onChangeValueMock}
/>,
{ wrapper: mockAppRoot().build(), legacyRoot: true },
{ wrapper: mockAppRoot().build() },
);
const selectInput = screen.getByRole('button', { name: 'hours' });
@ -99,7 +99,7 @@ describe('TimespanSettingInput component', () => {
placeholder='Enter timespan'
onChangeValue={onChangeValueMock}
/>,
{ wrapper: mockAppRoot().build(), legacyRoot: true },
{ wrapper: mockAppRoot().build() },
);
const selectInput = screen.getByRole('button', { name: 'days' });
@ -124,7 +124,7 @@ describe('TimespanSettingInput component', () => {
placeholder='Enter timespan'
onChangeValue={onChangeValueMock}
/>,
{ wrapper: mockAppRoot().build(), legacyRoot: true },
{ wrapper: mockAppRoot().build() },
);
const selectInput = screen.getByRole('button', { name: 'hours' });
@ -150,7 +150,7 @@ describe('TimespanSettingInput component', () => {
hasResetButton
onResetButtonClick={onResetButtonClickMock}
/>,
{ wrapper: mockAppRoot().build(), legacyRoot: true },
{ wrapper: mockAppRoot().build() },
);
const resetButton = screen.getByTitle('Reset');

@ -1,5 +1,5 @@
import { Field, FieldLabel, FieldRow, InputBox, Select } from '@rocket.chat/fuselage';
import type { FormEventHandler, ReactElement } from 'react';
import type { FormEventHandler, Key, ReactElement } from 'react';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
@ -62,7 +62,7 @@ function TimespanSettingInput({
setInternalValue(newValue);
};
const handleChangeTimeUnit = (nextTimeUnit: string | number) => {
const handleChangeTimeUnit = (nextTimeUnit: Key) => {
if (typeof nextTimeUnit !== 'string') {
return;
}
@ -72,7 +72,7 @@ function TimespanSettingInput({
const timeUnitOptions = useMemo(() => {
return Object.entries(TIMEUNIT).map<readonly [TIMEUNIT, string]>(([label, value]) => [value, i18n.exists(label) ? t(label) : label]); // todo translate
}, [t]);
}, [i18n, t]);
const handleResetButtonClick = () => {
onResetButtonClick?.();

@ -10,7 +10,6 @@ it('should call onClose when Cancel is clicked', async () => {
render(<CreateOAuthModal onConfirm={onConfirm} onClose={onClose} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
await userEvent.click(screen.getByText('Cancel'));
@ -24,7 +23,6 @@ it('should call onClose when X is clicked', async () => {
render(<CreateOAuthModal onConfirm={onConfirm} onClose={onClose} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
await userEvent.click(screen.getByLabelText('Close'));
@ -38,7 +36,6 @@ it('should call onConfirm when Add button is clicked', async () => {
render(<CreateOAuthModal onConfirm={onConfirm} onClose={onClose} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
const custoOAuthNameInput = screen.getByLabelText('Custom_OAuth_name');

@ -13,7 +13,6 @@ it('should display plan name in the title', async () => {
Cancel__planName__subscription: 'Cancel {{planName}} subscription',
})
.build(),
legacyRoot: true,
});
expect(screen.getByText('Cancel Starter subscription')).toBeInTheDocument();
@ -28,7 +27,6 @@ it('should have link to downgrade docs', async () => {
'<strong>This workspace will downgrage to Community and lose free access to premium capabilities.</strong><br/><br/> While you can keep using Rocket.Chat, your team will lose access to unlimited mobile push notifications, read receipts, marketplace apps <4>and other capabilities</4>.',
})
.build(),
legacyRoot: true,
});
expect(screen.getByRole('link', { name: 'and other capabilities' })).toHaveAttribute('href', DOWNGRADE_LINK);
@ -38,7 +36,6 @@ it('should call onConfirm when confirm button is clicked', async () => {
const confirmFn = jest.fn();
render(<CancelSubscriptionModal planName='Starter' onConfirm={confirmFn} onCancel={jest.fn()} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
await userEvent.click(screen.getByRole('button', { name: 'Cancel_subscription' }));
@ -49,7 +46,6 @@ it('should call onCancel when "Dont cancel" button is clicked', async () => {
const cancelFn = jest.fn();
render(<CancelSubscriptionModal planName='Starter' onConfirm={jest.fn()} onCancel={cancelFn} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
await userEvent.click(screen.getByRole('button', { name: 'Dont_cancel' }));
@ -60,7 +56,6 @@ it('should call onCancel when close button is clicked', async () => {
const cancelFn = jest.fn();
render(<CancelSubscriptionModal planName='Starter' onConfirm={jest.fn()} onCancel={cancelFn} />, {
wrapper: mockAppRoot().build(),
legacyRoot: true,
});
await userEvent.click(screen.getByRole('button', { name: 'Close' }));

@ -11,7 +11,7 @@ const appRoot = mockAppRoot().withTranslations('en', 'core', {
});
it('should render a skeleton if no data', () => {
render(<AppsUsageCard />, { wrapper: appRoot.build(), legacyRoot: true });
render(<AppsUsageCard />, { wrapper: appRoot.build() });
expect(screen.getByRole('heading', { name: 'Apps' })).toBeInTheDocument();
expect(screen.getByRole('presentation')).toBeInTheDocument();
@ -20,7 +20,6 @@ it('should render a skeleton if no data', () => {
it('should render data as progress bars', async () => {
render(<AppsUsageCard privateAppsLimit={{ value: 1, max: 3 }} marketplaceAppsLimit={{ value: 2, max: 5 }} />, {
wrapper: appRoot.build(),
legacyRoot: true,
});
expect(screen.getByRole('heading', { name: 'Apps' })).toBeInTheDocument();
@ -45,7 +44,6 @@ it('should render data as progress bars', async () => {
it('should render an upgrade button if marketplace apps reached 80% of the limit', async () => {
render(<AppsUsageCard privateAppsLimit={{ value: 1, max: 3 }} marketplaceAppsLimit={{ value: 4, max: 5 }} />, {
wrapper: appRoot.build(),
legacyRoot: true,
});
expect(screen.getByRole('heading', { name: 'Apps' })).toBeInTheDocument();
@ -64,7 +62,6 @@ it('should render an upgrade button if marketplace apps reached 80% of the limit
it('should render a full progress bar with private apps disabled', async () => {
render(<AppsUsageCard privateAppsLimit={{ value: 0, max: 0 }} marketplaceAppsLimit={{ value: 2, max: 5 }} />, {
wrapper: appRoot.build(),
legacyRoot: true,
});
expect(screen.getByRole('heading', { name: 'Apps' })).toBeInTheDocument();

@ -17,7 +17,6 @@ it('should open modal when open method is called', () => {
Cancel__planName__subscription: 'Cancel {{planName}} subscription',
})
.build(),
legacyRoot: true,
});
expect(screen.queryByText('Cancel Starter subscription')).not.toBeInTheDocument();
@ -34,7 +33,6 @@ it('should close modal cancel is clicked', async () => {
Cancel__planName__subscription: 'Cancel {{planName}} subscription',
})
.build(),
legacyRoot: true,
});
act(() => result.current.open());
@ -55,7 +53,6 @@ it('should call remove license endpoint when confirm is clicked', async () => {
Cancel__planName__subscription: 'Cancel {{planName}} subscription',
})
.build(),
legacyRoot: true,
});
act(() => result.current.open());

@ -7,7 +7,6 @@ import UsersPageHeaderContent from './UsersPageHeaderContent';
it('should not show "Assign Extension" button if voip setting is enabled but user dont have required permission', async () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withSetting('VoIP_TeamCollab_Enabled', true).build(),
});
@ -16,7 +15,6 @@ it('should not show "Assign Extension" button if voip setting is enabled but use
it('should not show "Assign Extension" button if user has required permission but voip setting is disabled', async () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withSetting('VoIP_TeamCollab_Enabled', true).build(),
});
@ -25,7 +23,6 @@ it('should not show "Assign Extension" button if user has required permission bu
it('should show "Assign Extension" button if user has required permission and voip setting is enabled', async () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withSetting('VoIP_TeamCollab_Enabled', true).withPermission('manage-voip-extensions').build(),
});
@ -35,7 +32,6 @@ it('should show "Assign Extension" button if user has required permission and vo
it('should not render "Associate Extension" button when VoIP_TeamCollab_Enabled setting is disabled', async () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withSetting('VoIP_TeamCollab_Enabled', false).build(),
});
@ -44,7 +40,6 @@ it('should not render "Associate Extension" button when VoIP_TeamCollab_Enabled
it('should show "Invite" button if has build-register-user permission', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withPermission('bulk-register-user').build(),
});
@ -53,7 +48,6 @@ it('should show "Invite" button if has build-register-user permission', () => {
it('should hide "Invite" button if user doesnt have build-register-user permission', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().build(),
});
@ -62,7 +56,6 @@ it('should hide "Invite" button if user doesnt have build-register-user permissi
it('should show "New User" button if has create-user permission', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withPermission('create-user').build(),
});
@ -71,7 +64,6 @@ it('should show "New User" button if has create-user permission', () => {
it('should hide "New User" button if user doesnt have create-user permission', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().withPermission('create-user').build(),
});
@ -80,7 +72,6 @@ it('should hide "New User" button if user doesnt have create-user permission', (
it('should show "Buy more seats" button if seats caps is exceeded', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().build(),
});
@ -89,7 +80,6 @@ it('should show "Buy more seats" button if seats caps is exceeded', () => {
it('should hide "Buy more seats" button if seats caps is within limits', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 1 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().build(),
});
@ -98,7 +88,6 @@ it('should hide "Buy more seats" button if seats caps is within limits', () => {
it('should show seats available progress bar', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: 10 }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().build(),
});
@ -107,7 +96,6 @@ it('should show seats available progress bar', () => {
it('should hide seats available progress bar if theres no limit', () => {
render(<UsersPageHeaderContent isSeatsCapExceeded={false} seatsCap={{ activeUsers: 1, maxActiveUsers: Number.POSITIVE_INFINITY }} />, {
legacyRoot: true,
wrapper: mockAppRoot().withJohnDoe().build(),
});

@ -27,7 +27,6 @@ it('should not render voip extension column when voice call is disabled', async
roleData={undefined}
/>,
{
legacyRoot: true,
wrapper: mockAppRoot().withUser(user).withSetting('VoIP_TeamCollab_Enabled', false).build(),
},
);
@ -55,7 +54,6 @@ it('should not render voip extension column or actions if user doesnt have the r
roleData={undefined}
/>,
{
legacyRoot: true,
wrapper: mockAppRoot().withUser(user).withSetting('VoIP_TeamCollab_Enabled', true).build(),
},
);
@ -83,7 +81,6 @@ it('should render "Unassign_extension" button when user has a associated extensi
roleData={undefined}
/>,
{
legacyRoot: true,
wrapper: mockAppRoot().withUser(user).withSetting('VoIP_TeamCollab_Enabled', true).withPermission('manage-voip-extensions').build(),
},
);
@ -111,7 +108,6 @@ it('should render "Assign_extension" button when user has no associated extensio
roleData={undefined}
/>,
{
legacyRoot: true,
wrapper: mockAppRoot().withUser(user).withSetting('VoIP_TeamCollab_Enabled', true).withPermission('manage-voip-extensions').build(),
},
);

@ -46,7 +46,6 @@ it.todo('should load with default extension');
it('should only enable "Available extensions" field if username is informed', async () => {
render(<AssignExtensionModal onClose={() => undefined} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -63,7 +62,6 @@ it('should only enable "Available extensions" field if username is informed', as
it('should only enable "Associate" button both username and extension is informed', async () => {
render(<AssignExtensionModal onClose={() => undefined} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -86,7 +84,6 @@ it('should only enable "Associate" button both username and extension is informe
it('should call onClose when extension is associated', async () => {
const closeFn = jest.fn();
render(<AssignExtensionModal onClose={closeFn} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -108,7 +105,6 @@ it('should call onClose when extension is associated', async () => {
it('should call onClose when cancel button is clicked', () => {
const closeFn = jest.fn();
render(<AssignExtensionModal onClose={closeFn} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -119,7 +115,6 @@ it('should call onClose when cancel button is clicked', () => {
it('should call onClose when cancel button is clicked', () => {
const closeFn = jest.fn();
render(<AssignExtensionModal onClose={closeFn} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});

@ -8,7 +8,6 @@ const appRoot = mockAppRoot().withJohnDoe();
it('should have user and extension informed', async () => {
render(<RemoveExtensionModal name='John Doe' username='john.doe' extension='1000' onClose={() => undefined} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -20,7 +19,6 @@ it('should call assign endpoint and onClose when extension is removed', async ()
const closeFn = jest.fn();
const assignFn = jest.fn(() => null);
render(<RemoveExtensionModal name='John Doe' username='john.doe' extension='1000' onClose={closeFn} />, {
legacyRoot: true,
wrapper: appRoot.withEndpoint('POST', '/v1/voip-freeswitch.extension.assign', assignFn).build(),
});
@ -33,7 +31,6 @@ it('should call assign endpoint and onClose when extension is removed', async ()
it('should call onClose when cancel button is clicked', () => {
const closeFn = jest.fn();
render(<RemoveExtensionModal name='John Doe' username='john.doe' extension='1000' onClose={closeFn} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});
@ -44,7 +41,6 @@ it('should call onClose when cancel button is clicked', () => {
it('should call onClose when cancel button is clicked', () => {
const closeFn = jest.fn();
render(<RemoveExtensionModal name='John Doe' username='john.doe' extension='1000' onClose={closeFn} />, {
legacyRoot: true,
wrapper: appRoot.build(),
});

@ -1,7 +1,11 @@
import { Box } from '@rocket.chat/fuselage';
import type { AllHTMLAttributes } from 'react';
import type { ComponentPropsWithoutRef } from 'react';
const ToneSelectorWrapper = ({ caption, children, ...props }: { caption: string } & Omit<AllHTMLAttributes<HTMLDivElement>, 'is'>) => {
type ToneSelectorWrapperProps = {
caption: string;
} & Omit<ComponentPropsWithoutRef<typeof Box>, 'caption'>;
const ToneSelectorWrapper = ({ caption, children, ...props }: ToneSelectorWrapperProps) => {
return (
<Box {...props} display='flex' alignItems='center'>
<Box fontScale='c2'>{caption}</Box>

@ -1,9 +1,12 @@
import type { IRoom, Serialized } from '@rocket.chat/core-typings';
import { Box, Margins, Tag } from '@rocket.chat/fuselage';
import type { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
const RoomTags = ({ room }: { room: Serialized<IRoom> }): ReactElement => {
type RoomTagsProps = {
room: Serialized<IRoom>;
};
const RoomTags = ({ room }: RoomTagsProps) => {
const { t } = useTranslation();
return (

@ -88,10 +88,7 @@ const UsersTable = ({ workspace = 'local' }): ReactElement => {
const handleClick = useCallback(
(username: IUser['username']) => (e: KeyboardEvent | MouseEvent) => {
if (!username) {
return;
}
if (!username) return;
if (e.type === 'click' || (e as KeyboardEvent).key === 'Enter') {
directRoute.push({ rid: username });
}

@ -11,7 +11,6 @@ it('should look good', async () => {
const app = createFakeApp();
render(<AppStatus app={app} showStatus isAppDetailsPage />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withJohnDoe()
.withEndpoint('GET', '/apps/count', async () => ({

@ -11,7 +11,6 @@ describe('without app details', () => {
const app = createFakeApp();
render(<AppMenu app={app} isAppDetailsPage={false} />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('GET', '/apps/count', async () => ({
maxMarketplaceApps: faker.number.int({ min: 0 }),

@ -27,7 +27,7 @@ describe('with private apps enabled', () => {
));
it('should offer to upgrade to unlock private apps', () => {
render(<PrivateEmptyState />, { wrapper: appRoot.build(), legacyRoot: true });
render(<PrivateEmptyState />, { wrapper: appRoot.build() });
expect(screen.getByRole('heading', { name: 'No private apps installed' })).toBeInTheDocument();
});
@ -55,7 +55,7 @@ describe('without private apps enabled', () => {
));
it('should offer to upgrade to unlock private apps', () => {
render(<PrivateEmptyState />, { wrapper: appRoot.build(), legacyRoot: true });
render(<PrivateEmptyState />, { wrapper: appRoot.build() });
expect(screen.getByRole('heading', { name: 'Upgrade to unlock private apps' })).toBeInTheDocument();
});

@ -26,7 +26,7 @@ describe('with private apps enabled', () => {
));
it('should inform that the marketplace is unavailable due unsupported version', () => {
render(<UnsupportedEmptyState />, { wrapper: appRoot.build(), legacyRoot: true });
render(<UnsupportedEmptyState />, { wrapper: appRoot.build() });
expect(screen.getByRole('heading', { name: 'Marketplace unavailable' })).toBeInTheDocument();
});

@ -14,7 +14,6 @@ describe('in private context', () => {
Private_Apps_Count_Enabled_other: '{{count}} private apps enabled',
})
.build(),
legacyRoot: true,
});
expect(screen.getByText('1 private app enabled')).toBeInTheDocument();
@ -31,7 +30,6 @@ describe('in private context', () => {
Private_Apps_Count_Enabled_other: '{{count}} private apps enabled',
})
.build(),
legacyRoot: true,
});
expect(screen.getByText('0 private apps enabled')).toBeInTheDocument();
@ -50,7 +48,6 @@ describe.each(['explore', 'installed', 'premium', 'requested'] as const)('in %s
Apps_Count_Enabled_other: '{{count}} apps enabled',
})
.build(),
legacyRoot: true,
});
expect(screen.getByText('1 app enabled')).toBeInTheDocument();

@ -21,13 +21,13 @@ const ModalRegion = (): ReactElement | null => {
return (
<ModalPortal>
<Suspense fallback={null}>
<ModalBackdrop onDismiss={handleDismiss}>
<ModalBackdrop onDismiss={handleDismiss}>
<Suspense fallback={null}>
<FocusScope contain restoreFocus autoFocus>
<Suspense fallback={<div />}>{currentModal}</Suspense>
{currentModal}
</FocusScope>
</ModalBackdrop>
</Suspense>
</Suspense>
</ModalBackdrop>
</ModalPortal>
);
};

@ -82,12 +82,15 @@ const ModalBlock = ({ view, errors, onSubmit, onClose, onCancel }: ModalBlockPar
[previousFocus],
);
const formRef = useRef<HTMLFormElement>(null);
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
switch (event.keyCode) {
case KeyboardCode.get('ENTER'):
if ((event?.target as Node | null)?.nodeName !== 'TEXTAREA') {
return onSubmit(event as any); // FIXME
formRef.current?.submit();
return;
}
return;
case KeyboardCode.get('ESC'):
@ -123,7 +126,7 @@ const ModalBlock = ({ view, errors, onSubmit, onClose, onCancel }: ModalBlockPar
}
}
},
[onClose, onSubmit],
[onClose],
);
useEffect(() => {
@ -139,7 +142,7 @@ const ModalBlock = ({ view, errors, onSubmit, onClose, onCancel }: ModalBlockPar
return false;
};
const ignoreIfNotContains = (e: Event) => {
const ignoreIfNotContains = (e: KeyboardEvent) => {
if (e.target !== element) {
return;
}
@ -168,7 +171,7 @@ const ModalBlock = ({ view, errors, onSubmit, onClose, onCancel }: ModalBlockPar
<Modal.Close tabIndex={-1} onClick={onClose} />
</Modal.Header>
<Modal.Content>
<Box is='form' method='post' action='#' onSubmit={onSubmit}>
<Box ref={formRef} is='form' method='post' action='#' onSubmit={onSubmit}>
<UiKitComponent render={UiKitModal} blocks={view.blocks} />
</Box>
</Modal.Content>

@ -6,7 +6,7 @@ import NotFoundPage from './NotFoundPage';
import RouterContextMock from '../../../tests/mocks/client/RouterContextMock';
it('should look good', async () => {
render(<NotFoundPage />, { legacyRoot: true });
render(<NotFoundPage />);
await expect(screen.findByRole('heading')).resolves.toHaveTextContent('Page_not_found');
@ -14,7 +14,7 @@ it('should look good', async () => {
});
it('should have correct tab order', async () => {
render(<NotFoundPage />, { legacyRoot: true });
render(<NotFoundPage />);
expect(document.body).toHaveFocus();
@ -36,7 +36,6 @@ describe('"Return to home" button', () => {
<RouterContextMock currentPath={currentPath}>
<NotFoundPage />
</RouterContextMock>,
{ legacyRoot: true },
);
const button = screen.getByRole('button', { name: 'Homepage' });

@ -1,16 +1,16 @@
import { Button, ButtonGroup } from '@rocket.chat/fuselage';
import { useRouter } from '@rocket.chat/ui-contexts';
import { lazy, useMemo } from 'react';
import { lazy } from 'react';
import { useTranslation } from 'react-i18next';
import { Page, PageHeader, PageContent } from '../../../components/Page';
const BusinessHoursTable = lazy(() => import('../../../omnichannel/businessHours/BusinessHoursTable'));
const BusinessHoursMultiplePage = () => {
const { t } = useTranslation();
const router = useRouter();
const BusinessHoursTable = useMemo(() => lazy(() => import('../../../omnichannel/businessHours/BusinessHoursTable')), []);
return (
<Page>
<PageHeader title={t('Business_Hours')}>

@ -7,7 +7,6 @@ import type { RoomToolboxActionConfig } from '../../../contexts/RoomToolboxConte
describe('useRoomToolboxActions', () => {
it('should return an empty array if there are no actions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions: [], openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
expect(result.current.featuredActions).toEqual([]);
@ -17,7 +16,6 @@ describe('useRoomToolboxActions', () => {
it('should return apps actions only inside hiddenActions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions: appsActions, openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
const appsSection = result.current.hiddenActions[0];
@ -30,7 +28,6 @@ describe('useRoomToolboxActions', () => {
it('should return max of 6 items on visibleActions and the rest items inside hiddenActions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions, openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
expect(result.current.hiddenActions.length).toBeGreaterThan(0);
@ -39,7 +36,6 @@ describe('useRoomToolboxActions', () => {
it('should return featured items inside featuredActions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions, openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
expect(result.current.featuredActions).toMatchObject(actions.filter((action) => action.featured));

@ -7,7 +7,6 @@ import type { RoomToolboxActionConfig } from '../../../contexts/RoomToolboxConte
describe('useRoomToolboxActions', () => {
it('should return an empty array if there are no actions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions: [], openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
expect(result.current.featuredActions).toEqual([]);
@ -17,7 +16,6 @@ describe('useRoomToolboxActions', () => {
it('should return apps actions only inside hiddenActions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions: appsActions, openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
const appsSection = result.current.hiddenActions[0];
@ -30,7 +28,6 @@ describe('useRoomToolboxActions', () => {
it('should return max of 6 items on visibleActions and the rest items inside hiddenActions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions, openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
expect(result.current.hiddenActions.length).toBeGreaterThan(0);
@ -39,7 +36,6 @@ describe('useRoomToolboxActions', () => {
it('should return featured items inside featuredActions', () => {
const { result } = renderHook(() => useRoomToolboxActions({ actions, openTab: () => undefined }), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
expect(result.current.featuredActions).toMatchObject(actions.filter((action) => action.featured));

@ -5,7 +5,6 @@ import { useKatex } from './useKatex';
it('should return enabled true dollar syntax true and parenthesis syntax true if all settings is enabled', () => {
const { result } = renderHook(() => useKatex(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withSetting('Katex_Enabled', true)
.withSetting('Katex_Dollar_Syntax', true)
@ -20,7 +19,6 @@ it('should return enabled true dollar syntax true and parenthesis syntax true if
it('should return enabled false dollar syntax false and parenthesis syntax false if all settings is disabled', () => {
const { result } = renderHook(() => useKatex(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withSetting('Katex_Enabled', false)
.withSetting('Katex_Dollar_Syntax', false)
@ -35,7 +33,6 @@ it('should return enabled false dollar syntax false and parenthesis syntax false
it('should return enabled true dollar syntax false and parenthesis syntax false if Katex_Enabled settings is enable', () => {
const { result } = renderHook(() => useKatex(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withSetting('Katex_Enabled', true)
.withSetting('Katex_Dollar_Syntax', false)
@ -50,7 +47,6 @@ it('should return enabled true dollar syntax false and parenthesis syntax false
it('should return enabled false dollar syntax false and parenthesis syntax false if DollarSyntaxEnabled and ParenthesisSyntaxEnabled settings is enable', () => {
const { result } = renderHook(() => useKatex(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withSetting('Katex_Enabled', false)
.withSetting('Katex_Dollar_Syntax', true)

@ -1,13 +1,15 @@
import { RoomBanner, RoomBannerContent } from '@rocket.chat/ui-client';
import type { FC, MouseEvent } from 'react';
import type { MouseEvent, ReactNode } from 'react';
type AnnouncementComponenttParams = {
type AnnouncementComponentProps = {
children: ReactNode;
onClickOpen: (e: MouseEvent<HTMLAnchorElement>) => void;
};
const AnnouncementComponent: FC<AnnouncementComponenttParams> = ({ children, onClickOpen }) => (
const AnnouncementComponent = ({ children, onClickOpen }: AnnouncementComponentProps) => (
<RoomBanner className='rcx-header-section rcx-announcement-section' onClick={onClickOpen}>
<RoomBannerContent data-qa='AnnouncementAnnoucementComponent'>{children}</RoomBannerContent>
</RoomBanner>
);
export default AnnouncementComponent;

@ -14,7 +14,6 @@ describe('RetentionPolicyWarning', () => {
it('Should render callout if settings are valid', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
render(<RetentionPolicyWarning room={fakeRoom} />, {
legacyRoot: true,
wrapper: createMock({ appliesToChannels: true, TTLChannels: 60000 }),
});
expect(screen.getByRole('alert')).toHaveTextContent('a minute June 1, 2024 at 12:30 AM');
@ -23,7 +22,6 @@ describe('RetentionPolicyWarning', () => {
it('Should not render callout if settings are invalid', () => {
const fakeRoom = createFakeRoom({ t: 'c' });
render(<RetentionPolicyWarning room={fakeRoom} />, {
legacyRoot: true,
wrapper: createMock({ appliesToChannels: true, TTLChannels: 60000, advancedPrecisionCron: '* * * 12 *', advancedPrecision: true }),
});
expect(screen.queryByRole('alert')).not.toBeInTheDocument();

@ -40,7 +40,7 @@ describe('useGetMore', () => {
const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: mockElement });
const { unmount } = renderHook(() => useGetMore('room-id', atBottomRef), { legacyRoot: true });
const { unmount } = renderHook(() => useGetMore('room-id', atBottomRef));
expect(useRefSpy).toHaveBeenCalledWith(null);
expect(RoomHistoryManager.getMore).toHaveBeenCalledWith('room-id');
@ -72,7 +72,7 @@ describe('useGetMore', () => {
};
const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: mockElement });
renderHook(() => useGetMore('room-id', atBottomRef), { legacyRoot: true });
renderHook(() => useGetMore('room-id', atBottomRef));
expect(useRefSpy).toHaveBeenCalledWith(null);
expect(RoomHistoryManager.getMoreNext).toHaveBeenCalledWith('room-id', atBottomRef);

@ -21,7 +21,7 @@ describe('useRestoreScrollPosition', () => {
const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: mockElement });
const { unmount } = renderHook(() => useRestoreScrollPosition('room-id'), { legacyRoot: true });
const { unmount } = renderHook(() => useRestoreScrollPosition('room-id'));
expect(useRefSpy).toHaveBeenCalledWith(null);
expect(mockElement).toHaveProperty('scrollTop', 100);
@ -42,7 +42,7 @@ describe('useRestoreScrollPosition', () => {
const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: mockElement });
const { unmount } = renderHook(() => useRestoreScrollPosition('room-id'), { legacyRoot: true });
const { unmount } = renderHook(() => useRestoreScrollPosition('room-id'));
expect(useRefSpy).toHaveBeenCalledWith(null);
expect(mockElement).toHaveProperty('scrollTop', 800);
@ -71,7 +71,7 @@ describe('useRestoreScrollPosition', () => {
const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: mockElement });
const { unmount } = renderHook(() => useRestoreScrollPosition('room-id'), { legacyRoot: true });
const { unmount } = renderHook(() => useRestoreScrollPosition('room-id'));
expect(useRefSpy).toHaveBeenCalledWith(null);
expect(update).toHaveBeenCalledWith({ scroll: 500, atBottom: false });

@ -23,7 +23,6 @@ const renderOptions = {
E2EE_Composer_Unencrypted_Message: "You're sending an unencrypted message",
})
.build(),
legacyRoot: true,
};
describe('MessageBoxHint', () => {

@ -3,7 +3,7 @@ import type { SelectOption } from '@rocket.chat/fuselage';
import { Box, Icon, TextInput, Select, Throbber, ButtonGroup, Button, Callout } from '@rocket.chat/fuselage';
import { useAutoFocus, useDebouncedCallback } from '@rocket.chat/fuselage-hooks';
import { useTranslation, useSetting } from '@rocket.chat/ui-contexts';
import type { ReactElement, FormEventHandler, ComponentProps, MouseEvent } from 'react';
import type { ReactElement, FormEventHandler, ComponentProps, MouseEvent, ElementType } from 'react';
import { useMemo } from 'react';
import { GroupedVirtuoso } from 'react-virtuoso';
@ -31,7 +31,7 @@ type RoomMembersProps = {
loading: boolean;
text: string;
type: string;
setText: FormEventHandler<HTMLElement>;
setText: FormEventHandler<HTMLInputElement>;
setType: (type: 'online' | 'all') => void;
members: RoomMemberUser[];
total: number;
@ -41,7 +41,7 @@ type RoomMembersProps = {
onClickAdd?: () => void;
onClickInvite?: () => void;
loadMoreItems: () => void;
renderRow?: (props: ComponentProps<typeof RoomMembersRow>) => ReactElement | null;
renderRow?: ElementType<ComponentProps<typeof RoomMembersRow>>;
reload: () => void;
};

@ -16,7 +16,7 @@ describe('with window.RocketChatDesktop set', () => {
});
it('should pass to videoConfOpenCall the url', async () => {
const { result } = renderHook(() => useVideoConfOpenCall(), { legacyRoot: true, wrapper: mockAppRoot().build() });
const { result } = renderHook(() => useVideoConfOpenCall(), { wrapper: mockAppRoot().build() });
const url = faker.internet.url();
@ -28,7 +28,7 @@ describe('with window.RocketChatDesktop set', () => {
});
it('should pass to videoConfOpenCall the url and the providerName', async () => {
const { result } = renderHook(() => useVideoConfOpenCall(), { legacyRoot: true, wrapper: mockAppRoot().build() });
const { result } = renderHook(() => useVideoConfOpenCall(), { wrapper: mockAppRoot().build() });
const url = faker.internet.url();
const providerName = faker.lorem.word();
@ -54,7 +54,6 @@ describe('without window.RocketChatDesktop set', () => {
window.open = jest.fn(() => ({}) as Window);
const { result } = renderHook(() => useVideoConfOpenCall(), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});
@ -71,7 +70,6 @@ describe('without window.RocketChatDesktop set', () => {
window.open = jest.fn(() => null);
const { result } = renderHook(() => useVideoConfOpenCall(), {
legacyRoot: true,
wrapper: mockAppRoot().build(),
});

@ -30,7 +30,6 @@ describe('useE2EEResetRoomKey', () => {
it('should call resetRoomKey endpoint with correct params', async () => {
const { result } = renderHook(() => useE2EEResetRoomKey(), {
legacyRoot: true,
wrapper: mockAppRoot().withEndpoint('POST', '/v1/e2e.resetRoomKey', resetRoomKeyMock).build(),
});
@ -53,7 +52,6 @@ describe('useE2EEResetRoomKey', () => {
(e2e.getInstanceByRoomId as jest.Mock).mockReturnValue(null);
const { result } = renderHook(() => useE2EEResetRoomKey(), {
legacyRoot: true,
wrapper: mockAppRoot().withEndpoint('POST', '/v1/e2e.resetRoomKey', resetRoomKeyMock).build(),
});
@ -75,7 +73,6 @@ describe('useE2EEResetRoomKey', () => {
}));
const { result } = renderHook(() => useE2EEResetRoomKey(), {
legacyRoot: true,
wrapper: mockAppRoot().withEndpoint('POST', '/v1/e2e.resetRoomKey', resetRoomKeyMock).build(),
});
@ -93,7 +90,6 @@ describe('useE2EEResetRoomKey', () => {
it('should return an error if resetRoomKey does not resolve', async () => {
resetRoomKeyMock.mockRejectedValue(new Error('error-e2e-key-reset-in-progress'));
const { result } = renderHook(() => useE2EEResetRoomKey(), {
legacyRoot: true,
wrapper: mockAppRoot().withEndpoint('POST', '/v1/e2e.resetRoomKey', resetRoomKeyMock).build(),
});

@ -43,7 +43,6 @@ it('should return the default value if global retention is not enabled', async (
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE });
const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({}).build(),
});
@ -54,7 +53,6 @@ it('should return enabled true if global retention is enabled', async () => {
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE });
const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({ enabled: true }).build(),
});
@ -65,7 +63,6 @@ it('should return enabled and active true global retention is active for rooms o
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE });
const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({ enabled: true, ...roomTypeConfig[CHANNELS_TYPE] }).build(),
});
@ -76,7 +73,6 @@ it('should isActive be false if global retention is active for rooms of the type
const fakeRoom = createFakeRoom({ t: CHANNELS_TYPE, retention: { enabled: false } });
const { result } = renderHook(() => useRetentionPolicy(fakeRoom), {
legacyRoot: true,
wrapper: getGlobalSettings({ enabled: true, ...roomTypeConfig[CHANNELS_TYPE] }).build(),
});

@ -9,7 +9,6 @@ it('should work', async () => {
const endpointHandler = jest.fn(() => null);
const { result } = renderHook(() => useToggleFavoriteMutation(), {
legacyRoot: true,
wrapper: mockAppRoot().withEndpoint('POST', '/v1/rooms.favorite', endpointHandler).build(),
});
@ -27,7 +26,6 @@ it('should invalidate any subscription queries', async () => {
jest.spyOn(queryClient, 'invalidateQueries');
const { result } = renderHook(() => useToggleFavoriteMutation(), {
legacyRoot: true,
wrapper: mockAppRoot()
.withEndpoint('POST', '/v1/rooms.favorite', async () => null)
.wrap((children) => <QueryClientProvider client={queryClient} children={children} />)

@ -16,7 +16,6 @@ const defaultProps = {
it('should show Undo request button when roomOpen is true and transcriptRequest exist', async () => {
render(<FileUploadModal {...defaultProps} />, {
legacyRoot: true,
wrapper: mockAppRoot()
.withTranslations('en', 'core', {
Cannot_upload_file_character_limit: 'Cannot upload file, description is over the {{count}} character limit',

@ -44,7 +44,7 @@ const UserCardProvider = ({ children }: { children: ReactNode }) => {
const handleSetUserCard = useCallback(
(e: UIEvent, username: string) => {
triggerRef.current = e.target as Element;
triggerRef.current = e.target as Element | null;
state.open();
setUserCardData({
username,

@ -81,14 +81,12 @@ describe('useChatMessagesInstance', () => {
});
it('should initialize ChatMessages instance with correct arguments', () => {
const { result } = renderHook(
() =>
useChatMessagesInstance({
rid: mockSubscription.rid,
tmid: 'threadId',
encrypted: false,
}),
{ legacyRoot: true },
const { result } = renderHook(() =>
useChatMessagesInstance({
rid: mockSubscription.rid,
tmid: 'threadId',
encrypted: false,
}),
);
expect(ChatMessages).toHaveBeenCalledWith({
@ -105,14 +103,12 @@ describe('useChatMessagesInstance', () => {
});
it('should update ChatMessages subscription', () => {
const { result, rerender } = renderHook(
() =>
useChatMessagesInstance({
rid: mockSubscription.rid,
tmid: 'threadId',
encrypted: false,
}),
{ legacyRoot: true },
const { result, rerender } = renderHook(() =>
useChatMessagesInstance({
rid: mockSubscription.rid,
tmid: 'threadId',
encrypted: false,
}),
);
expect(ChatMessages).toHaveBeenCalledWith({
@ -145,14 +141,12 @@ describe('useChatMessagesInstance', () => {
});
it('should update ChatMessages instance when dependencies changes', () => {
const { result, rerender } = renderHook(
() =>
useChatMessagesInstance({
rid: mockSubscription.rid,
tmid: 'threadId',
encrypted: false,
}),
{ legacyRoot: true },
const { result, rerender } = renderHook(() =>
useChatMessagesInstance({
rid: mockSubscription.rid,
tmid: 'threadId',
encrypted: false,
}),
);
expect(ChatMessages).toHaveBeenCalledWith({
@ -190,7 +184,7 @@ describe('useChatMessagesInstance', () => {
tmid: 'threadId',
encrypted: false,
};
const { result, rerender } = renderHook((props = initialProps) => useChatMessagesInstance(props as any), { legacyRoot: true });
const { result, rerender } = renderHook((props = initialProps) => useChatMessagesInstance(props as any));
expect(ChatMessages).toHaveBeenCalledWith({
rid: mockSubscription.rid,

@ -6,7 +6,6 @@ describe('useDepsMatch', () => {
it('should return true when dependencies match', () => {
const { result, rerender } = renderHook(({ deps }) => useDepsMatch(deps), {
initialProps: { deps: ['dep1', 'dep2'] },
legacyRoot: true,
});
expect(result.current).toBe(true);
@ -19,7 +18,6 @@ describe('useDepsMatch', () => {
it('should return false when dependencies do not match', () => {
const { result, rerender } = renderHook(({ deps }) => useDepsMatch(deps), {
initialProps: { deps: ['dep1', 'dep2'] },
legacyRoot: true,
});
expect(result.current).toBe(true);
@ -32,7 +30,6 @@ describe('useDepsMatch', () => {
it('should return false when dependencies length changes', () => {
const { result, rerender } = renderHook(({ deps }) => useDepsMatch(deps), {
initialProps: { deps: ['dep1', 'dep2'] },
legacyRoot: true,
});
expect(result.current).toBe(true);

@ -22,7 +22,6 @@ describe('useInstance', () => {
it('should create a new instance when dependencies change', () => {
const { result, rerender } = renderHook(({ deps }) => useInstance(factory, deps), {
initialProps: { deps: ['initial-dep'] },
legacyRoot: true,
});
expect(result.current).toEqual({ instance: new MockChatMessages() });
@ -39,7 +38,6 @@ describe('useInstance', () => {
it('should not create a new instance when dependencies do not change', () => {
const { result, rerender } = renderHook(({ deps }) => useInstance(factory, deps), {
initialProps: { deps: ['initial-dep'] },
legacyRoot: true,
});
expect(result.current).toEqual({ instance: new MockChatMessages() });
@ -54,7 +52,7 @@ describe('useInstance', () => {
});
it('should call release function when component unmounts', () => {
const { unmount } = renderHook(() => useInstance(factory, ['initial-dep']), { legacyRoot: true });
const { unmount } = renderHook(() => useInstance(factory, ['initial-dep']));
unmount();

@ -9,7 +9,7 @@ import LoggedOutBanner from '../../../components/deviceManagement/LoggedOutBanne
const LoginPage = ({ defaultRoute, children }: { defaultRoute?: LoginRoutes; children?: ReactNode }): ReactElement => {
const { t } = useTranslation();
const showForcedLogoutBanner = useSession('force_logout') as boolean;
const showForcedLogoutBanner = useSession('force_logout') as boolean | undefined;
const iframeLoginUrl = useIframeLogin();
if (iframeLoginUrl) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save