Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor and rename paidplancard #2367

Merged
merged 4 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

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 @@
return <EnterprisePlanCard plan={plan} />
}

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

Check warning on line 33 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx

View check run for this annotation

Codecov - Staging / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx#L33

Added line #L33 was not covered by tests

Check warning on line 33 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx#L33

Added line #L33 was not covered by tests

Check warning on line 33 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/CurrentPlanCard.jsx#L33

Added line #L33 was not covered by tests
}

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({

Check warning on line 13 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx

View check run for this annotation

Codecov - Staging / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx#L10-L13

Added lines #L10 - L13 were not covered by tests

Check warning on line 13 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx#L10-L13

Added lines #L10 - L13 were not covered by tests

Check warning on line 13 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx#L10-L13

Added lines #L10 - L13 were not covered by tests
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

Check warning on line 23 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx

View check run for this annotation

Codecov - Staging / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx#L17-L23

Added lines #L17 - L23 were not covered by tests

Check warning on line 23 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx

View check run for this annotation

Codecov - QA / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx#L17-L23

Added lines #L17 - L23 were not covered by tests

Check warning on line 23 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx

View check run for this annotation

Codecov / codecov/patch

src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentPlanCard/PaidPlanCard/PaidPlanCard.jsx#L17-L23

Added lines #L17 - L23 were not covered by tests
Comment on lines +17 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you able to provide any default values here if these values are possibly null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So all of these can't be nullable as per our backend/zod schema, so we should be fine here.

But otherwise, for a scenario that applies, what default value would work here? It almost feels like if we didn't have all of these that we shouldn't show the card, or have designs reflect that state (but to be clear, they're non-nullable here)

Screenshot 2023-11-01 at 9 35 54 AM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, the optional chaining made me think they were possibly nullable


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 @@
)
}

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
Loading