Skip to content

Commit

Permalink
fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
suejung-sentry committed Jan 14, 2025
1 parent 6e35b3b commit 2ade2fc
Show file tree
Hide file tree
Showing 17 changed files with 886 additions and 701 deletions.
28 changes: 16 additions & 12 deletions src/pages/PlanPage/PlanPage.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { MemoryRouter, Route } from 'react-router-dom'

import config from 'config'

import { ThemeContextProvider } from 'shared/ThemeContext'

import PlanPage from './PlanPage'

vi.mock('config')
Expand Down Expand Up @@ -44,18 +46,20 @@ const wrapper =
({ children }) => (
<QueryClientProviderV5 client={queryClientV5}>
<QueryClientProvider client={queryClient}>
<Suspense fallback={null}>
<MemoryRouter initialEntries={[initialEntries]}>
<Route path="/plan/:provider/:owner">{children}</Route>
<Route
path="*"
render={({ location }) => {
testLocation = location
return null
}}
/>
</MemoryRouter>
</Suspense>
<ThemeContextProvider>
<Suspense fallback={null}>
<MemoryRouter initialEntries={[initialEntries]}>
<Route path="/plan/:provider/:owner">{children}</Route>
<Route
path="*"
render={({ location }) => {
testLocation = location
return null
}}
/>
</MemoryRouter>
</Suspense>
</ThemeContextProvider>
</QueryClientProvider>
</QueryClientProviderV5>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ import { Plans } from 'shared/utils/billing'

import BillingDetails from './BillingDetails'

vi.mock('./PaymentCard/PaymentCard', () => ({ default: () => 'Payment Card' }))
vi.mock('./ViewPaymentMethod/PaymentMethod/PaymentMethod', () => ({
default: () => 'Payment Method',
}))
vi.mock('./EmailAddress/EmailAddress', () => ({
default: () => 'Email Address',
}))
vi.mock('./Address/AddressCard', () => ({ default: () => 'Address Card' }))
vi.mock('./ViewPaymentMethod/Address/Address', () => ({
default: () => 'Address',
}))

const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
Expand Down Expand Up @@ -84,12 +88,12 @@ describe('BillingDetails', () => {
}

describe('when there is a subscription', () => {
it('renders the payment card', async () => {
it('renders the payment method card', async () => {
setup({ hasSubscription: true })
render(<BillingDetails />, { wrapper })

const paymentCard = await screen.findByText(/Payment Card/)
expect(paymentCard).toBeInTheDocument()
const paymentCards = await screen.findAllByText(/Payment Method/)
expect(paymentCards.length).toBeGreaterThan(0)
})

it('renders the email address component', async () => {
Expand All @@ -104,7 +108,7 @@ describe('BillingDetails', () => {
setup({ hasSubscription: true })
render(<BillingDetails />, { wrapper })

const addressCard = await screen.findByText(/Address Card/)
const addressCard = await screen.findByText(/Address/)

Check failure on line 111 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/BillingDetails.test.tsx

View workflow job for this annotation

GitHub Actions / Test Runner #2 - Vitest

src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/BillingDetails.test.tsx > BillingDetails > when there is a subscription > renders the address card

TestingLibraryElementError: Found multiple elements with the text: /Address/ Here are the matching elements: Ignored nodes: comments, script, style <div class="flex flex-col divide-y border" > <div class="flex items-center justify-between gap-4 p-4" > <div> <h3 class="font-semibold" > Billing details </h3> <p class="pt-1 text-xs text-ds-gray-octonary" > You can modify your billing details. To update your tax IDs, please <a class=" font-sans cursor-pointer hover:underline focus:ring-2 text-ds-blue-darker inline-flex items-center gap-1" data-cy="support" data-marketing="support" href="https://codecovpro.zendesk.com/hc/en-us" target="_blank" > contact support <span class="text-ds-gray-quinary" > <svg class="w-4 h-4" data-icon="" data-testid="" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" > <path d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" /> </svg> </span> </a> </p> </div> <button class=" flex items-center gap-1 rounded py-1 px-4 transition-colors duration-150 motion-reduce:transition-none focus:outline-none focus:ring disabled:cursor-not-allowed disabled:text-ds-gray-quaternary disabled:border-ds-gray-tertiary disabled:bg-ds-gray-primary justify-center font-semibold text-ds-gray-octonary bg-ds-gray-primary border-ds-gray-quaternary border-solid border shadow hover:bg-ds-gray-secondary flex-none" data-cy="button" data-marketing="button" data-testid="button" > Edit payment </button> </div> Email Address <div> <div class="border-ds-gray-secondary m-0 border-0" data-state="open" > <button aria-controls="radix-:r2:" aria-expanded="true" class="flex w-full items-center justify-between text-left hover:bg-ds-gray-primary [&_#expandable-icon]:data-[state=open]:rotate-180 p-4" data-state="open" type="button" > <span> <h3 class="font-semibold" > Primary Payment Method </h3> </span> <span class="rotate-0 transition-transform" id="expandable-icon" > <svg class="w-4 h-4" data-icon="" data-testid="" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" > <path d="M19 9l-7 7-7-7" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" /> </svg> </span> </button> <div class="border-ds-gray-secondary p-4 border-0 pt-0 text-xs" data-state="open" id="radix-:r2:" style="transition-duration: 0s; animation-name: none;" > <div class="pb-4 pl-4 pt-2" > <div class="flex" > Payment Method <div class="mx-4 w-1/5 border-x border-ds-gray-tertiary px-4" > <h4 class="mb-2 font-semibold" > Cardholder name </h4> <p /> </div> Address </div> </div> </div> </div> </div> </div> Ignored nodes: comments, script, style <div class="flex" > Payment Method <div class="mx-4 w-1/5 border-x border-ds-gray-tertiary px-4" > <h4 class="mb-2 font-semibold" >
expect(addressCard).toBeInTheDocument()
})

Expand Down Expand Up @@ -132,7 +136,7 @@ describe('BillingDetails', () => {
it('renders the payment card', async () => {
render(<BillingDetails />, { wrapper })

const paymentCard = screen.queryByText(/Payment Card/)
const paymentCard = screen.queryByText(/Payment Method/)
expect(paymentCard).not.toBeInTheDocument()
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function BillingDetails() {
setEditMode={setEditMode}
provider={provider}
owner={owner}
existingSubscriptionDetail={subscriptionDetail}
subscriptionDetail={subscriptionDetail}
/>
) : (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
import { Elements } from '@stripe/react-stripe-js'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { MemoryRouter, Route } from 'react-router-dom'
import { vi } from 'vitest'
import { z } from 'zod'

import { SubscriptionDetailSchema } from 'services/account/useAccountDetails'

import AddressForm from './AddressForm'

const queryClient = new QueryClient()

const mockGetElement = vi.fn()
const mockGetValue = vi.fn()

vi.mock('@stripe/react-stripe-js', async () => {
const actual = await vi.importActual('@stripe/react-stripe-js')
return {
...actual,
useElements: () => ({
getElement: mockGetElement.mockReturnValue({
getValue: mockGetValue.mockResolvedValue({
complete: true,
value: {
name: 'John Doe',
address: {
line1: '123 Main St',
line2: null,
city: 'San Francisco',
state: 'CA',
postal_code: '94105',
country: 'US',
},
},
}),
}),
}),
}
})

const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
<QueryClientProvider client={queryClient}>
<Elements stripe={null}>
<MemoryRouter initialEntries={['/plan/gh/codecov']}>
<Route path="/plan/:provider/:owner">{children}</Route>
</MemoryRouter>
</Elements>
</QueryClientProvider>
)

const mockSubscriptionDetail: z.infer<typeof SubscriptionDetailSchema> = {
defaultPaymentMethod: {
billingDetails: {
address: {
line1: '123 Main St',
city: 'San Francisco',
state: 'CA',
postalCode: '94105',
country: 'US',
line2: null,
},
phone: '1234567890',
name: 'John Doe',
email: '[email protected]',
},
card: {
brand: 'visa',
expMonth: 12,
expYear: 2025,
last4: '4242',
},
},
currentPeriodEnd: 1706851492,
cancelAtPeriodEnd: false,
customer: {
id: 'cust_123',
email: '[email protected]',
},
latestInvoice: null,
taxIds: [],
trialEnd: null,
}

const mocks = {
useUpdateBillingAddress: vi.fn(),
}

vi.mock('services/account/useUpdateBillingAddress', () => ({
useUpdateBillingAddress: () => mocks.useUpdateBillingAddress(),
}))

afterEach(() => {
vi.clearAllMocks()
})

describe('AddressForm', () => {
const setup = () => {
return { user: userEvent.setup() }
}

it('renders the form', () => {
mocks.useUpdateBillingAddress.mockReturnValue({
mutate: vi.fn(),
isLoading: false,
})

render(
<AddressForm
address={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address
}
name={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name ||
undefined
}
provider="gh"
owner="codecov"
closeForm={() => {}}
/>,
{ wrapper }
)

expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument()
expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument()
})

describe('when submitting', () => {
it('calls the service to update the address', async () => {
const user = userEvent.setup()
const updateAddress = vi.fn()
mocks.useUpdateBillingAddress.mockReturnValue({
mutate: updateAddress,
isLoading: false,
})

render(
<AddressForm
address={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address
}
name={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name ||
undefined
}
provider="gh"
owner="codecov"
closeForm={() => {}}
/>,
{ wrapper }
)

await user.click(screen.getByTestId('submit-address-update'))
expect(updateAddress).toHaveBeenCalledWith(
{
name: 'John Doe',
address: {
line1: '123 Main St',
line2: null,
city: 'San Francisco',
state: 'CA',
postal_code: '94105',
country: 'US',
},
},
expect.any(Object)
)
})
})

describe('when the user clicks on cancel', () => {
it('calls the closeForm prop', async () => {
const { user } = setup()
const closeForm = vi.fn()
mocks.useUpdateBillingAddress.mockReturnValue({
mutate: vi.fn(),
isLoading: false,
})

render(
<AddressForm
address={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address
}
name={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name ||
undefined
}
provider="gh"
owner="codecov"
closeForm={closeForm}
/>,
{ wrapper }
)

await user.click(screen.getByRole('button', { name: /cancel/i }))

expect(closeForm).toHaveBeenCalled()
})
})

describe('when the form is loading', () => {
it('has the save and cancel buttons disabled', () => {
mocks.useUpdateBillingAddress.mockReturnValue({
mutate: vi.fn(),
isLoading: true,
error: null,
reset: vi.fn(),
})

render(
<AddressForm
address={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address
}
name={
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name ||
undefined
}
provider="gh"
owner="codecov"
closeForm={() => {}}
/>,
{ wrapper }
)

expect(screen.getByRole('button', { name: /save/i })).toBeDisabled()
expect(screen.getByRole('button', { name: /cancel/i })).toBeDisabled()
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Button from 'ui/Button'

interface AddressFormProps {
address?: z.infer<typeof AddressSchema>
name?: string | null | undefined
name?: string
closeForm: () => void
provider: string
owner: string
Expand All @@ -23,12 +23,7 @@ function AddressForm({
}: AddressFormProps) {
const elements = useElements()

const {
mutate: updateAddress,
isLoading,
error,
reset,
} = useUpdateBillingAddress({
const { mutate: updateAddress, isLoading } = useUpdateBillingAddress({
provider,
owner,
})
Expand All @@ -47,8 +42,6 @@ function AddressForm({
}
}

const showError = error && !reset

return (
<form onSubmit={submit} aria-label="form">
<div className={cs('flex flex-col gap-3')}>
Expand All @@ -72,15 +65,13 @@ function AddressForm({
},
}}
/>
<p className="mt-1 text-ds-primary-red">{showError && error}</p>
</div>
<div className="flex gap-1">
<Button
hook="submit-address-update"
type="submit"
variant="primary"
disabled={isLoading}
to={undefined}
>
Save
</Button>
Expand All @@ -90,7 +81,6 @@ function AddressForm({
variant="plain"
disabled={isLoading}
onClick={closeForm}
to={undefined}
>
Cancel
</Button>
Expand Down
Loading

0 comments on commit 2ade2fc

Please sign in to comment.