Skip to content

Commit 0e34c4d

Browse files
authored
chore: Migrate useSelfHostedSeatsConfig to TS Query V5 (#3580)
1 parent c87e433 commit 0e34c4d

File tree

14 files changed

+299
-189
lines changed

14 files changed

+299
-189
lines changed

src/layouts/Header/components/SeatDetails/SeatDetails.test.tsx

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
2+
import {
3+
QueryClientProvider as QueryClientProviderV5,
4+
QueryClient as QueryClientV5,
5+
} from '@tanstack/react-queryV5'
26
import { render, screen } from '@testing-library/react'
37
import { graphql, HttpResponse } from 'msw'
48
import { setupServer } from 'msw/node'
9+
import { Suspense } from 'react'
510
import { MemoryRouter, Route } from 'react-router-dom'
611

712
import SeatDetails from './SeatDetails'
@@ -14,37 +19,43 @@ const mockData = {
1419
}
1520

1621
const mockUndefinedSeats = {
17-
config: {},
22+
config: null,
1823
}
1924

25+
const queryClient = new QueryClient({
26+
defaultOptions: { queries: { retry: false } },
27+
})
28+
const queryClientV5 = new QueryClientV5({
29+
defaultOptions: { queries: { retry: false } },
30+
})
31+
2032
const wrapper: ({
2133
initialEntries,
2234
}: {
2335
initialEntries?: string
2436
}) => React.FC<React.PropsWithChildren> =
2537
({ initialEntries = '/gh' }) =>
2638
({ children }) => (
27-
<QueryClientProvider client={queryClient}>
28-
<MemoryRouter initialEntries={[initialEntries]}>
29-
<Route path="/:provider" exact>
30-
{children}
31-
</Route>
32-
</MemoryRouter>
33-
</QueryClientProvider>
39+
<QueryClientProviderV5 client={queryClientV5}>
40+
<QueryClientProvider client={queryClient}>
41+
<MemoryRouter initialEntries={[initialEntries]}>
42+
<Route path="/:provider" exact>
43+
<Suspense fallback={<div>Loading</div>}>{children}</Suspense>
44+
</Route>
45+
</MemoryRouter>
46+
</QueryClientProvider>
47+
</QueryClientProviderV5>
3448
)
3549

36-
const queryClient = new QueryClient({
37-
defaultOptions: { queries: { retry: false } },
38-
})
39-
4050
const server = setupServer()
4151
beforeAll(() => {
4252
server.listen()
4353
})
4454

4555
afterEach(() => {
46-
server.resetHandlers()
4756
queryClient.clear()
57+
queryClientV5.clear()
58+
server.resetHandlers()
4859
})
4960

5061
afterAll(() => {
@@ -62,12 +73,10 @@ describe('SeatDetails', () => {
6273

6374
describe('renders component', () => {
6475
describe('values are defined', () => {
65-
beforeEach(() => {
66-
setup({})
67-
})
68-
6976
it('displays the number of active seats', async () => {
77+
setup({})
7078
render(<SeatDetails />, { wrapper: wrapper({}) })
79+
7180
const number = await screen.findByText('5')
7281
expect(number).toBeInTheDocument()
7382

@@ -76,6 +85,7 @@ describe('SeatDetails', () => {
7685
})
7786

7887
it('displays the number of total seats', async () => {
88+
setup({})
7989
render(<SeatDetails />, { wrapper: wrapper({}) })
8090

8191
const number = await screen.findByText('10')

src/layouts/Header/components/SeatDetails/SeatDetails.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1-
import { useSelfHostedSeatsConfig } from 'services/selfHosted'
1+
import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5'
2+
import { useParams } from 'react-router'
3+
4+
import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts'
5+
6+
interface URLParams {
7+
provider: string
8+
}
29

310
function SeatDetails() {
4-
const { data: selfHostedSeats } = useSelfHostedSeatsConfig()
11+
const { provider } = useParams<URLParams>()
12+
const { data: selfHostedSeats } = useSuspenseQueryV5(
13+
SelfHostedSeatsConfigQueryOpts({ provider })
14+
)
515

616
if (!selfHostedSeats?.seatsUsed || !selfHostedSeats?.seatsLimit) {
717
return <p>Unable to get seat usage information</p>

src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.jsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { useQueryClient } from '@tanstack/react-query'
2+
import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5'
3+
import { useParams } from 'react-router'
24

3-
import {
4-
useSelfHostedCurrentUser,
5-
useSelfHostedSeatsConfig,
6-
} from 'services/selfHosted'
5+
import { useSelfHostedCurrentUser } from 'services/selfHosted'
6+
import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts'
77
import A from 'ui/A'
88
import Banner from 'ui/Banner'
99
import BannerContent from 'ui/Banner/BannerContent'
@@ -39,9 +39,12 @@ function canChangeActivation({ seatConfig, currentUser }) {
3939
}
4040

4141
function ActivationBanner() {
42+
const { provider } = useParams()
4243
const queryClient = useQueryClient()
4344
const { data: currentUser } = useSelfHostedCurrentUser()
44-
const { data: seatConfig } = useSelfHostedSeatsConfig()
45+
const { data: seatConfig } = useSuspenseQueryV5(
46+
SelfHostedSeatsConfigQueryOpts({ provider })
47+
)
4548

4649
const { canChange, displaySeatMsg } = canChangeActivation({
4750
seatConfig,

src/pages/AccountSettings/tabs/Profile/ActivationBanner/ActivationBanner.test.jsx

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
2+
import {
3+
QueryClientProvider as QueryClientProviderV5,
4+
QueryClient as QueryClientV5,
5+
} from '@tanstack/react-queryV5'
26
import { render, screen } from '@testing-library/react'
37
import userEvent from '@testing-library/user-event'
48
import { graphql, http, HttpResponse } from 'msw'
59
import { setupServer } from 'msw/node'
6-
import { Route } from 'react-router-dom'
7-
import { MemoryRouter } from 'react-router-dom/cjs/react-router-dom.min'
10+
import { Suspense } from 'react'
11+
import { MemoryRouter, Route } from 'react-router-dom'
812

913
import ActivationBanner from './ActivationBanner'
1014

@@ -27,27 +31,38 @@ const mockUserData = {
2731
const queryClient = new QueryClient({
2832
defaultOptions: { queries: { retry: false } },
2933
})
30-
const server = setupServer()
3134

35+
const queryClientV5 = new QueryClientV5({
36+
defaultOptions: { queries: { retry: false } },
37+
})
38+
39+
const wrapper = ({ children }) => (
40+
<QueryClientProviderV5 client={queryClientV5}>
41+
<QueryClientProvider client={queryClient}>
42+
<MemoryRouter initialEntries={['/gh']}>
43+
<Route path="/:provider">
44+
<Suspense fallback={<div>Loading</div>}>{children}</Suspense>
45+
</Route>
46+
</MemoryRouter>
47+
</QueryClientProvider>
48+
</QueryClientProviderV5>
49+
)
50+
51+
const server = setupServer()
3252
beforeAll(() => {
3353
server.listen()
3454
})
35-
beforeEach(() => {
55+
56+
afterEach(() => {
3657
queryClient.clear()
58+
queryClientV5.clear()
3759
server.resetHandlers()
3860
})
61+
3962
afterAll(() => {
4063
server.close()
4164
})
4265

43-
const wrapper = ({ children }) => (
44-
<QueryClientProvider client={queryClient}>
45-
<MemoryRouter initialEntries={['/gh']}>
46-
<Route path="/:provider">{children}</Route>
47-
</MemoryRouter>
48-
</QueryClientProvider>
49-
)
50-
5166
describe('ActivationBanner', () => {
5267
function setup(
5368
{ overrideUserData = {}, overrideSeatData = {} } = {
@@ -58,14 +73,14 @@ describe('ActivationBanner', () => {
5873
const user = userEvent.setup()
5974

6075
let restUsersCurrent = { ...mockUserData, ...overrideUserData }
61-
const querySeats = { ...mockSeatData, ...overrideSeatData }
76+
const querySeats = { ...mockSeatData.config, ...overrideSeatData }
6277

6378
server.use(
6479
http.get('/internal/users/current', () => {
6580
return HttpResponse.json(restUsersCurrent)
6681
}),
6782
graphql.query('Seats', () => {
68-
return HttpResponse.json({ data: querySeats })
83+
return HttpResponse.json({ data: { config: querySeats } })
6984
}),
7085
http.patch('/internal/users/current', async (info) => {
7186
const { activated } = await info.request.json()
@@ -83,9 +98,8 @@ describe('ActivationBanner', () => {
8398
}
8499

85100
describe('rendering banner header', () => {
86-
beforeEach(() => setup())
87-
88101
it('renders header content', async () => {
102+
setup()
89103
render(<ActivationBanner />, { wrapper })
90104

91105
const heading = await screen.findByText('Activation Status')
@@ -95,9 +109,8 @@ describe('ActivationBanner', () => {
95109

96110
describe('rendering banner content', () => {
97111
describe('user is activated', () => {
98-
beforeEach(() => setup({ overrideUserData: { activated: true } }))
99-
100112
it('displays user is activated', async () => {
113+
setup({ overrideUserData: { activated: true } })
101114
render(<ActivationBanner />, { wrapper })
102115

103116
const activated = await screen.findByText('You are currently activated')
@@ -107,9 +120,8 @@ describe('ActivationBanner', () => {
107120

108121
describe('user is not activated', () => {
109122
describe('org has free seats', () => {
110-
beforeEach(() => setup({ overrideSeatData: { activated: false } }))
111-
112123
it('displays user is not activated', async () => {
124+
setup({ overrideSeatData: { activated: false } })
113125
render(<ActivationBanner />, { wrapper })
114126

115127
const activated = await screen.findByText(
@@ -120,14 +132,11 @@ describe('ActivationBanner', () => {
120132
})
121133

122134
describe('org does not have free seats', () => {
123-
beforeEach(() =>
135+
it('displays org out of seat message', async () => {
124136
setup({
125137
overrideSeatData: { seatsUsed: 10, seatsLimit: 10 },
126138
overrideUserData: { activated: false },
127139
})
128-
)
129-
130-
it('displays org out of seat message', async () => {
131140
render(<ActivationBanner />, { wrapper })
132141

133142
const noSeatMsg = await screen.findByText(
@@ -137,6 +146,10 @@ describe('ActivationBanner', () => {
137146
})
138147

139148
it('sets toggle to disabled', async () => {
149+
setup({
150+
overrideSeatData: { seatsUsed: 10, seatsLimit: 10 },
151+
overrideUserData: { activated: false },
152+
})
140153
render(<ActivationBanner />, { wrapper })
141154

142155
const button = await screen.findByRole('button')
Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { useMutation } from '@tanstack/react-query'
2+
import { useQueryClient as useQueryClientV5 } from '@tanstack/react-queryV5'
23
import { useParams } from 'react-router-dom'
34

5+
import { SelfHostedSeatsConfigQueryOpts } from 'services/selfHosted/SelfHostedSeatsConfigQueryOpts'
46
import Api from 'shared/api'
57

68
export const useSelfActivationMutation = ({ queryClient, canChange }) => {
79
const { provider } = useParams()
10+
const queryClientV5 = useQueryClientV5()
811

912
return useMutation({
1013
mutationFn: (activated) => {
@@ -18,43 +21,51 @@ export const useSelfActivationMutation = ({ queryClient, canChange }) => {
1821
},
1922
onMutate: async (activated) => {
2023
await queryClient.cancelQueries(['SelfHostedCurrentUser'])
21-
await queryClient.cancelQueries(['Seats'])
24+
await queryClientV5.cancelQueries({
25+
queryKey: SelfHostedSeatsConfigQueryOpts({ provider }).queryKey,
26+
})
2227

2328
const prevUser = queryClient.getQueryData(['SelfHostedCurrentUser'])
24-
const prevSeat = queryClient.getQueryData(['Seats'])
29+
const prevSeat = queryClientV5.getQueryData(
30+
SelfHostedSeatsConfigQueryOpts({ provider }).queryKey
31+
)
2532

2633
if (canChange) {
2734
queryClient.setQueryData(['SelfHostedCurrentUser'], (user) => ({
2835
...user,
2936
activated,
3037
}))
3138

32-
queryClient.setQueryData(['Seats'], (seats) => {
33-
const seatsUsed = seats?.data?.config?.seatsUsed
34-
35-
return {
36-
data: {
37-
config: {
38-
...seats?.data?.config,
39-
seatsUsed: activated ? seatsUsed + 1 : seatsUsed - 1,
39+
queryClientV5.setQueryData(
40+
SelfHostedSeatsConfigQueryOpts({ provider }).queryKey,
41+
(seats) => {
42+
const seatsUsed = seats?.data?.config?.seatsUsed
43+
return {
44+
data: {
45+
config: {
46+
...seats?.data?.config,
47+
seatsUsed: activated ? seatsUsed + 1 : seatsUsed - 1,
48+
},
4049
},
41-
},
50+
}
4251
}
43-
})
52+
)
4453
}
4554

46-
return {
47-
prevUser,
48-
prevSeat,
49-
}
55+
return { prevUser, prevSeat }
5056
},
5157
onError: (_err, _activated, context) => {
5258
queryClient.setQueryData(['SelfHostedCurrentUser'], context.prevUser)
53-
queryClient.setQueryData(['Seats'], context.prevSeat)
59+
queryClientV5.setQueryData(
60+
SelfHostedSeatsConfigQueryOpts({ provider }).queryKey,
61+
context.prevSeat
62+
)
5463
},
5564
onSettled: () => {
5665
queryClient.invalidateQueries(['SelfHostedCurrentUser'])
57-
queryClient.invalidateQueries(['Seats'])
66+
queryClientV5.invalidateQueries(
67+
SelfHostedSeatsConfigQueryOpts({ provider }).queryKey
68+
)
5869
},
5970
})
6071
}

0 commit comments

Comments
 (0)