1import { describe, expect, it } from 'vitest';2import { BrowseInput } from '@tribes/protocol';3import { coerceBrowseQuery } from '../src/router';45const parse = (qs: string) => BrowseInput.safeParse(coerceBrowseQuery(new URLSearchParams(qs)));67describe('coerceBrowseQuery + BrowseInput', () => {8 it('applies zod defaults when params are absent or empty', () => {9 const r = parse('');10 expect(r.success).toBe(true);11 expect(r.data).toEqual({ sort: 'top', window: '7d', limit: 50, offset: 0 });12 const empties = parse('sort=&limit=&openWeights=');13 expect(empties.success).toBe(true);14 expect(empties.data).toEqual({ sort: 'top', window: '7d', limit: 50, offset: 0 });15 });1617 it('coerces numbers and booleans', () => {18 const r = parse('sort=rising&window=24h&limit=10&offset=20&openWeights=true&q=llama');19 expect(r.success).toBe(true);20 expect(r.data).toEqual({21 sort: 'rising',22 window: '24h',23 limit: 10,24 offset: 20,25 openWeights: true,26 q: 'llama',27 });28 expect(parse('openWeights=1').data?.openWeights).toBe(true);29 expect(parse('openWeights=0').data?.openWeights).toBe(false);30 expect(parse('openWeights=false').data?.openWeights).toBe(false);31 });3233 it('rejects malformed values instead of guessing', () => {34 expect(parse('limit=abc').success).toBe(false);35 expect(parse('limit=1.5').success).toBe(false);36 expect(parse('limit=1000').success).toBe(false);37 expect(parse('offset=-1').success).toBe(false);38 expect(parse('sort=hot').success).toBe(false);39 expect(parse('openWeights=maybe').success).toBe(false);40 expect(parse('releasedAfter=yesterday').success).toBe(false);41 });4243 it('passes date filters through', () => {44 const r = parse('releasedAfter=2025-01-01&releasedBefore=2025-12-31&lab=meta');45 expect(r.success).toBe(true);46 expect(r.data).toMatchObject({47 releasedAfter: '2025-01-01',48 releasedBefore: '2025-12-31',49 lab: 'meta',50 });51 });52});