This commit is contained in:
Gauthier Roebroeck 2026-01-30 17:22:39 +08:00
parent cf4a51a734
commit edbe676646
2 changed files with 96 additions and 6 deletions

View file

@ -1,6 +1,11 @@
import { describe, expect, test } from 'vitest'
import * as v from 'valibot'
import { SchemaAnyAll } from '@/types/filter'
import {
SchemaAnyAll,
SchemaFilterSeriesStatus,
SchemaFilterStrings,
SchemaSeriesStatus,
} from '@/types/filter'
describe('schema any all', () => {
test('anyOf', () => {
@ -30,3 +35,41 @@ describe('schema any all', () => {
expect(defaults).toStrictEqual(input)
})
})
describe('schema series status', () => {
test('correct value', () => {
const input = { v: 'ENDED' }
const result = v.parse(SchemaSeriesStatus, input)
expect(result).toStrictEqual(input)
})
test('case insensitive', () => {
const input = { v: 'enDeD' }
const result = v.parse(SchemaSeriesStatus, input)
expect(result).toStrictEqual({ v: 'ENDED' })
})
test('other value throws error', () => {
const input = { v: 'whatever' }
expect(() => v.parse(SchemaSeriesStatus, input)).toThrowError()
})
})
describe('filter schemas have a default value', () => {
test('SchemaFilterSeriesStatus', () => {
const expected = { m: 'anyOf', v: [] }
const defaults = v.getDefaults(SchemaFilterSeriesStatus)
expect(defaults).toStrictEqual(expected)
})
test('SchemaFilterStrings', () => {
const expected = { m: 'anyOf', v: [] }
const defaults = v.getDefaults(SchemaFilterStrings)
expect(defaults).toStrictEqual(expected)
})
})

View file

@ -2,23 +2,70 @@ import * as v from 'valibot'
export type AnyAll = 'anyOf' | 'allOf'
///////////////////////////////////////////////////////////////////////////
// This file contains all the valibot schemas for the Criteria API.
// Those objects end up serialized in the address bar in the query params,
// that's why the properties and values are kept to the shortest.
///////////////////////////////////////////////////////////////////////////
/**
* Schema for criteria API with `anyOf` or `allOf` condition.
*/
export const SchemaAnyAll = v.object({
/**
* Shorthand for `mode`.
*/
m: v.optional(v.picklist(['anyOf', 'allOf']), 'anyOf'),
})
const SchemaIncludeExclude = v.object({ i: v.optional(v.picklist(['i', 'e'])) })
const SchemaIncludeExclude = v.object({
/**
* Shorthand for `include`.
*
* Values can be: include (`i`) or exclude (`e`)
*/
i: v.optional(v.picklist(['i', 'e'])),
})
export const SchemaSeriesStatus = v.object({
...SchemaIncludeExclude.entries,
v: v.optional(v.picklist(['ENDED', 'ONGOING', 'ABANDONED', 'HIATUS'])),
/**
* Shorthand for `value`.
*/
v: v.pipe(v.string(), v.toUpperCase(), v.picklist(['ENDED', 'ONGOING', 'ABANDONED', 'HIATUS'])),
})
export const SchemaString = v.object({
...SchemaIncludeExclude.entries,
/**
* Shorthand for `value`.
*/
v: v.string(),
})
////////////////////////////////////////////////////
// All schema filters need to have a default value
////////////////////////////////////////////////////
/**
* Schema for Series Status.
*/
export const SchemaFilterSeriesStatus = v.object({
...SchemaAnyAll.entries,
v: v.fallback(v.optional(v.array(SchemaSeriesStatus), []), []),
/**
* Shorthand for 'value'
*/
v: v.optional(v.array(SchemaSeriesStatus), []),
})
export const FilterSeriesGenre = v.object({
/**
* Schema for a list of string.
* Can be used for tags, genre, sharing labels
*/
export const SchemaFilterStrings = v.object({
...SchemaAnyAll.entries,
value: v.array(v.string()),
/**
* Shorthand for 'value'
*/
v: v.optional(v.array(SchemaString), []),
})