Skip to content

Commit

Permalink
feat: refactor and rename paidplancard (#2367)
Browse files Browse the repository at this point in the history
* feat: refactor and rename paidplancard

* quick detail
  • Loading branch information
adrian-codecov authored Nov 1, 2023
1 parent 18c50f3 commit 2fc2003
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {

import EnterprisePlanCard from './EnterprisePlanCard'
import FreePlanCard from './FreePlanCard'
import ProPlanCard from './ProPlanCard'
import PaidPlanCard from './PaidPlanCard'

function CurrentPlanCard() {
const { provider, owner } = useParams()
Expand All @@ -30,7 +30,7 @@ function CurrentPlanCard() {
return <EnterprisePlanCard plan={plan} />
}

return <ProPlanCard plan={plan} scheduledPhase={scheduledPhase} />
return <PaidPlanCard />
}

export default CurrentPlanCard
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MemoryRouter, Route } from 'react-router-dom'
import CurrentPlanCard from './CurrentPlanCard'

jest.mock('./FreePlanCard', () => () => 'Free plan card')
jest.mock('./ProPlanCard', () => () => 'Pro plan card')
jest.mock('./PaidPlanCard', () => () => 'Paid plan card')
jest.mock('./EnterprisePlanCard', () => () => 'Enterprise plan card')

const proPlanDetails = {
Expand Down Expand Up @@ -122,8 +122,8 @@ describe('CurrentPlanCard', () => {
wrapper,
})

const proPlanCard = await screen.findByText(/Pro plan card/)
expect(proPlanCard).toBeInTheDocument()
const PaidPlanCard = await screen.findByText(/Paid plan card/)
expect(PaidPlanCard).toBeInTheDocument()
})
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
import PropType from 'prop-types'
import { useParams } from 'react-router-dom'

import { planPropType } from 'services/account'
import { useAccountDetails, usePlanData } from 'services/account'
import BenefitList from 'shared/plan/BenefitList'
import ScheduledPlanDetails from 'shared/plan/ScheduledPlanDetails'

import ActionsBilling from '../shared/ActionsBilling/ActionsBilling'
import PlanPricing from '../shared/PlanPricing'

function ProPlanCard({ plan, scheduledPhase }) {
const seats = plan?.quantity
function PaidPlanCard() {
const { provider, owner } = useParams()
const { data: accountDetails } = useAccountDetails({ provider, owner })
const { data: planData } = usePlanData({
provider,
owner,
})
const scheduledPhase = accountDetails?.scheduleDetail?.scheduledPhase
const plan = planData?.plan
const marketingName = plan?.marketingName
const benefits = plan?.benefits
const value = plan?.value
const baseUnitPrice = plan?.baseUnitPrice
const seats = plan?.planUserCount

return (
<div className="flex flex-col border">
<div className="p-4">
<h2 className="font-semibold">{plan.marketingName} plan</h2>
<h2 className="font-semibold">{marketingName} plan</h2>
<span className="text-gray-500">Current Plan</span>
</div>
<hr />
<div className="grid gap-4 p-4 sm:grid-cols-2 sm:gap-0">
<div className="flex flex-col gap-2">
<p className="text-xs font-semibold">Includes</p>
<BenefitList
benefits={plan.benefits}
benefits={benefits}
iconName="check"
iconColor="text-ds-pink-quinary"
/>
</div>
<div className="flex flex-col gap-3 border-t pt-2 sm:border-0 sm:p-0">
<p className="text-xs font-semibold">Pricing</p>
<div>
<PlanPricing
value={plan.value}
baseUnitPrice={plan.baseUnitPrice}
/>
<PlanPricing value={value} baseUnitPrice={baseUnitPrice} />
{seats && (
<p className="text-xs text-ds-gray-senary">
plan has {seats} seats
Expand All @@ -49,13 +58,4 @@ function ProPlanCard({ plan, scheduledPhase }) {
)
}

ProPlanCard.propTypes = {
plan: planPropType,
scheduledPhase: PropType.shape({
quantity: PropType.number.isRequired,
plan: PropType.string.isRequired,
startDate: PropType.number.isRequired,
}),
}

export default ProPlanCard
export default PaidPlanCard
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, screen } from '@testing-library/react'
import { graphql, rest } from 'msw'
import { setupServer } from 'msw/node'
import { MemoryRouter, Route } from 'react-router-dom'

import { TrialStatuses } from 'services/account'

import PaidPlanCard from './PaidPlanCard'

jest.mock(
'../shared/ActionsBilling/ActionsBilling',
() => () => 'Actions Billing'
)
jest.mock('../shared/PlanPricing', () => () => 'Plan Pricing')
jest.mock('shared/plan/BenefitList', () => () => 'BenefitsList')
jest.mock(
'shared/plan/ScheduledPlanDetails',
() => () => 'Scheduled Plan Details'
)

const mockProPlan = {
marketingName: 'Pro',
value: 'users-pr-inappm',
billingRate: 'monthly',
baseUnitPrice: 0,
benefits: ['Unlimited public repositories', 'Unlimited private repositories'],
planUserCount: 5,
monthlyUploadLimit: null,
trialStatus: TrialStatuses.CANNOT_TRIAL,
trialStartDate: '',
trialEndDate: '',
trialTotalDays: 0,
pretrialUsersCount: 0,
}

const mockTeamPlan = {
marketingName: 'Team',
value: 'users-teamm',
billingRate: 'monthly',
baseUnitPrice: 123,
benefits: ['Team benefits', 'Unlimited private repositories'],
planUserCount: 8,
monthlyUploadLimit: null,
trialStatus: TrialStatuses.CANNOT_TRIAL,
trialStartDate: '',
trialEndDate: '',
trialTotalDays: 0,
pretrialUsersCount: 0,
}

const mockScheduleDetail = {
id: 'test_sub_sched_123',
scheduled_phase: {
plan: 'annually',
quantity: 5,
start_date: 1724258944,
},
}

const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
})

const wrapper = ({ children }) => (
<QueryClientProvider client={queryClient}>
<MemoryRouter initialEntries={['/plan/bb/critical-role']}>
<Route path="/plan/:provider/:owner">{children}</Route>
</MemoryRouter>
</QueryClientProvider>
)

const server = setupServer()

beforeAll(() => server.listen())
afterEach(() => {
queryClient.clear()
server.resetHandlers()
})
afterAll(() => server.close())

describe('PaidPlanCard', () => {
function setup(
{ hasScheduledDetails = false, plan = mockProPlan } = {
hasScheduledDetails: false,
plan: mockProPlan,
}
) {
server.use(
rest.get(
'/internal/bb/critical-role/account-details/',
(req, res, ctx) => {
if (hasScheduledDetails) {
return res(
ctx.status(200),
ctx.json({ scheduleDetail: mockScheduleDetail })
)
} else {
return res(ctx.status(200), ctx.json({}))
}
}
),
graphql.query('GetPlanData', (req, res, ctx) =>
res(
ctx.status(200),
ctx.data({
owner: {
plan,
},
})
)
)
)
}

describe('When rendered for a pro plan', () => {
beforeEach(() => {
setup({ plan: mockProPlan })
})

it('renders the plan marketing name', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const planValue = await screen.findByText(/Pro plan/)
expect(planValue).toBeInTheDocument()
})

it('renders the benefits', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const benefitsList = await screen.findByText(/BenefitsList/)
expect(benefitsList).toBeInTheDocument()
})

it('renders seats number', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const seats = await screen.findByText(/plan has 5 seats/)
expect(seats).toBeInTheDocument()
})

it('renders the plan pricing', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const planPricing = await screen.findByText(/Plan Pricing/)
expect(planPricing).toBeInTheDocument()
})

it('renders actions billing button', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const actionsBilling = await screen.findByText(/Actions Billing/)
expect(actionsBilling).toBeInTheDocument()
})
})

describe('When rendered for a team plan', () => {
beforeEach(() => {
setup({ plan: mockTeamPlan })
})

it('renders the plan marketing name', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const planValue = await screen.findByText(/Team plan/)
expect(planValue).toBeInTheDocument()
})

it('renders the benefits', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const benefitsList = await screen.findByText(/BenefitsList/)
expect(benefitsList).toBeInTheDocument()
})

it('renders seats number', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const seats = await screen.findByText(/plan has 8 seats/)
expect(seats).toBeInTheDocument()
})

it('renders the plan pricing', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const planPricing = await screen.findByText(/Plan Pricing/)
expect(planPricing).toBeInTheDocument()
})

it('renders actions billing button', async () => {
render(<PaidPlanCard />, {
wrapper,
})

const actionsBilling = await screen.findByText(/Actions Billing/)
expect(actionsBilling).toBeInTheDocument()
})
})

describe('When rendered with scheduled details', () => {
it('renders the scheduled details', async () => {
setup({ hasScheduledDetails: true })
render(<PaidPlanCard />, {
wrapper,
})

const scheduledPlanDetails = await screen.findByText(
/Scheduled Plan Details/
)
expect(scheduledPlanDetails).toBeInTheDocument()
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './PaidPlanCard'
Loading

0 comments on commit 2fc2003

Please sign in to comment.