From 2fc2003069e57d3bbf1f3a76f00bcb9c9c146017 Mon Sep 17 00:00:00 2001 From: Adrian Date: Wed, 1 Nov 2023 12:17:28 -0700 Subject: [PATCH] feat: refactor and rename paidplancard (#2367) * feat: refactor and rename paidplancard * quick detail --- .../CurrentPlanCard/CurrentPlanCard.jsx | 4 +- .../CurrentPlanCard/CurrentPlanCard.spec.jsx | 6 +- .../PaidPlanCard.jsx} | 40 +-- .../PaidPlanCard/PaidPlanCard.spec.jsx | 231 ++++++++++++++++++ .../CurrentPlanCard/PaidPlanCard/index.js | 1 + .../ProPlanCard/ProPlanCard.spec.jsx | 83 ------- .../CurrentPlanCard/ProPlanCard/index.js | 1 - 7 files changed, 257 insertions(+), 109 deletions(-) rename src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/{ProPlanCard/ProPlanCard.jsx => PaidPlanCard/PaidPlanCard.jsx} (60%) create mode 100644 src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.spec.jsx create mode 100644 src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/index.js delete mode 100644 src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/ProPlanCard.spec.jsx delete mode 100644 src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/index.js diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx index 7b4b86f92c..2ef025e1ca 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx @@ -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() @@ -30,7 +30,7 @@ function CurrentPlanCard() { return } - return + return } export default CurrentPlanCard diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.spec.jsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.spec.jsx index e70f5d5156..2523d6bce2 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.spec.jsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.spec.jsx @@ -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 = { @@ -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() }) }) diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/ProPlanCard.jsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx similarity index 60% rename from src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/ProPlanCard.jsx rename to src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx index b68a3a434f..74c68641ce 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/ProPlanCard.jsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx @@ -1,19 +1,31 @@ -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 (
-

{plan.marketingName} plan

+

{marketingName} plan

Current Plan

@@ -21,7 +33,7 @@ function ProPlanCard({ plan, scheduledPhase }) {

Includes

@@ -29,10 +41,7 @@ function ProPlanCard({ plan, scheduledPhase }) {

Pricing

- + {seats && (

plan has {seats} seats @@ -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 diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.spec.jsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.spec.jsx new file mode 100644 index 0000000000..2bcb9c7e95 --- /dev/null +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.spec.jsx @@ -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 }) => ( + + + {children} + + +) + +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(, { + wrapper, + }) + + const planValue = await screen.findByText(/Pro plan/) + expect(planValue).toBeInTheDocument() + }) + + it('renders the benefits', async () => { + render(, { + wrapper, + }) + + const benefitsList = await screen.findByText(/BenefitsList/) + expect(benefitsList).toBeInTheDocument() + }) + + it('renders seats number', async () => { + render(, { + wrapper, + }) + + const seats = await screen.findByText(/plan has 5 seats/) + expect(seats).toBeInTheDocument() + }) + + it('renders the plan pricing', async () => { + render(, { + wrapper, + }) + + const planPricing = await screen.findByText(/Plan Pricing/) + expect(planPricing).toBeInTheDocument() + }) + + it('renders actions billing button', async () => { + render(, { + 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(, { + wrapper, + }) + + const planValue = await screen.findByText(/Team plan/) + expect(planValue).toBeInTheDocument() + }) + + it('renders the benefits', async () => { + render(, { + wrapper, + }) + + const benefitsList = await screen.findByText(/BenefitsList/) + expect(benefitsList).toBeInTheDocument() + }) + + it('renders seats number', async () => { + render(, { + wrapper, + }) + + const seats = await screen.findByText(/plan has 8 seats/) + expect(seats).toBeInTheDocument() + }) + + it('renders the plan pricing', async () => { + render(, { + wrapper, + }) + + const planPricing = await screen.findByText(/Plan Pricing/) + expect(planPricing).toBeInTheDocument() + }) + + it('renders actions billing button', async () => { + render(, { + 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(, { + wrapper, + }) + + const scheduledPlanDetails = await screen.findByText( + /Scheduled Plan Details/ + ) + expect(scheduledPlanDetails).toBeInTheDocument() + }) + }) +}) diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/index.js b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/index.js new file mode 100644 index 0000000000..5c0d1d4e4b --- /dev/null +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/index.js @@ -0,0 +1 @@ +export { default } from './PaidPlanCard' diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/ProPlanCard.spec.jsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/ProPlanCard.spec.jsx deleted file mode 100644 index d54843db28..0000000000 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/ProPlanCard.spec.jsx +++ /dev/null @@ -1,83 +0,0 @@ -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import { render, screen } from '@testing-library/react' -import { MemoryRouter, Route } from 'react-router-dom' - -import ProPlanCard from './ProPlanCard' - -const proPlan = { - marketingName: 'Pro Team', - value: 'users-pr', - billingRate: null, - baseUnitPrice: 0, - benefits: ['Unlimited public repositories', 'Unlimited private repositories'], - quantity: 5, -} - -const scheduledPhase = { - quantity: 0, - plan: '', - startDate: 123456789, -} - -const queryClient = new QueryClient({ - defaultOptions: { queries: { retry: false } }, -}) - -const wrapper = ({ children }) => ( - - - {children} - - -) - -describe('ProPlanCard', () => { - describe('When rendered', () => { - it('renders the plan marketing name', () => { - render(, { - wrapper, - }) - - const planValue = screen.getByText(/Pro Team plan/) - expect(planValue).toBeInTheDocument() - }) - - it('renders the benefits', () => { - render(, { - wrapper, - }) - - const benefits = screen.getByText(/Unlimited public repositories/) - expect(benefits).toBeInTheDocument() - }) - - it('renders the scheduled phase', () => { - render(, { - wrapper, - }) - - const scheduledPhaseCopy = screen.getByText(/Scheduled Details/) - expect(scheduledPhaseCopy).toBeInTheDocument() - }) - - it('renders seats number', () => { - render(, { - wrapper, - }) - - const seats = screen.getByText(/plan has 5 seats/) - expect(seats).toBeInTheDocument() - }) - - it('renders actions billing button', () => { - render(, { - wrapper, - }) - - const link = screen.getByRole('link', { name: /Manage plan/ }) - - expect(link).toBeInTheDocument() - expect(link).toHaveAttribute('href', '/plan/bb/critical-role/upgrade') - }) - }) -}) diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/index.js b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/index.js deleted file mode 100644 index c780b6b4c6..0000000000 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/ProPlanCard/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ProPlanCard'