mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #11602 from overleaf/jel-react-personal-subscription-dash-pt-6
[web] Continue migration of change plan UI to React GitOrigin-RevId: 4f6176ac101ba3c57134cf5c86329e205f17ab23
This commit is contained in:
parent
c7d8e4867d
commit
d4057a7bcc
10 changed files with 307 additions and 236 deletions
|
@ -0,0 +1,15 @@
|
|||
export const currencies = <const>{
|
||||
USD: '$',
|
||||
EUR: '€',
|
||||
GBP: '£',
|
||||
SEK: 'kr',
|
||||
CAD: '$',
|
||||
NOK: 'kr',
|
||||
DKK: 'kr',
|
||||
AUD: '$',
|
||||
NZD: '$',
|
||||
CHF: 'Fr',
|
||||
SGD: '$',
|
||||
}
|
||||
|
||||
export type CurrencyCode = keyof typeof currencies
|
|
@ -0,0 +1,56 @@
|
|||
import { SubscriptionPricingState } from '@recurly/recurly-js'
|
||||
import getMeta from '../../../utils/meta'
|
||||
import { currencies, CurrencyCode } from '../data/currency'
|
||||
|
||||
export function formatPriceForDisplayData(price: string, taxRate: number) {
|
||||
const currencyCode: CurrencyCode = getMeta('ol-recommendedCurrency')
|
||||
const currencySymbol = currencies[currencyCode]
|
||||
|
||||
const totalPriceExTax = parseFloat(price)
|
||||
let taxAmount = totalPriceExTax * taxRate
|
||||
if (isNaN(taxAmount)) {
|
||||
taxAmount = 0
|
||||
}
|
||||
const totalWithTax = totalPriceExTax + taxAmount
|
||||
|
||||
return {
|
||||
totalForDisplay: `${currencySymbol}${
|
||||
totalWithTax % 1 !== 0 ? totalWithTax.toFixed(2) : totalWithTax
|
||||
}`,
|
||||
totalAsNumber: totalWithTax,
|
||||
subtotal: `${currencySymbol}${totalPriceExTax.toFixed(2)}`,
|
||||
tax: `${currencySymbol}${taxAmount.toFixed(2)}`,
|
||||
includesTax: taxAmount !== 0,
|
||||
}
|
||||
}
|
||||
|
||||
export function loadDisplayPriceWithTaxPromise(
|
||||
planCode: string,
|
||||
currency: CurrencyCode,
|
||||
taxRate: number
|
||||
) {
|
||||
if (!recurly) return
|
||||
|
||||
return new Promise<ReturnType<typeof formatPriceForDisplayData> | undefined>(
|
||||
resolve => {
|
||||
recurly.Pricing.Subscription()
|
||||
.plan(planCode, { quantity: 1 })
|
||||
.currency(currency)
|
||||
.catch(function (error) {
|
||||
console.error(error)
|
||||
})
|
||||
.done(response => {
|
||||
if (response) {
|
||||
const price =
|
||||
response as unknown as SubscriptionPricingState['price']
|
||||
// type expects response to be {price: {next: ...}}
|
||||
// but the real response is {next: ...}
|
||||
const data = formatPriceForDisplayData(price.next.total, taxRate)
|
||||
resolve(data)
|
||||
} else {
|
||||
resolve(undefined)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
import { expect } from 'chai'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { screen } from '@testing-library/react'
|
||||
import InstitutionMemberships from '../../../../../../frontend/js/features/subscription/components/dashboard/institution-memberships'
|
||||
import { SubscriptionDashboardProvider } from '../../../../../../frontend/js/features/subscription/context/subscription-dashboard-context'
|
||||
import {
|
||||
cleanUpContext,
|
||||
renderWithSubscriptionDashContext,
|
||||
} from '../../helpers/render-with-subscription-dash-context'
|
||||
|
||||
const memberships = [
|
||||
{
|
||||
|
@ -27,25 +30,16 @@ const memberships = [
|
|||
]
|
||||
|
||||
describe('<InstitutionMemberships />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
cleanUpContext()
|
||||
})
|
||||
|
||||
it('renders all insitutions with license', function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-currentInstitutionsWithLicence',
|
||||
memberships
|
||||
)
|
||||
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<InstitutionMemberships />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<InstitutionMemberships />, {
|
||||
metaTags: [
|
||||
{ name: 'ol-currentInstitutionsWithLicence', value: memberships },
|
||||
],
|
||||
})
|
||||
|
||||
const elements = screen.getAllByText('You are on our', {
|
||||
exact: false,
|
||||
|
@ -60,27 +54,18 @@ describe('<InstitutionMemberships />', function () {
|
|||
})
|
||||
|
||||
it('renders error message when failed to check commons licenses', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<InstitutionMemberships />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<InstitutionMemberships />)
|
||||
screen.getByText(
|
||||
'Sorry, something went wrong. Subscription information related to institutional affiliations may not be displayed. Please try again later.'
|
||||
)
|
||||
})
|
||||
|
||||
it('renders the "Get the most out of your" subscription text when a user has a subscription', function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-currentInstitutionsWithLicence',
|
||||
memberships
|
||||
)
|
||||
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<InstitutionMemberships />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<InstitutionMemberships />, {
|
||||
metaTags: [
|
||||
{ name: 'ol-currentInstitutionsWithLicence', value: memberships },
|
||||
],
|
||||
})
|
||||
screen.getByText('Get the most out of your', {
|
||||
exact: false,
|
||||
})
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import { expect } from 'chai'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { screen } from '@testing-library/react'
|
||||
import {
|
||||
groupActiveSubscription,
|
||||
groupActiveSubscriptionWithPendingLicenseChange,
|
||||
} from '../../fixtures/subscriptions'
|
||||
import ManagedGroupSubscriptions from '../../../../../../frontend/js/features/subscription/components/dashboard/managed-group-subscriptions'
|
||||
import { ManagedGroupSubscription } from '../../../../../../types/subscription/dashboard/subscription'
|
||||
import { SubscriptionDashboardProvider } from '../../../../../../frontend/js/features/subscription/context/subscription-dashboard-context'
|
||||
import {
|
||||
cleanUpContext,
|
||||
renderWithSubscriptionDashContext,
|
||||
} from '../../helpers/render-with-subscription-dash-context'
|
||||
|
||||
const managedGroupSubscriptions: ManagedGroupSubscription[] = [
|
||||
{
|
||||
|
@ -30,24 +33,19 @@ const managedGroupSubscriptions: ManagedGroupSubscription[] = [
|
|||
]
|
||||
|
||||
describe('<ManagedGroupSubscriptions />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
cleanUpContext()
|
||||
})
|
||||
|
||||
it('renders all managed group subscriptions', function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-managedGroupSubscriptions',
|
||||
managedGroupSubscriptions
|
||||
)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ManagedGroupSubscriptions />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />, {
|
||||
metaTags: [
|
||||
{
|
||||
name: 'ol-managedGroupSubscriptions',
|
||||
value: managedGroupSubscriptions,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const elements = screen.getAllByText('You are a', {
|
||||
exact: false,
|
||||
|
@ -91,11 +89,7 @@ describe('<ManagedGroupSubscriptions />', function () {
|
|||
})
|
||||
|
||||
it('renders nothing when there are no group memberships', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ManagedGroupSubscriptions />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<ManagedGroupSubscriptions />)
|
||||
const elements = screen.queryAllByText('You are a', {
|
||||
exact: false,
|
||||
})
|
||||
|
|
|
@ -1,32 +1,25 @@
|
|||
import { expect } from 'chai'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { screen } from '@testing-library/react'
|
||||
import PersonalSubscription from '../../../../../../frontend/js/features/subscription/components/dashboard/personal-subscription'
|
||||
import { SubscriptionDashboardProvider } from '../../../../../../frontend/js/features/subscription/context/subscription-dashboard-context'
|
||||
import {
|
||||
annualActiveSubscription,
|
||||
canceledSubscription,
|
||||
pastDueExpiredSubscription,
|
||||
} from '../../fixtures/subscriptions'
|
||||
import {
|
||||
cleanUpContext,
|
||||
renderWithSubscriptionDashContext,
|
||||
} from '../../helpers/render-with-subscription-dash-context'
|
||||
|
||||
describe('<PersonalSubscription />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
// @ts-ignore
|
||||
window.recurly = {}
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
// @ts-ignore
|
||||
delete window.recurly
|
||||
cleanUpContext()
|
||||
})
|
||||
|
||||
describe('no subscription', function () {
|
||||
it('returns empty container', function () {
|
||||
const { container } = render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
const { container } = renderWithSubscriptionDashContext(
|
||||
<PersonalSubscription />
|
||||
)
|
||||
expect(container.firstChild).to.be.null
|
||||
})
|
||||
|
@ -34,26 +27,19 @@ describe('<PersonalSubscription />', function () {
|
|||
|
||||
describe('subscription states ', function () {
|
||||
it('renders the active dash', function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-subscription',
|
||||
annualActiveSubscription
|
||||
)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<PersonalSubscription />, {
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: annualActiveSubscription },
|
||||
],
|
||||
})
|
||||
|
||||
screen.getByText('You are currently subscribed to the', { exact: false })
|
||||
})
|
||||
|
||||
it('renders the canceled dash', function () {
|
||||
window.metaAttributesCache.set('ol-subscription', canceledSubscription)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<PersonalSubscription />, {
|
||||
metaTags: [{ name: 'ol-subscription', value: canceledSubscription }],
|
||||
})
|
||||
screen.getByText(
|
||||
'Your subscription has been canceled and will terminate on',
|
||||
{ exact: false }
|
||||
|
@ -74,15 +60,11 @@ describe('<PersonalSubscription />', function () {
|
|||
})
|
||||
|
||||
it('renders the expired dash', function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-subscription',
|
||||
pastDueExpiredSubscription
|
||||
)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<PersonalSubscription />, {
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: pastDueExpiredSubscription },
|
||||
],
|
||||
})
|
||||
screen.getByText('Your subscription has expired.')
|
||||
})
|
||||
|
||||
|
@ -92,12 +74,9 @@ describe('<PersonalSubscription />', function () {
|
|||
JSON.parse(JSON.stringify(annualActiveSubscription))
|
||||
)
|
||||
withStateDeleted.recurly.state = undefined
|
||||
window.metaAttributesCache.set('ol-subscription', withStateDeleted)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<PersonalSubscription />, {
|
||||
metaTags: [{ name: 'ol-subscription', value: withStateDeleted }],
|
||||
})
|
||||
screen.getByText(
|
||||
'There is a problem with your subscription. Please contact us for more information.'
|
||||
)
|
||||
|
@ -106,15 +85,11 @@ describe('<PersonalSubscription />', function () {
|
|||
|
||||
describe('past due subscription', function () {
|
||||
it('renders error alert', function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-subscription',
|
||||
pastDueExpiredSubscription
|
||||
)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<PersonalSubscription />, {
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: pastDueExpiredSubscription },
|
||||
],
|
||||
})
|
||||
screen.getByRole('alert')
|
||||
screen.getByText(
|
||||
'Your account currently has a past due invoice. You will not be able to change your plan until this is resolved.',
|
||||
|
@ -132,17 +107,12 @@ describe('<PersonalSubscription />', function () {
|
|||
'Sorry, there was an error talking to our payment provider. Please try again in a few moments. If you are using any ad or script blocking extensions in your browser, you may need to temporarily disable them.'
|
||||
|
||||
it('shows an alert and hides "Change plan" option when Recurly did not load', function () {
|
||||
// @ts-ignore
|
||||
delete window.recurly
|
||||
window.metaAttributesCache.set(
|
||||
'ol-subscription',
|
||||
annualActiveSubscription
|
||||
)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<PersonalSubscription />, {
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: annualActiveSubscription },
|
||||
],
|
||||
recurlyNotLoaded: true,
|
||||
})
|
||||
|
||||
screen.getByRole('alert')
|
||||
screen.getByText(recurlyFailedToLoadText)
|
||||
|
@ -151,15 +121,11 @@ describe('<PersonalSubscription />', function () {
|
|||
})
|
||||
|
||||
it('should not show an alert and should show "Change plan" option when Recurly did load', function () {
|
||||
window.metaAttributesCache.set(
|
||||
'ol-subscription',
|
||||
annualActiveSubscription
|
||||
)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<PersonalSubscription />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<PersonalSubscription />, {
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: annualActiveSubscription },
|
||||
],
|
||||
})
|
||||
|
||||
expect(screen.queryByRole('alert')).to.be.null
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { expect } from 'chai'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import * as eventTracking from '../../../../../../../../frontend/js/infrastructure/event-tracking'
|
||||
import { ActiveSubscription } from '../../../../../../../../frontend/js/features/subscription/components/dashboard/states/active/active'
|
||||
import { SubscriptionDashboardProvider } from '../../../../../../../../frontend/js/features/subscription/context/subscription-dashboard-context'
|
||||
import { Subscription } from '../../../../../../../../types/subscription/dashboard/subscription'
|
||||
import {
|
||||
annualActiveSubscription,
|
||||
|
@ -13,22 +12,20 @@ import {
|
|||
} from '../../../../fixtures/subscriptions'
|
||||
import sinon from 'sinon'
|
||||
import { plans } from '../../../../fixtures/plans'
|
||||
import {
|
||||
cleanUpContext,
|
||||
renderWithSubscriptionDashContext,
|
||||
} from '../../../../helpers/render-with-subscription-dash-context'
|
||||
|
||||
describe('<ActiveSubscription />', function () {
|
||||
let sendMBSpy: sinon.SinonSpy
|
||||
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
window.metaAttributesCache.set('ol-plans', plans)
|
||||
// @ts-ignore
|
||||
window.recurly = {}
|
||||
sendMBSpy = sinon.spy(eventTracking, 'sendMB')
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
// @ts-ignore
|
||||
delete window.recurly
|
||||
cleanUpContext()
|
||||
sendMBSpy.restore()
|
||||
})
|
||||
|
||||
|
@ -64,21 +61,26 @@ describe('<ActiveSubscription />', function () {
|
|||
screen.getByRole('link', { name: 'View Your Invoices' })
|
||||
}
|
||||
|
||||
it('renders the dash annual active subscription', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
function renderActiveSubscription(subscription: Subscription) {
|
||||
const renderOptions = {
|
||||
metaTags: [
|
||||
{ name: 'ol-plans', value: plans },
|
||||
{ name: 'ol-subscription', value: subscription },
|
||||
],
|
||||
}
|
||||
renderWithSubscriptionDashContext(
|
||||
<ActiveSubscription subscription={subscription} />,
|
||||
renderOptions
|
||||
)
|
||||
}
|
||||
|
||||
it('renders the dash annual active subscription', function () {
|
||||
renderActiveSubscription(annualActiveSubscription)
|
||||
expectedInActiveSubscription(annualActiveSubscription)
|
||||
})
|
||||
|
||||
it('shows change plan UI when button clicked', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(annualActiveSubscription)
|
||||
|
||||
const button = screen.getByRole('button', { name: 'Change plan' })
|
||||
fireEvent.click(button)
|
||||
|
@ -93,11 +95,7 @@ describe('<ActiveSubscription />', function () {
|
|||
})
|
||||
|
||||
it('notes when user is changing plan at end of current plan term', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={pendingSubscriptionChange} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(pendingSubscriptionChange)
|
||||
|
||||
expectedInActiveSubscription(pendingSubscriptionChange)
|
||||
|
||||
|
@ -126,24 +124,14 @@ describe('<ActiveSubscription />', function () {
|
|||
|
||||
activePastDueSubscription.recurly.account.has_past_due_invoice._ = 'true'
|
||||
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={activePastDueSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(activePastDueSubscription)
|
||||
|
||||
const changePlan = screen.queryByRole('button', { name: 'Change plan' })
|
||||
expect(changePlan).to.be.null
|
||||
})
|
||||
|
||||
it('shows the pending license change message when plan change is pending', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription
|
||||
subscription={groupActiveSubscriptionWithPendingLicenseChange}
|
||||
/>
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(groupActiveSubscriptionWithPendingLicenseChange)
|
||||
|
||||
screen.getByText('Your subscription is changing to include', {
|
||||
exact: false,
|
||||
|
@ -175,11 +163,7 @@ describe('<ActiveSubscription />', function () {
|
|||
subscription.recurly.totalLicenses +
|
||||
subscription.recurly.additionalLicenses
|
||||
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={subscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(subscription)
|
||||
|
||||
screen.getByText('Your subscription includes', {
|
||||
exact: false,
|
||||
|
@ -193,11 +177,7 @@ describe('<ActiveSubscription />', function () {
|
|||
})
|
||||
|
||||
it('shows when trial ends and first payment collected', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={trialSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(trialSubscription)
|
||||
screen.getByText('You’re on a free trial which ends on', { exact: false })
|
||||
|
||||
const endDate = screen.getAllByText(
|
||||
|
@ -207,11 +187,7 @@ describe('<ActiveSubscription />', function () {
|
|||
})
|
||||
|
||||
it('shows cancel UI and sends event', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(annualActiveSubscription)
|
||||
// before button clicked
|
||||
screen.getByText(
|
||||
'Your subscription will remain active until the end of your billing period',
|
||||
|
@ -238,22 +214,14 @@ describe('<ActiveSubscription />', function () {
|
|||
|
||||
describe('group plans', function () {
|
||||
it('does not show "Change plan" option for group plans', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={groupActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(groupActiveSubscription)
|
||||
|
||||
const changePlan = screen.queryByRole('button', { name: 'Change plan' })
|
||||
expect(changePlan).to.be.null
|
||||
})
|
||||
|
||||
it('shows contact support message for group plan change requests', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={groupActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderActiveSubscription(groupActiveSubscription)
|
||||
screen.getByRole('link', { name: 'contact support' })
|
||||
screen.getByText('if you wish to change your group subscription.', {
|
||||
exact: false,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { expect } from 'chai'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { SubscriptionDashboardProvider } from '../../../../../../../../../frontend/js/features/subscription/context/subscription-dashboard-context'
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import { ChangePlan } from '../../../../../../../../../frontend/js/features/subscription/components/dashboard/states/active/change-plan/change-plan'
|
||||
import { plans } from '../../../../../fixtures/plans'
|
||||
import {
|
||||
|
@ -8,38 +7,38 @@ import {
|
|||
pendingSubscriptionChange,
|
||||
} from '../../../../../fixtures/subscriptions'
|
||||
import { ActiveSubscription } from '../../../../../../../../../frontend/js/features/subscription/components/dashboard/states/active/active'
|
||||
import {
|
||||
cleanUpContext,
|
||||
renderWithSubscriptionDashContext,
|
||||
} from '../../../../../helpers/render-with-subscription-dash-context'
|
||||
|
||||
describe('<ChangePlan />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
window.metaAttributesCache.set('ol-plans', plans)
|
||||
// @ts-ignore
|
||||
window.recurly = {}
|
||||
})
|
||||
const plansMetaTag = { name: 'ol-plans', value: plans }
|
||||
const renderOptions = { metaTags: [plansMetaTag] }
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
// @ts-ignore
|
||||
delete window.recurly
|
||||
cleanUpContext()
|
||||
})
|
||||
|
||||
it('does not render the UI when showChangePersonalPlan is false', function () {
|
||||
window.metaAttributesCache.delete('ol-plans')
|
||||
const { container } = render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ChangePlan />
|
||||
</SubscriptionDashboardProvider>
|
||||
const { container } = renderWithSubscriptionDashContext(
|
||||
<ChangePlan />,
|
||||
renderOptions
|
||||
)
|
||||
|
||||
expect(container.firstChild).to.be.null
|
||||
})
|
||||
|
||||
it('renders the individual plans table', function () {
|
||||
window.metaAttributesCache.set('ol-subscription', annualActiveSubscription)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
renderWithSubscriptionDashContext(
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />,
|
||||
{
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: annualActiveSubscription },
|
||||
plansMetaTag,
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
const button = screen.getByRole('button', { name: 'Change plan' })
|
||||
|
@ -59,11 +58,14 @@ describe('<ChangePlan />', function () {
|
|||
})
|
||||
|
||||
it('renders the change to group plan UI', function () {
|
||||
window.metaAttributesCache.set('ol-subscription', annualActiveSubscription)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
renderWithSubscriptionDashContext(
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />,
|
||||
{
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: annualActiveSubscription },
|
||||
plansMetaTag,
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
const button = screen.getByRole('button', { name: 'Change plan' })
|
||||
|
@ -73,11 +75,14 @@ describe('<ChangePlan />', function () {
|
|||
})
|
||||
|
||||
it('renders "Your new plan" and "Keep current plan" when there is a pending plan change', function () {
|
||||
window.metaAttributesCache.set('ol-subscription', pendingSubscriptionChange)
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={pendingSubscriptionChange} />
|
||||
</SubscriptionDashboardProvider>
|
||||
renderWithSubscriptionDashContext(
|
||||
<ActiveSubscription subscription={pendingSubscriptionChange} />,
|
||||
{
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: pendingSubscriptionChange },
|
||||
plansMetaTag,
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
const button = screen.getByRole('button', { name: 'Change plan' })
|
||||
|
@ -88,12 +93,14 @@ describe('<ChangePlan />', function () {
|
|||
})
|
||||
|
||||
it('does not render when Recurly did not load', function () {
|
||||
// @ts-ignore
|
||||
delete window.recurly
|
||||
const { container } = render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />
|
||||
</SubscriptionDashboardProvider>
|
||||
const { container } = renderWithSubscriptionDashContext(
|
||||
<ActiveSubscription subscription={annualActiveSubscription} />,
|
||||
{
|
||||
metaTags: [
|
||||
{ name: 'ol-subscription', value: annualActiveSubscription },
|
||||
plansMetaTag,
|
||||
],
|
||||
}
|
||||
)
|
||||
expect(container).not.to.be.null
|
||||
})
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
import { expect } from 'chai'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { screen } from '@testing-library/react'
|
||||
import SubscriptionDashboard from '../../../../../../frontend/js/features/subscription/components/dashboard/subscription-dashboard'
|
||||
import { SubscriptionDashboardProvider } from '../../../../../../frontend/js/features/subscription/context/subscription-dashboard-context'
|
||||
import {
|
||||
cleanUpContext,
|
||||
renderWithSubscriptionDashContext,
|
||||
} from '../../helpers/render-with-subscription-dash-context'
|
||||
|
||||
describe('<SubscriptionDashboard />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
cleanUpContext()
|
||||
})
|
||||
|
||||
describe('Free Plan', function () {
|
||||
it('does not render the "Get the most out of your" subscription text', function () {
|
||||
render(
|
||||
<SubscriptionDashboardProvider>
|
||||
<SubscriptionDashboard />
|
||||
</SubscriptionDashboardProvider>
|
||||
)
|
||||
renderWithSubscriptionDashContext(<SubscriptionDashboard />)
|
||||
const text = screen.queryByText('Get the most out of your', {
|
||||
exact: false,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import { render } from '@testing-library/react'
|
||||
import { SubscriptionDashboardProvider } from '../../../../../frontend/js/features/subscription/context/subscription-dashboard-context'
|
||||
|
||||
export function renderWithSubscriptionDashContext(
|
||||
component: React.ReactElement,
|
||||
options?: {
|
||||
metaTags?: { name: string; value: string | object | Array<object> }[]
|
||||
recurlyNotLoaded?: boolean
|
||||
}
|
||||
) {
|
||||
const SubscriptionDashboardProviderWrapper = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) => (
|
||||
<SubscriptionDashboardProvider>{children}</SubscriptionDashboardProvider>
|
||||
)
|
||||
|
||||
window.metaAttributesCache = new Map()
|
||||
options?.metaTags?.forEach(tag =>
|
||||
window.metaAttributesCache.set(tag.name, tag.value)
|
||||
)
|
||||
|
||||
if (!options?.recurlyNotLoaded) {
|
||||
// @ts-ignore
|
||||
window.recurly = {}
|
||||
}
|
||||
|
||||
return render(component, {
|
||||
wrapper: SubscriptionDashboardProviderWrapper,
|
||||
})
|
||||
}
|
||||
|
||||
export function cleanUpContext() {
|
||||
// @ts-ignore
|
||||
delete window.recurly
|
||||
window.metaAttributesCache = new Map()
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
import { expect } from 'chai'
|
||||
import { formatPriceForDisplayData } from '../../../../../frontend/js/features/subscription/util/recurly-pricing'
|
||||
|
||||
describe('formatPriceForDisplayData', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
it('should handle no tax rate', function () {
|
||||
window.metaAttributesCache.set('ol-recommendedCurrency', 'USD')
|
||||
const data = formatPriceForDisplayData('1000', 0)
|
||||
expect(data).to.deep.equal({
|
||||
totalForDisplay: '$1000',
|
||||
totalAsNumber: 1000,
|
||||
subtotal: '$1000.00',
|
||||
tax: '$0.00',
|
||||
includesTax: false,
|
||||
})
|
||||
window.metaAttributesCache = new Map()
|
||||
})
|
||||
|
||||
it('should handle a tax rate', function () {
|
||||
window.metaAttributesCache.set('ol-recommendedCurrency', 'EUR')
|
||||
const data = formatPriceForDisplayData('380', 0.2)
|
||||
expect(data).to.deep.equal({
|
||||
totalForDisplay: '€456',
|
||||
totalAsNumber: 456,
|
||||
subtotal: '€380.00',
|
||||
tax: '€76.00',
|
||||
includesTax: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle total with cents', function () {
|
||||
window.metaAttributesCache.set('ol-recommendedCurrency', 'EUR')
|
||||
const data = formatPriceForDisplayData('8', 0.2)
|
||||
expect(data).to.deep.equal({
|
||||
totalForDisplay: '€9.60',
|
||||
totalAsNumber: 9.6,
|
||||
subtotal: '€8.00',
|
||||
tax: '€1.60',
|
||||
includesTax: true,
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue