import z from 'zod'
const envSchema = z.object({
REACT_APP_FEATURE_VAC_ASK: z.string(),
REACT_APP_FEATURE_RECORDS: z.string(),
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
})
const windowSchema = z.object({
SOMETHING_COOL: z.string()
})
export const ENV = envSchema.parse(process.env)
export const WINDOW = windowSchema.parse(window)
vitest에서 사용할 수 있는 사용자 지정 assertion을 추가하기.
import { expect } from 'vitest'
import type { ZodTypeAny } from 'zod'
expect.extend({
/**
* @param received 테스트할 Response 객체
* @param schema 검증할 Zod 스키마
*/
async toMatchSchema(received: Response, schema: ZodTypeAny) {
const response = await received.json()
const result = await schema.safeParseAsync(response)
return {
message: () => '',
pass: result.success,
} satisfies ExpectationResult
},
})
vitest.d.ts
에 기본 인터페이스를 확장하기.
import type { ZodTypeAny } from 'zod'
interface CustomMatchers<R = unknown> {
toMatchSchema(schema: ZodTypeAny): Promise<R>
}
todoResponse
의 응답 데이터가 todoSchema
에 정의된 Zod 스키마와 일치하는지 확인한다.
test('todo', async () => {
expect(todoResponse.ok).toBeTruthy()
expect(todoResponse).toMatchSchema(todoSchema)
})
https://www.jacobparis.com/content/zod-search-params-remix
- 검색 매개변수별로 데이터 유효성 검증
useSearchParams
와Zod
를 활용해 모든 검색 매개변수를 병합하고 유효성 검증
import { useMemo } from 'react'
import { useSearchParams } from 'react-router-dom'
import { z } from 'zod'
const CombinedSchema = PaginationSchema.merge(FilterSchema)
.merge(SortSchema)
.merge(SearchSchema)
.partial()
export function useSearchParamsWithSchema() {
const [searchParams, setSearchParams] = useSearchParams()
const parsedParams = useMemo(() => {
// searchParams를 객체로 변환
const paramsObject = Object.fromEntries(searchParams.entries())
// 결합된 스키마로 유효성 검사 및 파싱
const result = CombinedSchema.safeParse(paramsObject)
if (result.success) {
return result.data
}
console.error(result.error)
return {}
}, [searchParams])
/**
* 새로운 검색 매개변수로 업데이트하는 함수입니다.
*
* 1. 현재 검색 매개변수의 복사본을 생성합니다.
* 2. 새로운 매개변수를 순회하며 값을 설정하거나 삭제합니다.
* 3. 최종적으로 업데이트된 매개변수를 state에 설정합니다.
*/
const updateSearchParams = (newParams: Record<string, string>) => {
const updatedParams = new URLSearchParams(searchParams)
Object.entries(newParams).forEach(([key, value]) => {
if (value) {
// 업데이트된 매개변수로 상태 갱신
updatedParams.set(key, value)
} else {
// 값이 없으면 삭제
updatedParams.delete(key)
}
})
// 업데이트된 매개변수로 상태 갱신
setSearchParams(updatedParams)
}
return {
parsedParams,
updateSearchParams,
}
}