diff --git a/webui/src/routes/issues/-issues.helpers.test.ts b/webui/src/routes/issues/-issues.helpers.test.ts index 73aec7e9..1b812c9b 100644 --- a/webui/src/routes/issues/-issues.helpers.test.ts +++ b/webui/src/routes/issues/-issues.helpers.test.ts @@ -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, diff --git a/webui/src/routes/issues/-issues.types.ts b/webui/src/routes/issues/-issues.types.ts index 68639ee4..7cd57236 100644 --- a/webui/src/routes/issues/-issues.types.ts +++ b/webui/src/routes/issues/-issues.types.ts @@ -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; +export type IssuesSearch = z.infer; export interface IssueTrackRow extends Record { bitrate?: string | number; diff --git a/webui/src/routes/issues/-ui/issue-domain-host.tsx b/webui/src/routes/issues/-ui/issue-domain-host.tsx index c5aca392..da9f3a78 100644 --- a/webui/src/routes/issues/-ui/issue-domain-host.tsx +++ b/webui/src/routes/issues/-ui/issue-domain-host.tsx @@ -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; -type NormalizedReportIssueFormValues = z.output; +type ReportIssueFormValues = z.input; +type NormalizedReportIssueFormValues = z.output; 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'; } diff --git a/webui/src/routes/issues/route.tsx b/webui/src/routes/issues/route.tsx index 3824cbac..7ee72cc4 100644 --- a/webui/src/routes/issues/route.tsx +++ b/webui/src/routes/issues/route.tsx @@ -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;