Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 68 additions & 38 deletions src/components/BuyProcess/NewPlanSelection/ContactsPlan/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,14 @@ export const ContactsPlan = InjectAppServices(
appliedPromocode.toLowerCase() === savedPromocode.toLowerCase();
const shouldShowLosePromotionWarning =
!isTailoredPlan && isUpgradePlan && isAppliedPromocodeSameAsSaved;
const shouldShowCurrentPlanWarning =
!isFreeAccount &&
sessionPlan?.plan?.planType === PLAN_TYPE.byContact &&
isEqualPlan &&
!isTailoredPlan;
const shouldUseAdvisorCta = isTailoredPlan || shouldShowDowngradeWarning;
const shouldHideSubscriptionAndPromocode =
isTailoredPlan || shouldShowDowngradeWarning || shouldShowCurrentPlanWarning;
const shouldDisablePaymentFrequency = !isFreeAccount && !keepControlsEnabled;

const stickyDiscountSummary = useMemo(() => {
Expand Down Expand Up @@ -352,37 +359,43 @@ export const ContactsPlan = InjectAppServices(
</option>
</select>
</div>
<div className="dp-new-plan-selection-payment-frequency">
<PaymentFrequency
paymentFrequenciesList={paymentFrequencies}
onSelectPaymentFrequency={handlePaymentFrequencyChange}
currentSubscriptionUser={sessionPlan.plan.planSubscription}
disabled={shouldDisablePaymentFrequency}
/>
</div>
<div className="dp-new-plan-selection-promocode">
<Promocode
allowPromocode={
!selectedPaymentFrequency?.id || selectedPaymentFrequency?.applyPromo
}
selectedMarketingPlan={selectedPlan}
amountDetailsData={amountDetailsData}
selectedPaymentFrequency={selectedPaymentFrequency}
callback={handlePromocodeApplied}
hasPromocodeAppliedItem={Boolean(effectivePromocodeApplied?.promocode)}
isArgentina={sessionPlan.locationCountry === 'ar'}
isFreeAccount={isFreeAccount}
disabledPromocode={false}
handleRemovePromocodeApplied={handleRemovePromocodeApplied}
currentPromocodeApplied={effectivePromocodeApplied}
registerClearPromocodeInput={registerClearPromocodeInput}
defaultPromocodeDismissed={defaultPromocodeDismissed}
handleManualPromocodeIntervention={handleManualPromocodeIntervention}
hideCanNotApplyMessage={
shouldShowLosePromotionWarning || shouldShowDowngradeWarning || isTailoredPlan
}
/>
</div>
{!shouldHideSubscriptionAndPromocode && (
<>
<div className="dp-new-plan-selection-payment-frequency">
<PaymentFrequency
paymentFrequenciesList={paymentFrequencies}
onSelectPaymentFrequency={handlePaymentFrequencyChange}
currentSubscriptionUser={sessionPlan.plan.planSubscription}
disabled={shouldDisablePaymentFrequency}
/>
</div>
<div className="dp-new-plan-selection-promocode">
<Promocode
allowPromocode={
!selectedPaymentFrequency?.id || selectedPaymentFrequency?.applyPromo
}
selectedMarketingPlan={selectedPlan}
amountDetailsData={amountDetailsData}
selectedPaymentFrequency={selectedPaymentFrequency}
callback={handlePromocodeApplied}
hasPromocodeAppliedItem={Boolean(effectivePromocodeApplied?.promocode)}
isArgentina={sessionPlan.locationCountry === 'ar'}
isFreeAccount={isFreeAccount}
disabledPromocode={false}
handleRemovePromocodeApplied={handleRemovePromocodeApplied}
currentPromocodeApplied={effectivePromocodeApplied}
registerClearPromocodeInput={registerClearPromocodeInput}
defaultPromocodeDismissed={defaultPromocodeDismissed}
handleManualPromocodeIntervention={handleManualPromocodeIntervention}
hideCanNotApplyMessage={
shouldShowLosePromotionWarning ||
shouldShowDowngradeWarning ||
isTailoredPlan
}
/>
</div>
</>
)}
{isMoreThan100kSelected && (
<div
className="dp-wrap-message dp-wrap-info dp-new-plan-selection-more-than-message"
Expand All @@ -391,15 +404,18 @@ export const ContactsPlan = InjectAppServices(
<span className="dp-message-icon" />
<div className="dp-content-message">
<p>
<FormattedMessage id="buy_process.new_plan_selection.more_than_100k_info_message" />
<FormattedMessage
id="buy_process.new_plan_selection.more_than_100k_info_message"
values={{ br: <br />, bold: (chunks) => <b>{chunks}</b> }}
/>
</p>
<Link
to="/upgrade-suggestion-form"
className="dp-new-plan-selection-more-than-link"
>
<FormattedMessage id="buy_process.new_plan_selection.more_than_100k_contact_link" />
</Link>
</div>
<Link
to="/upgrade-suggestion-form"
className="dp-new-plan-selection-more-than-link"
>
<FormattedMessage id="buy_process.new_plan_selection.more_than_100k_contact_link" />
</Link>
</div>
)}
{shouldShowLosePromotionWarning && (
Expand Down Expand Up @@ -434,6 +450,19 @@ export const ContactsPlan = InjectAppServices(
</div>
</div>
)}
{shouldShowCurrentPlanWarning && (
<div
className="dp-wrap-message dp-wrap-info dp-new-plan-selection-more-than-message"
data-testid="dp-contacts-current-plan-message"
>
<span className="dp-message-icon" />
<div className="dp-content-message dp-content-full">
<p>
<FormattedMessage id="buy_process.new_plan_selection.contacts_current_plan_warning_message" />
</p>
</div>
</div>
)}
</div>
</div>

Expand Down Expand Up @@ -503,6 +532,7 @@ export const ContactsPlan = InjectAppServices(
<FormattedMessage
id="buy_process.new_plan_selection.savings_text"
values={{
br: <br />,
percentage: selectedDiscountPercentage,
currency: 'US$',
period: _(
Expand Down
20 changes: 19 additions & 1 deletion src/components/BuyProcess/NewPlanSelection/EmailsPlan/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,12 @@ export const EmailsPlan = InjectAppServices(
selectedEmailCapacity < currentSessionEmailCapacity));
const shouldShowHighVolumeMessage = isMoreThan10mSelected;
const shouldUseAdvisorCta = shouldShowDowngradeWarning || shouldShowHighVolumeMessage;
const shouldShowPromocode = !shouldUseAdvisorCta;
const shouldShowCurrentPlanWarning =
!isFreeAccount &&
sessionPlan?.plan?.planType === PLAN_TYPE.byEmail &&
isEqualPlan &&
!shouldUseAdvisorCta;
const shouldShowPromocode = !shouldUseAdvisorCta && !shouldShowCurrentPlanWarning;
const extraEmailPrice = selectedPlan?.extraEmailPrice ?? 0;

const stickyDiscountSummary = useMemo(() => {
Expand Down Expand Up @@ -327,6 +332,19 @@ export const EmailsPlan = InjectAppServices(
</div>
</div>
)}
{shouldShowCurrentPlanWarning && (
<div
className="dp-wrap-message dp-wrap-info dp-new-plan-selection-more-than-message"
data-testid="dp-emails-current-plan-message"
>
<span className="dp-message-icon" />
<div className="dp-content-message dp-content-full">
<p>
<FormattedMessage id="buy_process.new_plan_selection.contacts_current_plan_warning_message" />
</p>
</div>
</div>
)}
</div>
</div>

Expand Down
15 changes: 13 additions & 2 deletions src/components/BuyProcess/NewPlanSelection/index.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ export const NewPlanSelectionStyled = styled.div`
}

.dp-new-plan-selection-price .dp-button {
margin-top: 10px;
width: 250px;
}

Expand Down Expand Up @@ -644,7 +645,7 @@ export const NewPlanSelectionStyled = styled.div`
}

.dp-new-plan-selection-included-features {
margin: 28px auto 30px;
margin: 44px auto 30px;
width: 100%;
}

Expand Down Expand Up @@ -853,7 +854,7 @@ export const NewPlanSelectionStyled = styled.div`
}

.dp-new-plan-selection-addons {
margin: 34px auto 36px;
margin: 34px auto 52px;
}

.dp-new-plan-selection-addons-header {
Expand Down Expand Up @@ -886,6 +887,7 @@ export const NewPlanSelectionStyled = styled.div`
display: flex;
flex: 1 1 auto;
gap: 18px;
padding: 6px 8px 10px;
}

.dp-new-plan-selection-addon-card {
Expand All @@ -894,6 +896,7 @@ export const NewPlanSelectionStyled = styled.div`
flex: 0 0 calc((100% - 36px) / 3);
margin-bottom: 0;
min-height: 100%;
padding: 24px 24px 20px;
}

.dp-new-plan-selection-addon-card .card-title {
Expand Down Expand Up @@ -967,6 +970,14 @@ export const NewPlanSelectionStyled = styled.div`
max-width: none;
}

.dp-new-plan-selection-faq section {
padding-top: 32px;
}

.dp-new-plan-selection-faq .dp-title-faq {
margin-top: 0;
}

.dp-new-plan-selection-faq .dp-accordion li .dp-accordion-thumb {
color: #333;
font-weight: 400;
Expand Down
99 changes: 94 additions & 5 deletions src/components/BuyProcess/NewPlanSelection/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ describe('NewPlanSelection component', () => {
planType: PLAN_TYPE.byContact,
isFreeAccount: false,
planSubscription: 12,
subscribersCount: 900,
promotion: {
idUserTypePlan: 10222,
code: 'PROMOCODE_ANNUAL',
Expand All @@ -625,7 +626,9 @@ describe('NewPlanSelection component', () => {

const promocodeInput = within(getContactsPlanSection()).getByRole('textbox');
expect(promocodeInput).toHaveValue('');
expect(screen.queryByRole('link', { name: /Elegir Plan/i })).not.toBeInTheDocument();
const choosePlanHref = screen.getByRole('link', { name: /Elegir Plan/i }).getAttribute('href');
expect(choosePlanHref).not.toContain('PromoCode=');
expect(choosePlanHref).not.toContain('promo-code=');
});

it('should update selected contacts plan in checkout URL when contacts dropdown changes', async () => {
Expand Down Expand Up @@ -693,6 +696,30 @@ describe('NewPlanSelection component', () => {
).toHaveAttribute('href', '/checkout/premium/monthly-deliveries?selected-plan=30223&buyType=1');
});

it('should show current plan warning and hide promocode when selected byEmail plan equals current one', async () => {
await renderNewPlanSelection(
['/new-plan-selection'],
{
appSessionUser: {
plan: {
idPlan: 30223,
planType: PLAN_TYPE.byEmail,
isFreeAccount: false,
planSubscription: 1,
},
},
},
{ useI18nKeysAsValues: true },
);

expect(getEmailsSelect()).toHaveValue('1');
expect(screen.getByTestId('dp-emails-current-plan-message')).toBeInTheDocument();
expect(
screen.getByText('buy_process.new_plan_selection.contacts_current_plan_warning_message'),
).toBeInTheDocument();
expect(within(getEmailsPlanSection()).queryByRole('textbox')).not.toBeInTheDocument();
});

it('should preselect the next contact plan when subscribers count is lower than current plan capacity and a higher plan exists', async () => {
const contactPlansWithExtraLevel = [
{
Expand Down Expand Up @@ -792,6 +819,34 @@ describe('NewPlanSelection component', () => {
).toBeDisabled();
});

it('should show current plan warning and hide subscription and promocode when selected plan equals current one', async () => {
await renderNewPlanSelection(
['/new-plan-selection'],
{
appSessionUser: {
plan: {
idPlan: 10223,
planType: PLAN_TYPE.byContact,
isFreeAccount: false,
planSubscription: 1,
subscribersCount: 1300,
},
},
},
{ useI18nKeysAsValues: true },
);

expect(getContactsSelect()).toHaveValue('1');
expect(screen.getByTestId('dp-contacts-current-plan-message')).toBeInTheDocument();
expect(
screen.getByText('buy_process.new_plan_selection.contacts_current_plan_warning_message'),
).toBeInTheDocument();
expect(
within(getContactsPlanSection()).queryByRole('button', { name: /Mensual/i }),
).not.toBeInTheDocument();
expect(within(getContactsPlanSection()).queryByRole('textbox')).not.toBeInTheDocument();
});

it('should preselect a higher contact plan when subscribers count is greater than current plan capacity', async () => {
await renderNewPlanSelection(['/new-plan-selection'], {
appSessionUser: {
Expand Down Expand Up @@ -967,6 +1022,10 @@ describe('NewPlanSelection component', () => {
await waitFor(() =>
expect(screen.getByTestId('dp-contacts-downgrade-message')).toBeInTheDocument(),
);
expect(
within(getContactsPlanSection()).queryByRole('button', { name: /Mensual/i }),
).not.toBeInTheDocument();
expect(within(getContactsPlanSection()).queryByRole('textbox')).not.toBeInTheDocument();
expect(
screen.getByText('buy_process.new_plan_selection.contacts_downgrade_warning_message'),
).toBeInTheDocument();
Expand Down Expand Up @@ -1135,10 +1194,11 @@ describe('NewPlanSelection component', () => {
},
});

const annualFrequencyButton = within(getContactsPlanSection()).getByRole('button', {
name: /Anual/i,
});
expect(annualFrequencyButton).toBeDisabled();
expect(screen.getByTestId('dp-contacts-current-plan-message')).toBeInTheDocument();
expect(
within(getContactsPlanSection()).queryByRole('button', { name: /Anual/i }),
).not.toBeInTheDocument();
expect(within(getContactsPlanSection()).queryByRole('textbox')).not.toBeInTheDocument();
});

it('should render credits plan before contacts plan for users with current credit plan', async () => {
Expand Down Expand Up @@ -1195,6 +1255,10 @@ describe('NewPlanSelection component', () => {

const infoBanner = screen.getByTestId('dp-more-than-100k-message');
expect(infoBanner).toBeInTheDocument();
expect(
within(getContactsPlanSection()).queryByRole('button', { name: /Mensual/i }),
).not.toBeInTheDocument();
expect(within(getContactsPlanSection()).queryByRole('textbox')).not.toBeInTheDocument();
expect(within(infoBanner).getByText(/base supera los 100k de Contactos/i)).toBeInTheDocument();
expect(
within(infoBanner).getByRole('link', { name: /cont[aá]ctanos|contact us/i }),
Expand Down Expand Up @@ -1431,4 +1495,29 @@ describe('NewPlanSelection component', () => {
within(getCreditsPlanSection()).getByText(/Incluye 5.000 Creditos extra/i),
).toBeInTheDocument();
});

it('should keep prepayment breakdown in a new line for quarterly, semiannual and annual frequencies', async () => {
await renderNewPlanSelection();

const contactsSection = getContactsPlanSection();
const scenarios = [
{ buttonName: /Trimestral/i, expectedText: '1 pago trimestral de' },
{ buttonName: /Semestral/i, expectedText: '1 pago semestral de' },
{ buttonName: /Anual/i, expectedText: '1 pago anual de' },
];

for (const scenario of scenarios) {
fireEvent.click(within(contactsSection).getByRole('button', { name: scenario.buttonName }));
await settleAsyncState();

await waitFor(() => {
const savingsElement = contactsSection.querySelector(
'.dp-new-plan-selection-price-detail .dp-new-plan-selection-savings',
);
expect(savingsElement).toBeInTheDocument();
expect(savingsElement.textContent.toLowerCase()).toContain(scenario.expectedText);
expect(savingsElement.querySelector('br')).toBeInTheDocument();
});
}
});
});
Loading
Loading