From a7f74ddb1319ffbd28a5982f7a0540720676c7f0 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Fri, 12 Sep 2025 10:34:49 -0300 Subject: [PATCH 1/3] fix(outbound): upsell contact sales button being displayed for non admins --- .../OutboundMessageUpsellModal.spec.tsx | 55 +++++++++++++------ .../OutboundMessageUpsellModal.tsx | 2 +- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx index ef86069ef5c42..a126d3195e008 100644 --- a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx +++ b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx @@ -27,27 +27,48 @@ describe('OutboundMessageUpsellModal', () => { }); describe('hasModule is false', () => { - it('should render "Learn more" and "Contact sales" buttons', () => { - render(, { wrapper: appRoot.build() }); - expect(screen.getByRole('button', { name: 'Learn more' })).toBeInTheDocument(); - expect(screen.getByRole('button', { name: 'Contact sales' })).toBeInTheDocument(); - }); + describe('user is not admin', () => { + it('should render only "Learn more" button', () => { + render(, { wrapper: appRoot.build() }); + expect(screen.getByRole('button', { name: 'Learn more' })).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Contact sales' })).not.toBeInTheDocument(); + }); - it('should call openExternalLink with docs link when "Learn more" is clicked', async () => { - render(, { wrapper: appRoot.build() }); - await userEvent.click(screen.getByRole('button', { name: 'Learn more' })); - expect(openExternalLink).toHaveBeenCalledWith('https://go.rocket.chat/i/omnichannel-docs'); - }); + it('should render the annotation', () => { + render(, { wrapper: appRoot.build() }); + expect(screen.getByText('Outbound_message_upsell_annotation')).toBeInTheDocument(); + }); - it('should call openExternalLink with sales link when "Contact sales" is clicked', async () => { - render(, { wrapper: appRoot.build() }); - await userEvent.click(screen.getByRole('button', { name: 'Contact sales' })); - expect(openExternalLink).toHaveBeenCalledWith('https://go.rocket.chat/i/contact-sales'); + it('should call openExternalLink with docs link when "Learn more" is clicked', async () => { + render(, { wrapper: appRoot.build() }); + await userEvent.click(screen.getByRole('button', { name: 'Learn more' })); + expect(openExternalLink).toHaveBeenCalledWith('https://go.rocket.chat/i/omnichannel-docs'); + }); }); - it('should not render the annotation', () => { - render(, { wrapper: appRoot.build() }); - expect(screen.queryByText('Outbound_message_upsell_annotation')).not.toBeInTheDocument(); + describe('user is admin', () => { + it('should render "Learn more" and "Contact sales" buttons', () => { + render(, { wrapper: appRoot.build() }); + expect(screen.getByRole('button', { name: 'Learn more' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Contact sales' })).toBeInTheDocument(); + }); + + it('should call openExternalLink with docs link when "Learn more" is clicked', async () => { + render(, { wrapper: appRoot.build() }); + await userEvent.click(screen.getByRole('button', { name: 'Learn more' })); + expect(openExternalLink).toHaveBeenCalledWith('https://go.rocket.chat/i/omnichannel-docs'); + }); + + it('should call openExternalLink with sales link when "Contact sales" is clicked', async () => { + render(, { wrapper: appRoot.build() }); + await userEvent.click(screen.getByRole('button', { name: 'Contact sales' })); + expect(openExternalLink).toHaveBeenCalledWith('https://go.rocket.chat/i/contact-sales'); + }); + + it('should not render the annotation', () => { + render(, { wrapper: appRoot.build() }); + expect(screen.queryByText('Outbound_message_upsell_annotation')).not.toBeInTheDocument(); + }); }); }); diff --git a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx index 94d58fc138b11..16d8949b0b0ea 100644 --- a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx +++ b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx @@ -20,7 +20,7 @@ const OutboundMessageUpsellModal = ({ hasModule, isAdmin, onClose }: OutboundMes const openExternalLink = useExternalLink(); const props = useMemo(() => { - if (!hasModule) { + if (isAdmin && !hasModule) { return { cancelText: t('Learn_more'), onCancel: () => openExternalLink(OMNICHANNEL_DOCS_LINK), From c04fd492e7d89e8428cb45ec21b456f2ee3e6c15 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Fri, 12 Sep 2025 11:40:30 -0300 Subject: [PATCH 2/3] fix: show "Upgrade" button for CE workspaces --- .../OutboundMessageUpsellModal.spec.tsx | 6 ++++++ .../OutboundMessageUpsellModal.tsx | 7 ++++--- .../useOutboundMessageUpsellModal.tsx | 6 +++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx index a126d3195e008..8f312f7454584 100644 --- a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx +++ b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx @@ -53,6 +53,12 @@ describe('OutboundMessageUpsellModal', () => { expect(screen.getByRole('button', { name: 'Contact sales' })).toBeInTheDocument(); }); + it('should render "Upgrade" button when isCommunity is true', () => { + render(, { wrapper: appRoot.build() }); + expect(screen.getByRole('button', { name: 'Upgrade' })).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Contact sales' })).not.toBeInTheDocument(); + }); + it('should call openExternalLink with docs link when "Learn more" is clicked', async () => { render(, { wrapper: appRoot.build() }); await userEvent.click(screen.getByRole('button', { name: 'Learn more' })); diff --git a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx index 16d8949b0b0ea..ae8e2a4aef3d1 100644 --- a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx +++ b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.tsx @@ -8,13 +8,14 @@ import GenericUpsellModal from '../../../../GenericUpsellModal'; type OutboundMessageUpsellModalProps = { hasModule?: boolean; isAdmin?: boolean; + isCommunity?: boolean; onClose: () => void; }; const OMNICHANNEL_DOCS_LINK = 'https://go.rocket.chat/i/omnichannel-docs'; const CONTACT_SALES_LINK = 'https://go.rocket.chat/i/contact-sales'; -const OutboundMessageUpsellModal = ({ hasModule, isAdmin, onClose }: OutboundMessageUpsellModalProps) => { +const OutboundMessageUpsellModal = ({ isCommunity, hasModule, isAdmin, onClose }: OutboundMessageUpsellModalProps) => { const { t } = useTranslation(); const openExternalLink = useExternalLink(); @@ -24,7 +25,7 @@ const OutboundMessageUpsellModal = ({ hasModule, isAdmin, onClose }: OutboundMes return { cancelText: t('Learn_more'), onCancel: () => openExternalLink(OMNICHANNEL_DOCS_LINK), - confirmText: t('Contact_sales'), + confirmText: isCommunity ? t('Upgrade') : t('Contact_sales'), onConfirm: () => openExternalLink(CONTACT_SALES_LINK), onClose, }; @@ -36,7 +37,7 @@ const OutboundMessageUpsellModal = ({ hasModule, isAdmin, onClose }: OutboundMes onCancel: () => openExternalLink(OMNICHANNEL_DOCS_LINK), onClose, }; - }, [hasModule, isAdmin, onClose, openExternalLink, t]); + }, [hasModule, isAdmin, isCommunity, onClose, openExternalLink, t]); return ( { const setModal = useSetModal(); const isAdmin = useRole('admin'); + const license = useLicense(); const hasModule = useHasLicenseModule('outbound-messaging') === true; const close = useEffectEvent(() => setModal(null)); - const open = useEffectEvent(() => setModal()); + const open = useEffectEvent(() => + setModal(), + ); return useMemo(() => ({ open, close }), [open, close]); }; From 29e7de79f6b82da0b338855b9e1d6df936ce6008 Mon Sep 17 00:00:00 2001 From: Aleksander Nicacio da Silva Date: Fri, 12 Sep 2025 14:09:05 -0300 Subject: [PATCH 3/3] test: adjusted hasModule prop --- .../OutboundMessageUpsellModal.spec.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx index 8f312f7454584..8adb3b0ee58b7 100644 --- a/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx +++ b/apps/meteor/client/components/Omnichannel/OutboundMessage/modals/OutboundMessageUpsellModal/OutboundMessageUpsellModal.spec.tsx @@ -29,18 +29,18 @@ describe('OutboundMessageUpsellModal', () => { describe('hasModule is false', () => { describe('user is not admin', () => { it('should render only "Learn more" button', () => { - render(, { wrapper: appRoot.build() }); + render(, { wrapper: appRoot.build() }); expect(screen.getByRole('button', { name: 'Learn more' })).toBeInTheDocument(); expect(screen.queryByRole('button', { name: 'Contact sales' })).not.toBeInTheDocument(); }); it('should render the annotation', () => { - render(, { wrapper: appRoot.build() }); + render(, { wrapper: appRoot.build() }); expect(screen.getByText('Outbound_message_upsell_annotation')).toBeInTheDocument(); }); it('should call openExternalLink with docs link when "Learn more" is clicked', async () => { - render(, { wrapper: appRoot.build() }); + render(, { wrapper: appRoot.build() }); await userEvent.click(screen.getByRole('button', { name: 'Learn more' })); expect(openExternalLink).toHaveBeenCalledWith('https://go.rocket.chat/i/omnichannel-docs'); });