diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.test.tsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.test.tsx index 9e01293cb6..fa43871a3d 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.test.tsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.test.tsx @@ -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', diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.tsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.tsx index c5b343b8a7..4650fb425a 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.tsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/AccountOrgs/AccountOrgs.tsx @@ -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 { diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.test.tsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.test.tsx index ab478617f9..b737cd079b 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.test.tsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.test.tsx @@ -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' @@ -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 { EnterpriseAccountDetailsRequestSchema } 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: {}, @@ -81,6 +78,14 @@ const mockEnterpriseAccountDetailsHundredPercent = { }, } +const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false } }, +}) + +const queryClientV5 = new QueryClientV5({ + defaultOptions: { queries: { retry: false } }, +}) + const alertOptionWrapperCreator = ( alertOptionString: AlertOptionsType | '', isCancellation?: boolean @@ -88,19 +93,23 @@ const alertOptionWrapperCreator = ( const wrapper: React.FC = ({ children }) => ( - - - {children} - - + + + Loading}> + + {children} + + + + ) @@ -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 - enterpriseAccountDetails?: ReturnType< - typeof useEnterpriseAccountDetails - >['data'] + enterpriseAccountDetails?: z.infer< + typeof EnterpriseAccountDetailsRequestSchema + > } describe('CurrentOrgPlan', () => { @@ -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) + }) ) } @@ -402,8 +418,8 @@ describe('CurrentOrgPlan', () => { setup({ enterpriseAccountDetails: mockEnterpriseAccountDetailsHundredPercent, }) - render(, { wrapper }) + const banner = await screen.findByText( /Your account is using 100% of its seats/ ) diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.tsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.tsx index f84b68a5fa..806576d679 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.tsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/CurrentOrgPlan.tsx @@ -1,3 +1,4 @@ +import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5' import { useParams } from 'react-router-dom' import { usePlanUpdatedNotification } from 'pages/PlanPage/context' @@ -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 @@ -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 diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/hooks/useEnterpriseAccountDetails.test.tsx b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/queries/EnterpriseAccountDetailsQueryOpts.test.tsx similarity index 67% rename from src/pages/PlanPage/subRoutes/CurrentOrgPlan/hooks/useEnterpriseAccountDetails.test.tsx rename to src/pages/PlanPage/subRoutes/CurrentOrgPlan/queries/EnterpriseAccountDetailsQueryOpts.test.tsx index 6b12cef1b4..eed76322da 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/hooks/useEnterpriseAccountDetails.test.tsx +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/queries/EnterpriseAccountDetailsQueryOpts.test.tsx @@ -1,9 +1,13 @@ -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: { @@ -11,28 +15,34 @@ const mockEnterpriseAccountDetails = { 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 = ({ children }) => ( - {children} + + {children} + ) -beforeAll(() => server.listen()) +beforeAll(() => { + server.listen() +}) + afterEach(() => { - queryClient.clear() + queryClientV5.clear() server.resetHandlers() }) -afterAll(() => server.close()) + +afterAll(() => { + server.close() +}) interface SetupArgs { badResponse?: boolean @@ -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 } ) @@ -73,10 +89,12 @@ describe('useEnterpriseAccountDetails', () => { setup({}) const { result } = renderHook( () => - useEnterpriseAccountDetails({ - provider: 'gh', - owner: 'codecov', - }), + useQueryV5( + EnterpriseAccountDetailsQueryOpts({ + provider: 'gh', + owner: 'codecov', + }) + ), { wrapper } ) diff --git a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/hooks/useEnterpriseAccountDetails.ts b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/queries/EnterpriseAccountDetailsQueryOpts.ts similarity index 67% rename from src/pages/PlanPage/subRoutes/CurrentOrgPlan/hooks/useEnterpriseAccountDetails.ts rename to src/pages/PlanPage/subRoutes/CurrentOrgPlan/queries/EnterpriseAccountDetailsQueryOpts.ts index 22657b0cec..3e72388354 100644 --- a/src/pages/PlanPage/subRoutes/CurrentOrgPlan/hooks/useEnterpriseAccountDetails.ts +++ b/src/pages/PlanPage/subRoutes/CurrentOrgPlan/queries/EnterpriseAccountDetailsQueryOpts.ts @@ -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(), @@ -15,7 +15,7 @@ const AccountSchema = z.object({ export type Account = z.infer -const RequestSchema = z.object({ +export const EnterpriseAccountDetailsRequestSchema = z.object({ owner: z .object({ account: AccountSchema.nullable(), @@ -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({ @@ -56,14 +56,17 @@ export function useEnterpriseAccountDetails({ owner, }, }).then((res) => { - const parsedRes = RequestSchema.safeParse(res?.data) + const parsedRes = EnterpriseAccountDetailsRequestSchema.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