Skip to content

Commit

Permalink
Merge branch 'main' into fix-scroll-to-line-with-dropdowns
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholas-codecov authored Apr 29, 2024
2 parents 1d8f111 + 782e9b4 commit 66caba8
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 41 deletions.
49 changes: 36 additions & 13 deletions src/App.spec.jsx → src/App.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, screen, waitFor } from '@testing-library/react'
import { graphql, rest } from 'msw'
import { setupServer } from 'msw/node'
import React from 'react'
import { MemoryRouter, Route } from 'react-router-dom'

import config from 'config'
Expand Down Expand Up @@ -43,9 +44,9 @@ const internalUser = {
integrationId: null,
name: null,
ownerid: 123,
service: 'github',
service: 'cool-service',
stats: null,
username: 'codecov',
username: 'cool-guy',
},
],
termsAgreement: true,
Expand Down Expand Up @@ -73,9 +74,9 @@ const queryClient = new QueryClient({
})

const server = setupServer()
let testLocation
let testLocation: any
const wrapper =
(initialEntries = []) =>
(initialEntries = ['']): React.FC<React.PropsWithChildren> =>
({ children }) =>
(
<QueryClientProvider client={queryClient}>
Expand All @@ -94,9 +95,10 @@ const wrapper =

beforeAll(() => {
server.listen({ onUnhandledRequest: 'warn' })
console.error = () => {}
})

afterEach(() => {
beforeEach(() => {
config.IS_SELF_HOSTED = false
queryClient.clear()
server.resetHandlers()
Expand All @@ -107,10 +109,20 @@ afterAll(() => {
})

describe('App', () => {
function setup(hasLoggedInUser = true) {
function setup({
hasLoggedInUser,
hasSession,
}: {
hasLoggedInUser?: boolean
hasSession?: boolean
}) {
server.use(
rest.get('/internal/user', (_, res, ctx) => {
return res(ctx.status(200), ctx.json(internalUser))
if (hasSession) {
return res(ctx.status(200), ctx.json(internalUser))
} else {
return res(ctx.status(200), ctx.json({}))
}
}),
graphql.query('DetailOwner', (_, res, ctx) =>
res(ctx.status(200), ctx.data({ owner: 'codecov' }))
Expand Down Expand Up @@ -319,17 +331,18 @@ describe('App', () => {
({ testLabel, pathname, expected }) => {
beforeEach(() => {
config.IS_SELF_HOSTED = false
setup()
setup({ hasLoggedInUser: true, hasSession: true })
})

it(`renders the ${testLabel} page`, async () => {
render(<App />, { wrapper: wrapper([pathname]) })

await waitFor(
() => expect(testLocation.pathname).toBe(expected.location),
expect(testLocation.search).toBe(expected.search)
await waitFor(() =>
expect(testLocation.pathname).toBe(expected.location)
)

await waitFor(() => expect(testLocation.search).toBe(expected.search))

const page = await screen.findByText(expected.page)
expect(page).toBeInTheDocument()
})
Expand Down Expand Up @@ -504,7 +517,7 @@ describe('App', () => {
({ testLabel, pathname, expected }) => {
beforeEach(() => {
config.IS_SELF_HOSTED = true
setup()
setup({ hasLoggedInUser: true, hasSession: true })
})

it(`renders the ${testLabel} page`, async () => {
Expand All @@ -521,9 +534,19 @@ describe('App', () => {

describe('user not logged in', () => {
it('redirects to login', async () => {
setup(false)
setup({ hasLoggedInUser: true, hasSession: false })
render(<App />, { wrapper: wrapper(['*']) })
await waitFor(() => expect(testLocation.pathname).toBe('/login'))
})
})
describe('user has session, not logged in', () => {
it('redirects to session default', async () => {
setup({ hasLoggedInUser: false, hasSession: true })

render(<App />, { wrapper: wrapper(['/blah']) })
await waitFor(() =>
expect(testLocation.pathname).toBe('/cool-service/cool-guy')
)
})
})
})
34 changes: 23 additions & 11 deletions src/App.jsx → src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import LoginLayout from 'layouts/LoginLayout'
import { useLocationParams } from 'services/navigation'
import { ToastNotificationProvider } from 'services/toastNotification'
import { useUTM } from 'services/tracking/utm'
import { useUser } from 'services/user'
import { useInternalUser, useUser } from 'services/user'
import { isProvider } from 'shared/api/helpers'

const AccountSettings = lazy(() => import('./pages/AccountSettings'))
const AdminSettings = lazy(() => import('./pages/AdminSettings'))
Expand All @@ -28,21 +29,32 @@ const PullRequestPage = lazy(() => import('./pages/PullRequestPage'))
const RepoPage = lazy(() => import('./pages/RepoPage'))
const SyncProviderPage = lazy(() => import('./pages/SyncProviderPage'))

interface URLParams {
provider: string
}

const HomePageRedirect = () => {
const { provider } = useParams()
const { provider } = useParams<URLParams>()
const { data: currentUser } = useUser()
const { data: internalUser } = useInternalUser({})
const { params } = useLocationParams()

if (!provider || !currentUser) {
return <Redirect to="/login" />
let redirectURL = '/login'

if (internalUser && internalUser.owners) {
redirectURL = `/${internalUser.owners[0]?.service}/${internalUser.owners[0]?.username}`
}

const defaultOrg =
currentUser.owner?.defaultOrgUsername ?? currentUser.user?.username
let redirectURL = `/${provider}/${defaultOrg}`
const { setup_action: setupAction } = params
if (setupAction) {
redirectURL += `?setup_action=${setupAction}`
if (provider && isProvider(provider) && currentUser) {
const defaultOrg =
currentUser.owner?.defaultOrgUsername ?? currentUser.user?.username
redirectURL = `/${provider}/${defaultOrg}`

// @ts-expect-error useLocationParams needs to be typed
const { setup_action: setupAction } = params
if (setupAction) {
redirectURL += `?setup_action=${setupAction}`
}
}

return <Redirect to={redirectURL} />
Expand Down Expand Up @@ -148,7 +160,7 @@ const MainAppRoutes = () => (
<EnterpriseLandingPage />
</EnterpriseLoginLayout>
) : (
<Redirect to="/login" />
<HomePageRedirect />
)}
</SentryRoute>
<SentryRoute path="*">
Expand Down
15 changes: 14 additions & 1 deletion src/services/user/useInternalUser.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ afterAll(() => {
})

describe('useInternalUser', () => {
function setup() {
function setup(hasError = false) {
server.use(
rest.get('/internal/user', (req, res, ctx) => {
if (hasError) {
return res(ctx.status(400), ctx.json({}))
}
return res(
ctx.status(200),
ctx.json({
Expand Down Expand Up @@ -60,4 +63,14 @@ describe('useInternalUser', () => {
)
})
})

describe('when hook call errors', () => {
it('returns empty object', async () => {
setup(true)

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

await waitFor(() => expect(result.current.data).toStrictEqual({}))
})
})
})
37 changes: 21 additions & 16 deletions src/services/user/useInternalUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,27 @@ export interface UseInternalUserArgs {
export const useInternalUser = (opts: UseInternalUserArgs) =>
useQuery({
queryKey: ['InternalUser'],
queryFn: ({ signal }) => {
return Api.get({
path: '/user',
signal,
}).then((res) => {
const parsedData = InternalUserSchema.safeParse(res)

if (!parsedData.success) {
return Promise.reject({
status: 404,
data: null,
})
}

return parsedData.data
})
queryFn: async ({ signal }) => {
let response
try {
response = await Api.get({
path: '/user',
signal,
})
} catch (e) {
return {} as InternalUserData
}

const parsedData = InternalUserSchema.safeParse(response)

if (!parsedData.success) {
return Promise.reject({
status: 404,
data: null,
})
}

return parsedData.data
},
...(!!opts && opts),
})

0 comments on commit 66caba8

Please sign in to comment.