diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx index 29ba07b7a6..9c891ae497 100644 --- a/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx +++ b/services/web/frontend/js/features/project-list/components/notifications/groups/confirm-email.tsx @@ -12,6 +12,7 @@ import { import { ExposedSettings } from '../../../../../../../types/exposed-settings' import { UserEmailData } from '../../../../../../../types/user-email' import { debugConsole } from '@/utils/debugging' +import { Subscription } from '../../../../../../../types/project/dashboard/subscription' const ssoAvailable = ({ samlProviderId, affiliation }: UserEmailData) => { const { hasSamlFeature, hasSamlBeta } = getMeta( @@ -58,6 +59,17 @@ function emailHasLicenceAfterConfirming(emailData: UserEmailData) { return affiliation.institution.commonsAccount } +function isOnFreeOrIndividualPlan() { + const subscription: Subscription | undefined = getMeta( + 'ol-usersBestSubscription' + ) + if (!subscription) { + return false + } + const { type } = subscription + return type === 'free' || type === 'individual' +} + const showConfirmEmail = (userEmail: UserEmailData) => { const { emailConfirmationDisabled } = getMeta( 'ol-ExposedSettings' @@ -86,7 +98,10 @@ function ConfirmEmailNotification({ userEmail }: { userEmail: UserEmailData }) { return null } - if (emailHasLicenceAfterConfirming(userEmail)) { + // Only show the notification if a) a commons license is available and b) the + // user is on a free or individual plan. Users on a group or Commons plan + // already have premium features. + if (emailHasLicenceAfterConfirming(userEmail) && isOnFreeOrIndividualPlan()) { return ( diff --git a/services/web/test/frontend/features/project-list/components/notifications.test.tsx b/services/web/test/frontend/features/project-list/components/notifications.test.tsx index c06dbc826a..17c834d804 100644 --- a/services/web/test/frontend/features/project-list/components/notifications.test.tsx +++ b/services/web/test/frontend/features/project-list/components/notifications.test.tsx @@ -36,6 +36,12 @@ import { Project } from '../../../../../types/project/dashboard/api' import GroupsAndEnterpriseBanner from '../../../../../frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner' import localStorage from '../../../../../frontend/js/infrastructure/local-storage' import * as useLocationModule from '../../../../../frontend/js/shared/hooks/use-location' +import { + commonsSubscription, + freeSubscription, + groupSubscription, + individualSubscription, +} from '../fixtures/user-subscriptions' const renderWithinProjectListProvider = (Component: React.ComponentType) => { render(, { @@ -588,6 +594,10 @@ describe('', function () { emailConfirmationDisabled: false, }) window.metaAttributesCache.set('ol-userEmails', [unconfirmedUserData]) + window.metaAttributesCache.set( + 'ol-usersBestSubscription', + freeSubscription + ) }) afterEach(function () { @@ -634,24 +644,47 @@ describe('', function () { screen.getByText(/something went wrong/i) }) - it('shows notification for commons account', async function () { - window.metaAttributesCache.set('ol-userEmails', [ - unconfirmedCommonsUserData, - ]) + for (const subscription of [freeSubscription, individualSubscription]) { + it(`shows commons notification for commons account when user is on ${subscription.type} plan`, async function () { + window.metaAttributesCache.set('ol-userEmails', [ + unconfirmedCommonsUserData, + ]) + window.metaAttributesCache.set('ol-usersBestSubscription', subscription) - renderWithinProjectListProvider(ConfirmEmail) - await fetchMock.flush(true) + renderWithinProjectListProvider(ConfirmEmail) + await fetchMock.flush(true) - const alert = screen.getByRole('alert') - const email = unconfirmedCommonsUserData.email - const notificationBody = within(alert).getByTestId('notification-body') - expect(notificationBody.textContent).to.contain( - 'You are one step away from accessing Overleaf Professional features' - ) - expect(notificationBody.textContent).to.contain( - `Overleaf has an Overleaf subscription. Click the confirmation link sent to ${email} to upgrade to Overleaf Professional` - ) - }) + const alert = screen.getByRole('alert') + const email = unconfirmedCommonsUserData.email + const notificationBody = within(alert).getByTestId('notification-body') + expect(notificationBody.textContent).to.contain( + 'You are one step away from accessing Overleaf Professional features' + ) + expect(notificationBody.textContent).to.contain( + `Overleaf has an Overleaf subscription. Click the confirmation link sent to ${email} to upgrade to Overleaf Professional` + ) + }) + } + for (const subscription of [groupSubscription, commonsSubscription]) { + it(`shows default notification for commons account when user is on ${subscription.type} plan`, async function () { + window.metaAttributesCache.set('ol-userEmails', [ + unconfirmedCommonsUserData, + ]) + window.metaAttributesCache.set('ol-usersBestSubscription', subscription) + + renderWithinProjectListProvider(ConfirmEmail) + await fetchMock.flush(true) + + const alert = screen.getByRole('alert') + const email = unconfirmedCommonsUserData.email + const notificationBody = within(alert).getByTestId( + 'pro-notification-body' + ) + expect(notificationBody.textContent).to.contain( + `Please confirm your email ${email} by clicking on the link in the confirmation email` + ) + }) + } }) describe('', function () { diff --git a/services/web/test/frontend/features/project-list/fixtures/user-subscriptions.ts b/services/web/test/frontend/features/project-list/fixtures/user-subscriptions.ts new file mode 100644 index 0000000000..8daba525d3 --- /dev/null +++ b/services/web/test/frontend/features/project-list/fixtures/user-subscriptions.ts @@ -0,0 +1,41 @@ +import { + CommonsPlanSubscription, + FreePlanSubscription, + GroupPlanSubscription, + IndividualPlanSubscription, +} from '../../../../../types/project/dashboard/subscription' + +export const freeSubscription: FreePlanSubscription = { + type: 'free', + featuresPageURL: '/features', +} + +export const individualSubscription: IndividualPlanSubscription = { + type: 'individual', + plan: { name: 'professional' }, + featuresPageURL: '/features', + remainingTrialDays: -1, + subscription: { + name: 'professional', + }, +} + +export const commonsSubscription: CommonsPlanSubscription = { + type: 'commons', + plan: { name: 'professional' }, + featuresPageURL: '/features', + subscription: { + name: 'professional', + }, +} + +export const groupSubscription: GroupPlanSubscription = { + type: 'group', + plan: { name: 'professional' }, + featuresPageURL: '/features', + remainingTrialDays: -1, + subscription: { + name: 'professional', + teamName: 'My group', + }, +}