-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6e35b3b
commit 169de52
Showing
11 changed files
with
675 additions
and
452 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
240 changes: 240 additions & 0 deletions
240
...e/subRoutes/CurrentOrgPlan/BillingDetails/EditPaymentMethods/Address/AddressForm.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
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('src/services/account/useUpdateBillingAddress', () => ({ | ||
useUpdateBillingAddress: () => mocks.useUpdateBillingAddress(), | ||
})) | ||
|
||
afterEach(() => { | ||
vi.clearAllMocks() | ||
}) | ||
|
||
describe('AddressForm', () => { | ||
const setup = () => { | ||
const mutation = vi.fn() | ||
mocks.useUpdateBillingAddress.mockReturnValue({ | ||
mutate: mutation, | ||
isLoading: false, | ||
}) | ||
return { user: userEvent.setup() } | ||
} | ||
|
||
it('renders the form', () => { | ||
render( | ||
<AddressForm | ||
address={ | ||
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address | ||
} | ||
name={mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name} | ||
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.only('calls the service to update the address', async () => { | ||
const { user } = setup() | ||
const updateAddress = vi.fn() | ||
mocks.useUpdateBillingAddress.mockReturnValue({ | ||
mutate: updateAddress, | ||
isLoading: false, | ||
}) | ||
|
||
render( | ||
<AddressForm | ||
address={ | ||
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address | ||
} | ||
name={ | ||
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name | ||
} | ||
provider="gh" | ||
owner="codecov" | ||
closeForm={() => {}} | ||
/>, | ||
{ wrapper } | ||
) | ||
|
||
await user.click(screen.getByRole('button', { name: /save/i })) | ||
|
||
expect(updateAddress).toHaveBeenCalled() | ||
}) | ||
}) | ||
|
||
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 | ||
} | ||
provider="gh" | ||
owner="codecov" | ||
closeForm={closeForm} | ||
/>, | ||
{ wrapper } | ||
) | ||
|
||
await user.click(screen.getByRole('button', { name: /cancel/i })) | ||
|
||
expect(closeForm).toHaveBeenCalled() | ||
}) | ||
}) | ||
|
||
describe('when there is an error in the form', () => { | ||
it('renders the error', async () => { | ||
const randomError = 'not a valid address' | ||
mocks.useUpdateBillingAddress.mockReturnValue({ | ||
mutate: vi.fn(), | ||
error: randomError, | ||
}) | ||
|
||
render( | ||
<AddressForm | ||
address={ | ||
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address | ||
} | ||
name={ | ||
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name | ||
} | ||
provider="gh" | ||
owner="codecov" | ||
closeForm={() => {}} | ||
/>, | ||
{ wrapper } | ||
) | ||
|
||
expect(screen.getByText(randomError)).toBeInTheDocument() | ||
}) | ||
}) | ||
|
||
describe('when the form is loading', () => { | ||
it('has the save and cancel buttons disabled', () => { | ||
mocks.useUpdateBillingAddress.mockReturnValue({ | ||
mutate: vi.fn(), | ||
isLoading: true, | ||
}) | ||
|
||
render( | ||
<AddressForm | ||
address={ | ||
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.address | ||
} | ||
name={ | ||
mockSubscriptionDetail.defaultPaymentMethod?.billingDetails?.name | ||
} | ||
provider="gh" | ||
owner="codecov" | ||
closeForm={() => {}} | ||
/>, | ||
{ wrapper } | ||
) | ||
|
||
expect(screen.getByRole('button', { name: /save/i })).toBeDisabled() | ||
expect(screen.getByRole('button', { name: /cancel/i })).toBeDisabled() | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.