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

chore: Migrate useEnterpriseAccountDetails to TS Query V5 #3571

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -11,7 +11,7 @@ import { MemoryRouter, Route, useLocation } from 'react-router'

import AccountOrgs from './AccountOrgs'

import { Account } from '../hooks/useEnterpriseAccountDetails'
import { Account } from '../queries/EnterpriseAccountDetailsQueryOpts'

const mockAccount: Account = {
name: 'my-account',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Icon from 'ui/Icon'
import Spinner from 'ui/Spinner'
import { Tooltip } from 'ui/Tooltip'

import { Account } from '../hooks/useEnterpriseAccountDetails'
import { Account } from '../queries/EnterpriseAccountDetailsQueryOpts'
import { InfiniteAccountOrganizationsQueryOpts } from '../queries/InfiniteAccountOrganizationsQueryOpts'

interface AccountOrgsArgs {
Expand Down
84 changes: 50 additions & 34 deletions src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import {
QueryClientProvider as QueryClientProviderV5,
QueryClient as QueryClientV5,
} from '@tanstack/react-queryV5'
import { render, screen } from '@testing-library/react'
import noop from 'lodash/noop'
import { graphql, http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { Suspense } from 'react'
import { MemoryRouter, Route } from 'react-router-dom'
import { z } from 'zod'

Expand All @@ -12,21 +17,13 @@ import { Plans } from 'shared/utils/billing'
import { AlertOptions, type AlertOptionsType } from 'ui/Alert'

import CurrentOrgPlan from './CurrentOrgPlan'
import { useEnterpriseAccountDetails } from './hooks/useEnterpriseAccountDetails'
import { RequestSchema as EnterpriseAccountDetailsQueryOptsSchema } from './queries/EnterpriseAccountDetailsQueryOpts'

vi.mock('./BillingDetails', () => ({ default: () => 'BillingDetails' }))
vi.mock('./CurrentPlanCard', () => ({ default: () => 'CurrentPlanCard' }))
vi.mock('./LatestInvoiceCard', () => ({ default: () => 'LatestInvoiceCard' }))
vi.mock('./AccountOrgs', () => ({ default: () => 'AccountOrgs' }))

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

const mockedAccountDetails = {
planProvider: 'github',
rootOrganization: {},
Expand Down Expand Up @@ -81,26 +78,38 @@ const mockEnterpriseAccountDetailsHundredPercent = {
},
}

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

const queryClientV5 = new QueryClientV5({
defaultOptions: { queries: { retry: false } },
})

const alertOptionWrapperCreator = (
alertOptionString: AlertOptionsType | '',
isCancellation?: boolean
) => {
const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
<MemoryRouter initialEntries={['/billing/gh/codecov']}>
<Route path="/billing/:provider/:owner">
<QueryClientProvider client={queryClient}>
<PlanUpdatedPlanNotificationContext.Provider
value={{
updatedNotification: {
alertOption: alertOptionString,
isCancellation,
},
setUpdatedNotification: noop,
}}
>
{children}
</PlanUpdatedPlanNotificationContext.Provider>
</QueryClientProvider>
<QueryClientProviderV5 client={queryClientV5}>
<QueryClientProvider client={queryClient}>
<Suspense fallback={<div>Loading</div>}>
<PlanUpdatedPlanNotificationContext.Provider
value={{
updatedNotification: {
alertOption: alertOptionString,
isCancellation,
},
setUpdatedNotification: noop,
}}
>
{children}
</PlanUpdatedPlanNotificationContext.Provider>
</Suspense>
</QueryClientProvider>
</QueryClientProviderV5>
</Route>
</MemoryRouter>
)
Expand All @@ -112,18 +121,25 @@ const wrapper = alertOptionWrapperCreator(AlertOptions.SUCCESS)
const noUpdatedPlanWrapper = alertOptionWrapperCreator('')
const cancellationPlanWrapper = alertOptionWrapperCreator('', true)

beforeAll(() => server.listen())
beforeAll(() => {
server.listen()
})

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

afterAll(() => {
server.close()
})

interface SetupArgs {
accountDetails?: z.infer<typeof AccountDetailsSchema>
enterpriseAccountDetails?: ReturnType<
typeof useEnterpriseAccountDetails
>['data']
enterpriseAccountDetails?: z.infer<
typeof EnterpriseAccountDetailsQueryOptsSchema
>
}

describe('CurrentOrgPlan', () => {
Expand All @@ -132,12 +148,12 @@ describe('CurrentOrgPlan', () => {
enterpriseAccountDetails = mockNoEnterpriseAccount,
}: SetupArgs) {
server.use(
graphql.query('EnterpriseAccountDetails', () =>
HttpResponse.json({ data: enterpriseAccountDetails })
),
http.get('/internal/:provider/:owner/account-details', () =>
HttpResponse.json(accountDetails)
)
graphql.query('EnterpriseAccountDetails', () => {
return HttpResponse.json({ data: enterpriseAccountDetails })
}),
http.get('/internal/:provider/:owner/account-details', () => {
return HttpResponse.json(accountDetails)
})
)
}

Expand Down Expand Up @@ -402,8 +418,8 @@ describe('CurrentOrgPlan', () => {
setup({
enterpriseAccountDetails: mockEnterpriseAccountDetailsHundredPercent,
})

render(<CurrentOrgPlan />, { wrapper })

const banner = await screen.findByText(
/Your account is using 100% of its seats/
)
Expand Down
13 changes: 8 additions & 5 deletions src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5'
import { useParams } from 'react-router-dom'

import { usePlanUpdatedNotification } from 'pages/PlanPage/context'
Expand All @@ -9,10 +10,10 @@ import { Alert } from 'ui/Alert'
import AccountOrgs from './AccountOrgs'
import BillingDetails from './BillingDetails'
import CurrentPlanCard from './CurrentPlanCard'
import { useEnterpriseAccountDetails } from './hooks/useEnterpriseAccountDetails'
import InfoAlertCancellation from './InfoAlertCancellation'
import InfoMessageStripeCallback from './InfoMessageStripeCallback'
import LatestInvoiceCard from './LatestInvoiceCard'
import { EnterpriseAccountDetailsQueryOpts } from './queries/EnterpriseAccountDetailsQueryOpts'

interface URLParams {
provider: string
Expand All @@ -25,10 +26,12 @@ function CurrentOrgPlan() {
provider,
owner,
})
const { data: enterpriseDetails } = useEnterpriseAccountDetails({
provider,
owner,
})
const { data: enterpriseDetails } = useSuspenseQueryV5(
EnterpriseAccountDetailsQueryOpts({
provider,
owner,
})
)

const scheduledPhase = accountDetails?.scheduleDetail?.scheduledPhase
const isDelinquent = accountDetails?.delinquent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import {
QueryClientProvider as QueryClientProviderV5,
QueryClient as QueryClientV5,
useQuery as useQueryV5,
} from '@tanstack/react-queryV5'
import { renderHook, waitFor } from '@testing-library/react'
import { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'

import { useEnterpriseAccountDetails } from './useEnterpriseAccountDetails'
import { EnterpriseAccountDetailsQueryOpts } from './EnterpriseAccountDetailsQueryOpts'

const mockEnterpriseAccountDetails = {
owner: {
account: {
name: 'account-name',
totalSeatCount: 10,
activatedUserCount: 7,
organizations: {
totalCount: 3,
},
organizations: { totalCount: 3 },
},
},
}

const queryClient = new QueryClient({
const queryClientV5 = new QueryClientV5({
defaultOptions: { queries: { retry: false } },
})
const server = setupServer()

const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
<QueryClientProviderV5 client={queryClientV5}>
{children}
</QueryClientProviderV5>
)

beforeAll(() => server.listen())
beforeAll(() => {
server.listen()
})

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

afterAll(() => {
server.close()
})

interface SetupArgs {
badResponse?: boolean
Expand All @@ -54,7 +64,13 @@ describe('useEnterpriseAccountDetails', () => {
setup({ badResponse: true })
console.error = () => {}
const { result } = renderHook(
() => useEnterpriseAccountDetails({ provider: 'gh', owner: 'codecov' }),
() =>
useQueryV5(
EnterpriseAccountDetailsQueryOpts({
provider: 'gh',
owner: 'codecov',
})
),
{ wrapper }
)

Expand All @@ -73,10 +89,12 @@ describe('useEnterpriseAccountDetails', () => {
setup({})
const { result } = renderHook(
() =>
useEnterpriseAccountDetails({
provider: 'gh',
owner: 'codecov',
}),
useQueryV5(
EnterpriseAccountDetailsQueryOpts({
provider: 'gh',
owner: 'codecov',
})
),
{ wrapper }
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useQuery } from '@tanstack/react-query'
import { queryOptions as queryOptionsV5 } from '@tanstack/react-queryV5'
import { z } from 'zod'

import Api from 'shared/api/api'
import { NetworkErrorObject } from 'shared/api/helpers'
import { rejectNetworkError } from 'shared/api/helpers'

const AccountSchema = z.object({
name: z.string(),
Expand All @@ -15,7 +15,7 @@ const AccountSchema = z.object({

export type Account = z.infer<typeof AccountSchema>

const RequestSchema = z.object({
export const RequestSchema = z.object({
owner: z
.object({
account: AccountSchema.nullable(),
Expand All @@ -36,16 +36,16 @@ const query = `query EnterpriseAccountDetails($owner: String!) {
}
}`

interface UseEnterpriseAccountDetailsArgs {
interface EnterpriseAccountDetailsQueryArgs {
provider: string
owner: string
}

export function useEnterpriseAccountDetails({
export function EnterpriseAccountDetailsQueryOpts({
provider,
owner,
}: UseEnterpriseAccountDetailsArgs) {
return useQuery({
}: EnterpriseAccountDetailsQueryArgs) {
return queryOptionsV5({
queryKey: ['EnterpriseAccountDetails', provider, owner],
queryFn: ({ signal }) =>
Api.graphql({
Expand All @@ -59,11 +59,12 @@ export function useEnterpriseAccountDetails({
const parsedRes = RequestSchema.safeParse(res?.data)

if (!parsedRes.success) {
return Promise.reject({
return rejectNetworkError({
status: 404,
data: {},
dev: 'useEnterpriseAccountDetails - 404 Failed to parse data',
} satisfies NetworkErrorObject)
error: parsedRes.error,
})
}

return parsedRes.data
Expand Down
Loading