Skip to content

Commit

Permalink
ref: Update useSetUploadTokenRequired to TSQ V5 (#3698)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholas-codecov authored Feb 6, 2025
1 parent 5fb62d0 commit 81bfaf2
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 146 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
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 userEvent from '@testing-library/user-event'
import { graphql, HttpResponse } from 'msw'
Expand Down Expand Up @@ -31,30 +35,37 @@ vi.mock('shared/featureFlags', async () => {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
})
const queryClientV5 = new QueryClientV5({
defaultOptions: { queries: { retry: false } },
})

const server = setupServer()
const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
<QueryClientProviderV5 client={queryClientV5}>
<QueryClientProvider client={queryClient}>
<MemoryRouter initialEntries={['/account/gh/codecov/org-upload-token']}>
<Route path="/account/:provider/:owner/org-upload-token">
{children}
</Route>
</MemoryRouter>
</QueryClientProvider>
</QueryClientProviderV5>
)

const server = setupServer()
beforeAll(() => {
console.error = () => {}
server.listen()
})

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

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

const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
<QueryClientProvider client={queryClient}>
<MemoryRouter initialEntries={['/account/gh/codecov/org-upload-token']}>
<Route path="/account/:provider/:owner/org-upload-token">
{children}
</Route>
</MemoryRouter>
</QueryClientProvider>
)
afterAll(() => {
server.close()
})

describe('TokenlessSection', () => {
function setup({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'

import { useUploadTokenRequired } from 'services/uploadTokenRequired'
import { Provider } from 'shared/api/helpers'
import A from 'ui/A'
import { Card } from 'ui/Card'
import { RadioTileGroup } from 'ui/RadioTileGroup'
Expand All @@ -15,7 +16,7 @@ const AUTHENTICATION_OPTIONS = {
} as const

interface UseParams {
provider: string
provider: Provider
owner: string
}

Expand All @@ -25,8 +26,8 @@ const TokenlessSection: React.FC = () => {
data: uploadTokenRequiredData,
isLoading: isUploadTokenRequiredLoading,
} = useUploadTokenRequired({ provider, owner })
const { mutate, isLoading: isSetUploadTokenRequiredLoading } =
useSetUploadTokenRequired()
const { mutate, isPending: isSetUploadTokenRequiredPending } =
useSetUploadTokenRequired({ provider, owner })

const [showModal, setShowModal] = useState<boolean>(false)
const [tokenRequired, setTokenRequiredState] = useState<boolean>(true)
Expand Down Expand Up @@ -108,7 +109,7 @@ const TokenlessSection: React.FC = () => {
setTokenRequiredState(value)
mutate(true)
}}
isLoading={isSetUploadTokenRequiredLoading}
isLoading={isSetUploadTokenRequiredPending}
/>
)}
</Card.Content>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
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 { graphql, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { MemoryRouter, Route } from 'react-router-dom'

import { useSetUploadTokenRequired } from './useSetUploadTokenRequired'

Expand All @@ -18,160 +21,183 @@ vi.mock('services/toastNotification', async () => {
}
})

const server = setupServer()
const mockSuccessResponse = { setUploadTokenRequired: { error: null } }

const mockErrorResponse = {
setUploadTokenRequired: {
error: {
__typename: 'ValidationError',
message: 'Failed to set upload token requirement',
},
},
}
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
})
const queryClientV5 = new QueryClientV5({
defaultOptions: { queries: { retry: false } },
})

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

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

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

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

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

const wrapper: React.FC<React.PropsWithChildren> = ({ children }) => (
<MemoryRouter initialEntries={['/gh/codecov']}>
<Route path="/:provider/:owner">
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</Route>
</MemoryRouter>
)
interface SetupArgs {
isErrorResponse?: boolean
isParsingError?: boolean
}

describe('useSetUploadTokenRequired', () => {
function setup({ isErrorResponse = false }) {
function setup({
isErrorResponse = false,
isParsingError = false,
}: SetupArgs) {
const mockAddToast = vi.fn()
mocks.useAddNotification.mockReturnValue(mockAddToast)

server.use(
graphql.mutation('SetUploadTokenRequired', () => {
if (isErrorResponse) {
return HttpResponse.json({
data: {
setUploadTokenRequired: {
error: {
__typename: 'ValidationError',
message: 'Failed to set upload token requirement',
},
},
},
})
return HttpResponse.json({ data: mockErrorResponse })
} else if (isParsingError) {
return HttpResponse.json({ data: { owner: '' } })
}

return HttpResponse.json({
data: {
setUploadTokenRequired: {
error: null,
},
},
})
return HttpResponse.json({ data: mockSuccessResponse })
})
)

return { mockAddToast }
}

describe('when called', () => {
beforeEach(() => {
setup({})
})

describe('when calling the mutation', () => {
describe('when successful', () => {
it('returns isSuccess true', async () => {
const { result } = renderHook(() => useSetUploadTokenRequired(), {
wrapper,
})

result.current.mutate(true)

await waitFor(() => result.current.isLoading)
await waitFor(() => !result.current.isLoading)

await waitFor(() => expect(result.current.isSuccess).toBeTruthy())
const data = result.current.data
await waitFor(() =>
expect(data).toEqual({
data: {
setUploadTokenRequired: {
error: null,
},
},
})
describe('parsing error occurs', () => {
it('rejects the promise', async () => {
setup({ isParsingError: true })
const { result } = renderHook(
() =>
useSetUploadTokenRequired({ provider: 'gh', owner: 'codecov' }),
{ wrapper }
)
})

it('fires a success toast', async () => {
const { mockAddToast } = setup({})

const { result } = renderHook(() => useSetUploadTokenRequired(), {
wrapper,
let error: any
try {
await result.current.mutateAsync(true)
} catch (e) {
error = e
}

expect(error).toBeDefined()
expect(error).toEqual({
status: 404,
data: {},
dev: 'useSetUploadTokenRequired - 404 failed to parse',
})
})
})

result.current.mutate(true)
describe('onSuccess', () => {
describe('when the mutation is successful', () => {
it('returns isSuccess true', async () => {
setup({})
const { result } = renderHook(
() =>
useSetUploadTokenRequired({ provider: 'gh', owner: 'codecov' }),
{ wrapper }
)

await result.current.mutateAsync(true)

await waitFor(() => expect(result.current.isSuccess).toBeTruthy())
const data = result.current.data
await waitFor(() =>
expect(data).toEqual({ setUploadTokenRequired: { error: null } })
)
})

await waitFor(() => result.current.isLoading)
await waitFor(() => !result.current.isLoading)
it('fires a success toast', async () => {
const { mockAddToast } = setup({})
const { result } = renderHook(
() =>
useSetUploadTokenRequired({ provider: 'gh', owner: 'codecov' }),
{ wrapper }
)

await result.current.mutateAsync(true)

await waitFor(() => expect(result.current.isSuccess).toBeTruthy())
await waitFor(() =>
expect(mockAddToast).toHaveBeenCalledWith({
type: 'success',
text: 'Upload token requirement updated successfully',
disappearAfter: 10000,
})
)
})
})

await waitFor(() => expect(result.current.isSuccess).toBeTruthy())
await waitFor(() =>
expect(mockAddToast).toHaveBeenCalledWith({
type: 'success',
text: 'Upload token requirement updated successfully',
disappearAfter: 10000,
})
)
describe('when the mutation is not successful', () => {
it('fires an error toast', async () => {
const { mockAddToast } = setup({ isErrorResponse: true })
const { result } = renderHook(
() =>
useSetUploadTokenRequired({ provider: 'gh', owner: 'codecov' }),
{ wrapper }
)

await result.current.mutateAsync(true)

await waitFor(() => expect(result.current.isSuccess).toBeTruthy())
await waitFor(() =>
expect(mockAddToast).toHaveBeenCalledWith({
type: 'error',
text: 'Failed to set upload token requirement',
disappearAfter: 10000,
})
)
})
})
})

describe('on error', () => {
describe('onError', () => {
it('fires an error toast', async () => {
const { mockAddToast } = setup({ isErrorResponse: true })

const { result } = renderHook(() => useSetUploadTokenRequired(), {
wrapper,
})

result.current.mutate(true)
const { mockAddToast } = setup({})
const { result } = renderHook(
() =>
useSetUploadTokenRequired({ provider: 'gh', owner: 'codecov' }),
{ wrapper }
)

await waitFor(() => result.current.isLoading)
await waitFor(() => !result.current.isLoading)
result.current.mutate(false)

await waitFor(() => expect(result.current.isSuccess).toBeTruthy())
await waitFor(() => expect(result.current.isSuccess).toBeFalsy())
await waitFor(() =>
expect(mockAddToast).toHaveBeenCalledWith({
expect(mockAddToast).not.toHaveBeenCalledWith({
type: 'error',
text: 'Failed to set upload token requirement',
text: 'An error occurred while updating upload token requirement',
disappearAfter: 10000,
})
)
})
})

it('does not fire a success toast when isSuccess is falsy', async () => {
const { mockAddToast } = setup({})

const { result } = renderHook(() => useSetUploadTokenRequired(), {
wrapper,
})

result.current.mutate(false)
await waitFor(() => expect(result.current.isSuccess).toBeFalsy())

await waitFor(() =>
expect(mockAddToast).not.toHaveBeenCalledWith({
type: 'error',
text: 'An error occurred while updating upload token requirement',
disappearAfter: 10000,
})
)
})
})
})
})
Loading

0 comments on commit 81bfaf2

Please sign in to comment.