diff --git a/src/layouts/Header/components/SeatDetails/SeatDetails.test.tsx b/src/layouts/Header/components/SeatDetails/SeatDetails.test.tsx index 893bf56189..d59b1081c7 100644 --- a/src/layouts/Header/components/SeatDetails/SeatDetails.test.tsx +++ b/src/layouts/Header/components/SeatDetails/SeatDetails.test.tsx @@ -1,7 +1,12 @@ 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 { graphql, HttpResponse } from 'msw' import { setupServer } from 'msw/node' +import { Suspense } from 'react' import { MemoryRouter, Route } from 'react-router-dom' import SeatDetails from './SeatDetails' @@ -14,9 +19,16 @@ const mockData = { } const mockUndefinedSeats = { - config: {}, + config: null, } +const queryClient = new QueryClient({ + defaultOptions: { queries: { retry: false } }, +}) +const queryClientV5 = new QueryClientV5({ + defaultOptions: { queries: { retry: false } }, +}) + const wrapper: ({ initialEntries, }: { @@ -24,27 +36,26 @@ const wrapper: ({ }) => React.FC = ({ initialEntries = '/gh' }) => ({ children }) => ( - - - - {children} - - - + + + + + Loading}>{children} + + + + ) -const queryClient = new QueryClient({ - defaultOptions: { queries: { retry: false } }, -}) - const server = setupServer() beforeAll(() => { server.listen() }) afterEach(() => { - server.resetHandlers() queryClient.clear() + queryClientV5.clear() + server.resetHandlers() }) afterAll(() => { @@ -62,12 +73,10 @@ describe('SeatDetails', () => { describe('renders component', () => { describe('values are defined', () => { - beforeEach(() => { - setup({}) - }) - it('displays the number of active seats', async () => { + setup({}) render(, { wrapper: wrapper({}) }) + const number = await screen.findByText('5') expect(number).toBeInTheDocument() @@ -76,6 +85,7 @@ describe('SeatDetails', () => { }) it('displays the number of total seats', async () => { + setup({}) render(, { wrapper: wrapper({}) }) const number = await screen.findByText('10') diff --git a/src/layouts/Header/components/SeatDetails/SeatDetails.tsx b/src/layouts/Header/components/SeatDetails/SeatDetails.tsx index edf72fbbdb..76add31d1d 100644 --- a/src/layouts/Header/components/SeatDetails/SeatDetails.tsx +++ b/src/layouts/Header/components/SeatDetails/SeatDetails.tsx @@ -1,7 +1,17 @@ -import { useSelfHostedSeatsConfig } from 'services/selfHosted' +import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5' +import { useParams } from 'react-router' + +import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts' + +interface URLParams { + provider: string +} function SeatDetails() { - const { data: selfHostedSeats } = useSelfHostedSeatsConfig() + const { provider } = useParams() + const { data: selfHostedSeats } = useSuspenseQueryV5( + SelfHostedSeatsConfigQueryOpts({ provider }) + ) if (!selfHostedSeats?.seatsUsed || !selfHostedSeats?.seatsLimit) { return

Unable to get seat usage information

diff --git a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.jsx b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.jsx index 1a3d57115a..06a73f7db1 100644 --- a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.jsx +++ b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.jsx @@ -1,9 +1,9 @@ import { useQueryClient } from '@tanstack/react-query' +import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5' +import { useParams } from 'react-router' -import { - useSelfHostedCurrentUser, - useSelfHostedSeatsConfig, -} from 'services/selfHosted' +import { useSelfHostedCurrentUser } from 'services/selfHosted' +import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts' import A from 'ui/A' import Banner from 'ui/Banner' import BannerContent from 'ui/Banner/BannerContent' @@ -39,9 +39,12 @@ function canChangeActivation({ seatConfig, currentUser }) { } function ActivationBanner() { + const { provider } = useParams() const queryClient = useQueryClient() const { data: currentUser } = useSelfHostedCurrentUser() - const { data: seatConfig } = useSelfHostedSeatsConfig() + const { data: seatConfig } = useSuspenseQueryV5( + SelfHostedSeatsConfigQueryOpts({ provider }) + ) const { canChange, displaySeatMsg } = canChangeActivation({ seatConfig, diff --git a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.test.jsx b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.test.jsx index 2e8316eb23..2b4177d2f6 100644 --- a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.test.jsx +++ b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.test.jsx @@ -1,10 +1,14 @@ 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 userEvent from '@testing-library/user-event' import { graphql, http, HttpResponse } from 'msw' import { setupServer } from 'msw/node' -import { Route } from 'react-router-dom' -import { MemoryRouter } from 'react-router-dom/cjs/react-router-dom.min' +import { Suspense } from 'react' +import { MemoryRouter, Route } from 'react-router-dom' import ActivationBanner from './ActivationBanner' @@ -27,27 +31,38 @@ const mockUserData = { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } }, }) -const server = setupServer() +const queryClientV5 = new QueryClientV5({ + defaultOptions: { queries: { retry: false } }, +}) + +const wrapper = ({ children }) => ( + + + + + Loading}>{children} + + + + +) + +const server = setupServer() beforeAll(() => { server.listen() }) -beforeEach(() => { + +afterEach(() => { queryClient.clear() + queryClientV5.clear() server.resetHandlers() }) + afterAll(() => { server.close() }) -const wrapper = ({ children }) => ( - - - {children} - - -) - describe('ActivationBanner', () => { function setup( { overrideUserData = {}, overrideSeatData = {} } = { @@ -58,14 +73,14 @@ describe('ActivationBanner', () => { const user = userEvent.setup() let restUsersCurrent = { ...mockUserData, ...overrideUserData } - const querySeats = { ...mockSeatData, ...overrideSeatData } + const querySeats = { ...mockSeatData.config, ...overrideSeatData } server.use( http.get('/internal/users/current', () => { return HttpResponse.json(restUsersCurrent) }), graphql.query('Seats', () => { - return HttpResponse.json({ data: querySeats }) + return HttpResponse.json({ data: { config: querySeats } }) }), http.patch('/internal/users/current', async (info) => { const { activated } = await info.request.json() @@ -83,9 +98,8 @@ describe('ActivationBanner', () => { } describe('rendering banner header', () => { - beforeEach(() => setup()) - it('renders header content', async () => { + setup() render(, { wrapper }) const heading = await screen.findByText('Activation Status') @@ -95,9 +109,8 @@ describe('ActivationBanner', () => { describe('rendering banner content', () => { describe('user is activated', () => { - beforeEach(() => setup({ overrideUserData: { activated: true } })) - it('displays user is activated', async () => { + setup({ overrideUserData: { activated: true } }) render(, { wrapper }) const activated = await screen.findByText('You are currently activated') @@ -107,9 +120,8 @@ describe('ActivationBanner', () => { describe('user is not activated', () => { describe('org has free seats', () => { - beforeEach(() => setup({ overrideSeatData: { activated: false } })) - it('displays user is not activated', async () => { + setup({ overrideSeatData: { activated: false } }) render(, { wrapper }) const activated = await screen.findByText( @@ -120,14 +132,11 @@ describe('ActivationBanner', () => { }) describe('org does not have free seats', () => { - beforeEach(() => + it('displays org out of seat message', async () => { setup({ overrideSeatData: { seatsUsed: 10, seatsLimit: 10 }, overrideUserData: { activated: false }, }) - ) - - it('displays org out of seat message', async () => { render(, { wrapper }) const noSeatMsg = await screen.findByText( @@ -137,6 +146,10 @@ describe('ActivationBanner', () => { }) it('sets toggle to disabled', async () => { + setup({ + overrideSeatData: { seatsUsed: 10, seatsLimit: 10 }, + overrideUserData: { activated: false }, + }) render(, { wrapper }) const button = await screen.findByRole('button') diff --git a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.js b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.js index ce174df043..4e3e26e4a4 100644 --- a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.js +++ b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.js @@ -1,10 +1,13 @@ import { useMutation } from '@tanstack/react-query' +import { useQueryClient as useQueryClientV5 } from '@tanstack/react-queryV5' import { useParams } from 'react-router-dom' +import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts' import Api from 'shared/api' export const useSelfActivationMutation = ({ queryClient, canChange }) => { const { provider } = useParams() + const queryClientV5 = useQueryClientV5() return useMutation({ mutationFn: (activated) => { @@ -18,10 +21,14 @@ export const useSelfActivationMutation = ({ queryClient, canChange }) => { }, onMutate: async (activated) => { await queryClient.cancelQueries(['SelfHostedCurrentUser']) - await queryClient.cancelQueries(['Seats']) + await queryClientV5.cancelQueries({ + queryKey: SelfHostedSeatsConfigQueryOpts({ provider }).queryKey, + }) const prevUser = queryClient.getQueryData(['SelfHostedCurrentUser']) - const prevSeat = queryClient.getQueryData(['Seats']) + const prevSeat = queryClientV5.getQueryData( + SelfHostedSeatsConfigQueryOpts({ provider }).queryKey + ) if (canChange) { queryClient.setQueryData(['SelfHostedCurrentUser'], (user) => ({ @@ -29,32 +36,36 @@ export const useSelfActivationMutation = ({ queryClient, canChange }) => { activated, })) - queryClient.setQueryData(['Seats'], (seats) => { - const seatsUsed = seats?.data?.config?.seatsUsed - - return { - data: { - config: { - ...seats?.data?.config, - seatsUsed: activated ? seatsUsed + 1 : seatsUsed - 1, + queryClientV5.setQueryData( + SelfHostedSeatsConfigQueryOpts({ provider }).queryKey, + (seats) => { + const seatsUsed = seats?.data?.config?.seatsUsed + return { + data: { + config: { + ...seats?.data?.config, + seatsUsed: activated ? seatsUsed + 1 : seatsUsed - 1, + }, }, - }, + } } - }) + ) } - return { - prevUser, - prevSeat, - } + return { prevUser, prevSeat } }, onError: (_err, _activated, context) => { queryClient.setQueryData(['SelfHostedCurrentUser'], context.prevUser) - queryClient.setQueryData(['Seats'], context.prevSeat) + queryClientV5.setQueryData( + SelfHostedSeatsConfigQueryOpts({ provider }).queryKey, + context.prevSeat + ) }, onSettled: () => { queryClient.invalidateQueries(['SelfHostedCurrentUser']) - queryClient.invalidateQueries(['Seats']) + queryClientV5.invalidateQueries( + SelfHostedSeatsConfigQueryOpts({ provider }).queryKey + ) }, }) } diff --git a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.test.jsx b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.test.jsx index e704710534..eec7be64cf 100644 --- a/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.test.jsx +++ b/src/pages/AccountSettings/tabs/Profile/ActivationBanner/useSelfActivationMutation.test.jsx @@ -1,39 +1,51 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { + QueryClientProvider as QueryClientProviderV5, + QueryClient as QueryClientV5, +} from '@tanstack/react-queryV5' import { renderHook, waitFor } from '@testing-library/react' import { http, HttpResponse } from 'msw' import { setupServer } from 'msw/node' import { MemoryRouter, Route } from 'react-router-dom' import { act } from 'react-test-renderer' +import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts' + import { useSelfActivationMutation } from './useSelfActivationMutation' const queryClient = new QueryClient({ - logger: { - error: () => {}, - }, - defaultOptions: { - retry: false, - }, + logger: { error: () => {} }, + defaultOptions: { retry: false }, +}) + +const queryClientV5 = new QueryClientV5({ + logger: { error: () => {} }, + defaultOptions: { retry: false }, }) -const server = setupServer() const wrapper = (initialEntries = '/gh') => ({ children }) => ( - - - {children} - - + + + + {children} + + + ) +const server = setupServer() beforeAll(() => { server.listen() }) -beforeEach(() => { + +afterEach(() => { queryClient.clear() + queryClientV5.clear() server.resetHandlers() }) + afterAll(() => { server.close() }) @@ -42,14 +54,10 @@ describe('useSelfActivationMutation', () => { describe('on a successful call', () => { describe('user can activate themselves', () => { beforeEach(() => { - queryClient.setQueryData(['Seats'], { - data: { - config: { - seatsUsed: 0, - seatsLimit: 10, - }, - }, - }) + queryClientV5.setQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey, + { data: { config: { seatsUsed: 0, seatsLimit: 10 } } } + ) queryClient.setQueryData(['SelfHostedCurrentUser'], { activated: false, @@ -82,7 +90,11 @@ describe('useSelfActivationMutation', () => { act(() => result.current.mutate(true)) await waitFor(() => - expect(queryClient.getQueryData(['Seats'])).toStrictEqual({ + expect( + queryClientV5.getQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey + ) + ).toStrictEqual({ data: { config: { seatsUsed: 1, seatsLimit: 10 } }, }) ) @@ -97,14 +109,10 @@ describe('useSelfActivationMutation', () => { describe('user can deactivate themselves', () => { beforeEach(() => { - queryClient.setQueryData(['Seats'], { - data: { - config: { - seatsUsed: 1, - seatsLimit: 10, - }, - }, - }) + queryClientV5.setQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey, + { data: { config: { seatsUsed: 1, seatsLimit: 10 } } } + ) queryClient.setQueryData(['SelfHostedCurrentUser'], { activated: true, @@ -136,7 +144,11 @@ describe('useSelfActivationMutation', () => { act(() => result.current.mutate(false)) await waitFor(() => - expect(queryClient.getQueryData(['Seats'])).toStrictEqual({ + expect( + queryClientV5.getQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey + ) + ).toStrictEqual({ data: { config: { seatsUsed: 0, seatsLimit: 10 } }, }) ) @@ -151,14 +163,10 @@ describe('useSelfActivationMutation', () => { describe('user cannot change their status', () => { beforeEach(() => { - queryClient.setQueryData(['Seats'], { - data: { - config: { - seatsUsed: 10, - seatsLimit: 10, - }, - }, - }) + queryClientV5.setQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey, + { data: { config: { seatsUsed: 10, seatsLimit: 10 } } } + ) queryClient.setQueryData(['SelfHostedCurrentUser'], { activated: false, @@ -191,7 +199,11 @@ describe('useSelfActivationMutation', () => { act(() => result.current.mutate(false)) await waitFor(() => - expect(queryClient.getQueryData(['Seats'])).toStrictEqual({ + expect( + queryClientV5.getQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey + ) + ).toStrictEqual({ data: { config: { seatsUsed: 10, seatsLimit: 10 } }, }) ) @@ -207,14 +219,10 @@ describe('useSelfActivationMutation', () => { describe('on an unsuccessful call', () => { beforeEach(() => { - queryClient.setQueryData(['Seats'], { - data: { - config: { - seatsUsed: 1, - seatsLimit: 10, - }, - }, - }) + queryClientV5.setQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey, + { data: { config: { seatsUsed: 1, seatsLimit: 10 } } } + ) queryClient.setQueryData(['SelfHostedCurrentUser'], { activated: true, @@ -243,7 +251,11 @@ describe('useSelfActivationMutation', () => { act(() => result.current.mutate(false)) await waitFor(() => - expect(queryClient.getQueryData(['Seats'])).toStrictEqual({ + expect( + queryClientV5.getQueryData( + SelfHostedSeatsConfigQueryOpts({ provider: 'gh' }).queryKey + ) + ).toStrictEqual({ data: { config: { seatsUsed: 1, seatsLimit: 10 } }, }) ) diff --git a/src/pages/AccountSettings/tabs/Profile/Profile.test.jsx b/src/pages/AccountSettings/tabs/Profile/Profile.test.jsx index c4a0988205..9d1828f935 100644 --- a/src/pages/AccountSettings/tabs/Profile/Profile.test.jsx +++ b/src/pages/AccountSettings/tabs/Profile/Profile.test.jsx @@ -1,7 +1,12 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { + QueryClientProvider as QueryClientProviderV5, + QueryClient as QueryClientV5, +} from '@tanstack/react-queryV5' import { render, screen, waitFor } from '@testing-library/react' import { graphql, http, HttpResponse } from 'msw' import { setupServer } from 'msw/node' +import { Suspense } from 'react' import { MemoryRouter, Route } from 'react-router-dom' import Profile from './Profile' @@ -9,13 +14,20 @@ import Profile from './Profile' const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } }, }) +const queryClientV5 = new QueryClientV5({ + defaultOptions: { queries: { retry: false } }, +}) const wrapper = ({ children }) => ( - - - {children} - - + + + + + Loading}>{children} + + + + ) const mockUser = { @@ -26,12 +38,19 @@ const mockUser = { } const server = setupServer() -beforeAll(() => server.listen()) -beforeEach(() => { - server.resetHandlers() +beforeAll(() => { + server.listen() +}) + +afterEach(() => { queryClient.clear() + queryClientV5.clear() + server.resetHandlers() +}) + +afterAll(() => { + server.close() }) -afterAll(() => server.close()) describe('Profile', () => { function setup() { diff --git a/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx b/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx index 876b363d1d..289d6b2aa5 100644 --- a/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx +++ b/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx @@ -1,7 +1,12 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { + QueryClientProvider as QueryClientProviderV5, + QueryClient as QueryClientV5, +} from '@tanstack/react-queryV5' import { render, screen, waitFor } from '@testing-library/react' import { graphql, http, HttpResponse } from 'msw' import { setupServer } from 'msw/node' +import { Suspense } from 'react' import { MemoryRouter, Route } from 'react-router-dom' import { vi } from 'vitest' @@ -9,19 +14,24 @@ import ActivationRequiredSelfHosted from './ActivationRequiredSelfHosted' const queryClient = new QueryClient({ defaultOptions: { - queries: { - retry: false, - suspense: false, - }, + queries: { retry: false, suspense: false }, }, }) +const queryClientV5 = new QueryClientV5({ + defaultOptions: { queries: { retry: false } }, +}) + const wrapper: React.FC = ({ children }) => ( - - - {children} - - + + + + + Loading}>{children} + + + + ) const server = setupServer() @@ -33,6 +43,7 @@ beforeAll(() => { afterEach(() => { queryClient.clear() + queryClientV5.clear() server.resetHandlers() vi.clearAllMocks() }) diff --git a/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx b/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx index 61d6bb0d96..3cb07b7a67 100644 --- a/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx +++ b/src/pages/RepoPage/ActivationAlert/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx @@ -1,8 +1,9 @@ +import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5' +import { useParams } from 'react-router' + import upsideDownUmbrella from 'layouts/shared/NetworkErrorBoundary/assets/error-upsidedown-umbrella.svg' -import { - useSelfHostedCurrentUser, - useSelfHostedSeatsConfig, -} from 'services/selfHosted' +import { useSelfHostedCurrentUser } from 'services/selfHosted' +import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts' import A from 'ui/A' import Button from 'ui/Button' @@ -55,9 +56,16 @@ function SeatsAvailable({ isAdmin }: { isAdmin: boolean }) { ) } +interface URLParams { + provider: string +} + function ActivationRequiredSelfHosted() { + const { provider } = useParams() const { data } = useSelfHostedCurrentUser() - const { data: selfHostedSeats } = useSelfHostedSeatsConfig() + const { data: selfHostedSeats } = useSuspenseQueryV5( + SelfHostedSeatsConfigQueryOpts({ provider }) + ) const hasSelfHostedSeats = selfHostedSeats?.seatsUsed && diff --git a/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx b/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx index 9165a1effd..93640024e0 100644 --- a/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx +++ b/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.test.tsx @@ -1,21 +1,36 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { + QueryClientProvider as QueryClientProviderV5, + QueryClient as QueryClientV5, +} from '@tanstack/react-queryV5' import { render, screen, waitFor } from '@testing-library/react' import { graphql, http, HttpResponse } from 'msw' import { setupServer } from 'msw/node' +import { Suspense } from 'react' import { MemoryRouter, Route } from 'react-router-dom' import ActivationRequiredSelfHosted from './ActivationRequiredSelfHosted' const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: false, - }, - }, + defaultOptions: { queries: { retry: false } }, +}) +const queryClientV5 = new QueryClientV5({ + defaultOptions: { queries: { retry: false } }, }) -const server = setupServer() +const wrapper: React.FC = ({ children }) => ( + + + + + Loading}>{children} + + + + +) +const server = setupServer() beforeAll(() => { server.listen({ onUnhandledRequest: 'warn' }) console.error = () => {} @@ -23,6 +38,7 @@ beforeAll(() => { afterEach(() => { queryClient.clear() + queryClientV5.clear() server.resetHandlers() vi.clearAllMocks() }) @@ -31,14 +47,6 @@ afterAll(() => { server.close() }) -const wrapper: React.FC = ({ children }) => ( - - - {children} - - -) - describe('ActivationRequiredSelfHosted', () => { function setup(isAdmin: boolean, seatsUsed: number, seatsLimit: number) { server.use( diff --git a/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx b/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx index 9bcd83587f..b9f4ee3a80 100644 --- a/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx +++ b/src/pages/RepoPage/CoverageOnboarding/ActivationBanner/ActivationRequiredSelfHosted/ActivationRequiredSelfHosted.tsx @@ -1,7 +1,8 @@ -import { - useSelfHostedCurrentUser, - useSelfHostedSeatsConfig, -} from 'services/selfHosted' +import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5' +import { useParams } from 'react-router' + +import { useSelfHostedCurrentUser } from 'services/selfHosted' +import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts' import A from 'ui/A' import Banner from 'ui/Banner' import BannerContent from 'ui/Banner/BannerContent' @@ -60,9 +61,16 @@ function SeatsAvailable({ isAdmin }: { isAdmin: boolean }) { ) } +interface URLParams { + provider: string +} + function ActivationRequiredSelfHosted() { + const { provider } = useParams() const { data } = useSelfHostedCurrentUser() - const { data: selfHostedSeats } = useSelfHostedSeatsConfig() + const { data: selfHostedSeats } = useSuspenseQueryV5( + SelfHostedSeatsConfigQueryOpts({ provider }) + ) const hasSelfHostedSeats = selfHostedSeats?.seatsUsed && diff --git a/src/services/selfHosted/useSelfHostedSeatsConfig.test.tsx b/src/services/selfHosted/SelfHostedSeatsConfigQueryOpts.test.tsx similarity index 57% rename from src/services/selfHosted/useSelfHostedSeatsConfig.test.tsx rename to src/services/selfHosted/SelfHostedSeatsConfigQueryOpts.test.tsx index 91bc9aedb5..6b8e441b4e 100644 --- a/src/services/selfHosted/useSelfHostedSeatsConfig.test.tsx +++ b/src/services/selfHosted/SelfHostedSeatsConfigQueryOpts.test.tsx @@ -1,11 +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 { PropsWithChildren } from 'react' -import { MemoryRouter, Route } from 'react-router-dom' -import { useSelfHostedSeatsConfig } from './useSelfHostedSeatsConfig' +import { SelfHostedSeatsConfigQueryOpts } from './SelfHostedSeatsConfigQueryOpts' const mockData = { config: { @@ -14,15 +16,13 @@ const mockData = { }, } -const queryClient = new QueryClient({ +const queryClientV5 = new QueryClientV5({ defaultOptions: { queries: { retry: false } }, }) -const wrapper: React.FC = ({ children }) => ( - - - {children} - - +const wrapper: React.FC = ({ children }) => ( + + {children} + ) const server = setupServer() @@ -31,8 +31,8 @@ beforeAll(() => { }) beforeEach(() => { + queryClientV5.clear() server.resetHandlers() - queryClient.clear() }) afterAll(() => { @@ -51,9 +51,10 @@ describe('useSelfHostedSeatsConfig', () => { describe('when called', () => { it('returns data', async () => { setup() - const { result } = renderHook(() => useSelfHostedSeatsConfig(), { - wrapper, - }) + const { result } = renderHook( + () => useQueryV5(SelfHostedSeatsConfigQueryOpts({ provider: 'gh' })), + { wrapper } + ) await waitFor(() => expect(result.current.data).toStrictEqual({ diff --git a/src/services/selfHosted/useSelfHostedSeatsConfig.ts b/src/services/selfHosted/SelfHostedSeatsConfigQueryOpts.ts similarity index 53% rename from src/services/selfHosted/useSelfHostedSeatsConfig.ts rename to src/services/selfHosted/SelfHostedSeatsConfigQueryOpts.ts index 0a467ec238..d27b565b39 100644 --- a/src/services/selfHosted/useSelfHostedSeatsConfig.ts +++ b/src/services/selfHosted/SelfHostedSeatsConfigQueryOpts.ts @@ -1,9 +1,8 @@ -import { useQuery } from '@tanstack/react-query' -import { useParams } from 'react-router-dom' +import { queryOptions as queryOptionsV5 } from '@tanstack/react-queryV5' import { z } from 'zod' import Api from 'shared/api' -import { NetworkErrorObject, rejectNetworkError } from 'shared/api/helpers' +import { rejectNetworkError } from 'shared/api/helpers' export const SeatsSchema = z .object({ @@ -22,18 +21,17 @@ query Seats { seatsUsed seatsLimit } -} -` +}` -interface URLParams { +interface SelfHostedSeatsConfigQueryArgs { provider: string } -export const useSelfHostedSeatsConfig = (options = {}) => { - const { provider } = useParams() - - return useQuery({ - queryKey: ['Seats', provider, query], +export const SelfHostedSeatsConfigQueryOpts = ({ + provider, +}: SelfHostedSeatsConfigQueryArgs) => { + return queryOptionsV5({ + queryKey: ['Seats', provider], queryFn: ({ signal }) => Api.graphql({ provider, query, signal }).then((res) => { const parsedRes = SeatsSchema.safeParse(res?.data) @@ -42,13 +40,12 @@ export const useSelfHostedSeatsConfig = (options = {}) => { return rejectNetworkError({ status: 404, data: {}, - dev: 'useSelfHostedSeatsConfig - 404 schema parsing failed', - } satisfies NetworkErrorObject) + dev: 'SelfHostedSeatsConfigQueryOpts - 404 schema parsing failed', + error: parsedRes.error, + }) } - return parsedRes?.data ?? null + return parsedRes?.data?.config ?? null }), - select: (data) => data?.config, - ...options, }) } diff --git a/src/services/selfHosted/index.ts b/src/services/selfHosted/index.ts index a7a9941144..e6776e5324 100644 --- a/src/services/selfHosted/index.ts +++ b/src/services/selfHosted/index.ts @@ -1,3 +1,2 @@ export * from './useSelfHostedCurrentUser' -export * from './useSelfHostedSeatsConfig' export * from './useSelfHostedSeatsAndLicense'