From fc0d687b0d7dddf8d65e0525b023a323ad2bc660 Mon Sep 17 00:00:00 2001 From: Suejung Shin Date: Wed, 6 Nov 2024 01:35:54 -0800 Subject: [PATCH] add zod schemas --- .../charts/useLegacyRepoCoverage.test.tsx | 77 ------------------- src/services/charts/useLegacyRepoCoverage.ts | 58 -------------- .../useRegenerateOrgUploadToken.test.tsx | 6 +- .../useRegenerateOrgUploadToken.ts | 48 +++++++++--- .../branch/file/usePrefetchBranchFileEntry.ts | 2 - src/services/user/useOwner.ts | 25 ++++-- 6 files changed, 57 insertions(+), 159 deletions(-) delete mode 100644 src/services/charts/useLegacyRepoCoverage.test.tsx delete mode 100644 src/services/charts/useLegacyRepoCoverage.ts diff --git a/src/services/charts/useLegacyRepoCoverage.test.tsx b/src/services/charts/useLegacyRepoCoverage.test.tsx deleted file mode 100644 index 28a065b4b8..0000000000 --- a/src/services/charts/useLegacyRepoCoverage.test.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import { renderHook, waitFor } from '@testing-library/react' -import { setupServer } from 'msw/node' - -import { repoCoverageHandler } from './mocks' - -import { useLegacyRepoCoverage } from './index' - -const queryClient = new QueryClient({ - defaultOptions: { queries: { retry: false } }, -}) - -const wrapper: React.FC = ({ children }) => ( - {children} -) - -const server = setupServer() - -beforeAll(() => { - server.listen() -}) - -afterEach(() => { - server.resetHandlers() - queryClient.clear() -}) - -afterAll(() => { - server.close() -}) - -const exampleYearlyHookData = { - coverage: [ - { - date: '2020-01-01T00:00:00Z', - totalHits: 41.0, - totalMisses: 4.0, - totalPartials: 0.0, - totalLines: 45.0, - coverage: 91.11, - }, - { - date: '2021-01-01T00:00:00Z', - totalHits: 41.0, - totalMisses: 4.0, - totalPartials: 0.0, - totalLines: 45.0, - coverage: 91.11, - }, - ], -} - -describe('useLegacyRepoCoverage', () => { - beforeEach(() => { - server.use(repoCoverageHandler) - }) - - describe('returns year coverage data', () => { - it('returns chart data', async () => { - const { result } = renderHook( - () => - useLegacyRepoCoverage({ - provider: 'bitbucket', - owner: 'critical role', - query: { groupingUnit: 'yearly' }, - }), - { - wrapper, - } - ) - await waitFor(() => !result.current.isFetching) - await waitFor(() => - expect(result.current.data).toStrictEqual(exampleYearlyHookData) - ) - }) - }) -}) diff --git a/src/services/charts/useLegacyRepoCoverage.ts b/src/services/charts/useLegacyRepoCoverage.ts deleted file mode 100644 index 9fb88adcfb..0000000000 --- a/src/services/charts/useLegacyRepoCoverage.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { QueryOptions, useQuery } from '@tanstack/react-query' - -import Api from 'shared/api' -import { providerToInternalProvider } from 'shared/utils' - -function getRepoCoverage({ - provider, - owner, -}: { - provider: string - owner: string -}) { - const internalProvider = providerToInternalProvider(provider) - return `/charts/${internalProvider}/${owner}/coverage/repository` -} - -function fetchRepoCoverage({ - provider, - owner, - body, - signal, -}: { - provider: string - owner: string - body?: string - signal?: AbortSignal -}) { - const path = getRepoCoverage({ provider, owner }) - return Api.post({ path, provider, body, signal }) -} - -interface UseLegacyRepoCoverageArgs { - provider: string - owner: string - branch?: string - trend?: string - body?: string - opts?: QueryOptions - query?: { - groupingUnit: string - } -} - -export function useLegacyRepoCoverage({ - provider, - owner, - branch, - trend, - body, - opts = {}, -}: UseLegacyRepoCoverageArgs) { - return useQuery({ - queryKey: ['legacyRepo', 'coverage', provider, owner, branch, trend, body], - queryFn: ({ signal }) => - fetchRepoCoverage({ provider, owner, body, signal }), - ...opts, - }) -} diff --git a/src/services/orgUploadToken/useRegenerateOrgUploadToken.test.tsx b/src/services/orgUploadToken/useRegenerateOrgUploadToken.test.tsx index dbfaab63d8..13960e26d4 100644 --- a/src/services/orgUploadToken/useRegenerateOrgUploadToken.test.tsx +++ b/src/services/orgUploadToken/useRegenerateOrgUploadToken.test.tsx @@ -8,10 +8,8 @@ import { MemoryRouter, Route } from 'react-router-dom' import { useRegenerateOrgUploadToken } from './useRegenerateOrgUploadToken' const data = { - data: { - regenerateOrgUploadToken: { - orgUploadToken: 'new token', - }, + regenerateOrgUploadToken: { + orgUploadToken: 'new token', }, } diff --git a/src/services/orgUploadToken/useRegenerateOrgUploadToken.ts b/src/services/orgUploadToken/useRegenerateOrgUploadToken.ts index 72a4350055..4641b277f9 100644 --- a/src/services/orgUploadToken/useRegenerateOrgUploadToken.ts +++ b/src/services/orgUploadToken/useRegenerateOrgUploadToken.ts @@ -1,24 +1,41 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { useParams } from 'react-router-dom' +import { z } from 'zod' import Api from 'shared/api' +import { NetworkErrorObject } from 'shared/api/helpers' + +const RequestSchema = z.object({ + regenerateOrgUploadToken: z + .object({ + orgUploadToken: z.string().nullish(), + error: z + .union([ + z.object({ + __typename: z.literal('UnauthorizedError'), + message: z.string(), + }), + z.object({ + __typename: z.literal('ValidationError'), + message: z.string(), + }), + z.object({ + __typename: z.literal('UnauthenticatedError'), + message: z.string(), + }), + ]) + .nullish(), + }) + .nullable(), +}) interface URLParams { provider: string owner: string } -interface RegenerateOrgUploadTokenOutput { - regenerateOrgUploadToken?: { - orgUploadToken?: string - error?: { - __typename?: string - } - } -} - export function useRegenerateOrgUploadToken( - { onSuccess = (data: RegenerateOrgUploadTokenOutput) => {} } = { + { onSuccess = (data: z.infer) => {} } = { onSuccess: () => {}, } ) { @@ -46,7 +63,16 @@ export function useRegenerateOrgUploadToken( mutationPath: 'regenerateOrgUploadToken', }) - return data + const parsedRes = RequestSchema.safeParse(data.data) + if (!parsedRes.success) { + return Promise.reject({ + status: 404, + data: {}, + dev: 'useRegenerateOrgUploadToken - 404 schema parsing failed', + } satisfies NetworkErrorObject) + } + + return parsedRes }, useErrorBoundary: true, onSuccess: ({ data }) => { diff --git a/src/services/pathContents/branch/file/usePrefetchBranchFileEntry.ts b/src/services/pathContents/branch/file/usePrefetchBranchFileEntry.ts index 00d75392e3..529643217c 100644 --- a/src/services/pathContents/branch/file/usePrefetchBranchFileEntry.ts +++ b/src/services/pathContents/branch/file/usePrefetchBranchFileEntry.ts @@ -16,12 +16,10 @@ export function usePrefetchBranchFileEntry({ branch, path, flags = [], - options = {}, }: { branch: string path: string flags?: string[] - options?: Record }) { const { provider, owner, repo } = useParams() const queryClient = useQueryClient() diff --git a/src/services/user/useOwner.ts b/src/services/user/useOwner.ts index d94cd68dc3..8941e654ca 100644 --- a/src/services/user/useOwner.ts +++ b/src/services/user/useOwner.ts @@ -1,19 +1,21 @@ import { useQuery } from '@tanstack/react-query' import { useParams } from 'react-router-dom' +import { z } from 'zod' import Api from 'shared/api' +import { NetworkErrorObject } from 'shared/api/helpers' interface URLParams { provider: string } -export interface DetailOwnerSchema { - ownerid?: string - username?: string - avatarUrl?: string - isCurrentUserPartOfOrg?: boolean - isAdmin?: boolean -} +export const DetailOwnerSchema = z.object({ + ownerid: z.string().nullish(), + username: z.string().nullish(), + avatarUrl: z.string().nullish(), + isCurrentUserPartOfOrg: z.boolean().nullish(), + isAdmin: z.boolean().nullish(), +}) export function useOwner({ username, @@ -45,6 +47,15 @@ export function useOwner({ queryKey: ['owner', variables, provider, query], queryFn: ({ signal }) => Api.graphql({ provider, query, variables, signal }).then((res) => { + const parsedData = DetailOwnerSchema.safeParse(res) + if (!parsedData.success) { + return Promise.reject({ + status: 404, + data: {}, + dev: 'useOwner - 404 failed to parse', + } satisfies NetworkErrorObject) + } + return res?.data?.owner }), ...opts,