Normalize issues schema naming

Use camelCase for the Zod schema objects while keeping shared enum value arrays in CONSTANT_CASE.

Also adds search validation coverage for invalid statuses so the new route schema behavior stays tested.
pull/388/head
Antti Kettunen 2 weeks ago
parent 59eb8b75b0
commit 8bc686afec
No known key found for this signature in database
GPG Key ID: C6B2A3D250359BD7

@ -1,11 +1,11 @@
import { describe, expect, it } from 'vitest';
import { ISSUE_CATEGORY_META } from './-issues.helpers';
import { ISSUE_SEARCH_SCHEMA } from './-issues.types';
import { issueSearchSchema } from './-issues.types';
describe('ISSUE_SEARCH_SCHEMA', () => {
describe('issueSearchSchema', () => {
it('falls back to all for unknown categories', () => {
expect(ISSUE_SEARCH_SCHEMA.parse({ category: 'not_real' })).toEqual({
expect(issueSearchSchema.parse({ category: 'not_real' })).toEqual({
status: 'open',
category: 'all',
issueId: undefined,
@ -13,15 +13,23 @@ describe('ISSUE_SEARCH_SCHEMA', () => {
});
it('preserves known categories', () => {
expect(ISSUE_SEARCH_SCHEMA.parse({ category: 'wrong_metadata' })).toEqual({
expect(issueSearchSchema.parse({ category: 'wrong_metadata' })).toEqual({
status: 'open',
category: 'wrong_metadata',
issueId: undefined,
});
});
it('falls back to open for unknown statuses', () => {
expect(issueSearchSchema.parse({ status: 'not_real' })).toEqual({
status: 'open',
category: 'all',
issueId: undefined,
});
});
it('drops invalid issue ids', () => {
expect(ISSUE_SEARCH_SCHEMA.parse({ issueId: 'abc123' })).toEqual({
expect(issueSearchSchema.parse({ issueId: 'abc123' })).toEqual({
status: 'open',
category: 'all',
issueId: undefined,
@ -29,7 +37,7 @@ describe('ISSUE_SEARCH_SCHEMA', () => {
});
it('normalizes numeric issue ids', () => {
expect(ISSUE_SEARCH_SCHEMA.parse({ issueId: '7' })).toEqual({
expect(issueSearchSchema.parse({ issueId: '7' })).toEqual({
status: 'open',
category: 'all',
issueId: 7,

@ -33,13 +33,13 @@ export const ISSUE_SEARCH_STATUS_VALUES = [
] as const;
export const ISSUE_SEARCH_CATEGORY_VALUES = ['all', ...ISSUE_CATEGORY_VALUES] as const;
export const ISSUE_SEARCH_SCHEMA = z.object({
export const issueSearchSchema = z.object({
status: z.enum(ISSUE_SEARCH_STATUS_VALUES).default('open').catch('open'),
category: z.enum(ISSUE_SEARCH_CATEGORY_VALUES).default('all').catch('all'),
issueId: z.coerce.number().int().positive().optional().catch(undefined),
});
export type IssuesSearch = z.infer<typeof ISSUE_SEARCH_SCHEMA>;
export type IssuesSearch = z.infer<typeof issueSearchSchema>;
export interface IssueTrackRow extends Record<string, unknown> {
bitrate?: string | number;

@ -326,7 +326,7 @@ const DEFAULT_REPORT_ISSUE_VALUES: ReportIssueFormValues = {
title: '',
};
const reportIssueFormBaseSchema = z.object({
const reportIssueFormSchema = z.object({
category: z
.string()
.trim()
@ -336,8 +336,8 @@ const reportIssueFormBaseSchema = z.object({
title: z.string().trim().min(1, 'Please provide a title for the issue'),
});
type ReportIssueFormValues = z.input<typeof reportIssueFormBaseSchema>;
type NormalizedReportIssueFormValues = z.output<typeof reportIssueFormBaseSchema>;
type ReportIssueFormValues = z.input<typeof reportIssueFormSchema>;
type NormalizedReportIssueFormValues = z.output<typeof reportIssueFormSchema>;
function notify(message: string, type: 'success' | 'error' | 'warning' | 'info' = 'info') {
window.showToast?.(message, type);
@ -353,7 +353,7 @@ function updateBadge(openCount: number) {
function normalizeReportIssueFormValues(
values: ReportIssueFormValues,
): NormalizedReportIssueFormValues {
return reportIssueFormBaseSchema.parse(values);
return reportIssueFormSchema.parse(values);
}
function validateReportIssueForm(
@ -361,7 +361,7 @@ function validateReportIssueForm(
values: ReportIssueFormValues,
): string | undefined {
if (!profileId) return 'Profile is still loading';
const result = reportIssueFormBaseSchema.safeParse(values);
const result = reportIssueFormSchema.safeParse(values);
if (result.success) return undefined;
return result.error.issues[0]?.message || 'Unable to submit this issue';
}

@ -7,11 +7,11 @@ import {
issueDetailQueryOptions,
issueListQueryOptions,
} from './-issues.api';
import { ISSUE_SEARCH_SCHEMA } from './-issues.types';
import { issueSearchSchema } from './-issues.types';
import { IssuesPage } from './-ui/issues-page';
export const Route = createFileRoute('/issues')({
validateSearch: ISSUE_SEARCH_SCHEMA,
validateSearch: issueSearchSchema,
beforeLoad: ({ context }) => {
const { bridge } = context.shell;

Loading…
Cancel
Save