test: fix tests and program schema ordering

This commit is contained in:
Christian Benincasa
2026-02-15 17:57:26 -05:00
parent 9c7fd04e47
commit 6ba45e3e80
5 changed files with 70 additions and 46 deletions

View File

@@ -40,6 +40,9 @@
"inputs": ["./src/**"],
"dependsOn": ["^build"]
},
"generate-env": {}
"generate-env": {},
"test": {
"dependsOn": ["^build"]
}
}
}

View File

@@ -22,6 +22,8 @@ export default defineConfig({
typecheck: {
tsconfig: 'tsconfig.test.json',
},
silent: true,
reporters: ['dot'],
},
define: {
'import.meta.vitest': false,

View File

@@ -2,6 +2,7 @@ import { SearchFilter } from '@tunarr/types/schemas';
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
import {
BinarySearchClause,
parsedSearchToRequest,
SearchClause,
searchFilterToString,
@@ -104,20 +105,35 @@ describe('search parser', () => {
test('parse numeric fields', () => {
const input = 'duration >= 10';
const lexerResult = tokenizeSearchQuery(input);
const parser = new SearchParser();
parser.input = lexerResult.tokens;
console.log(lexerResult.tokens, parser.errors);
const query = parseAndCheckExpression(input);
expect(query).toMatchObject({
type: 'single_numeric_query',
field: 'duration',
op: '>=',
value: 10,
} satisfies SearchClause);
});
test('can parse uuids', () => {
const input =
'library_id = ddd327c3-aea2-4b27-a2c0-a8ce190d25d0 AND title <= A';
const lexerResult = tokenizeSearchQuery(input);
const parser = new SearchParser();
parser.input = lexerResult.tokens;
const query = parser.searchExpression();
console.log(query);
const query = parseAndCheckExpression(input);
expect(query).toMatchObject({
type: 'binary_clause',
lhs: {
type: 'single_query',
field: 'library_id',
op: '=',
value: 'ddd327c3-aea2-4b27-a2c0-a8ce190d25d0',
},
rhs: {
type: 'single_query',
field: 'title',
op: '<=',
value: 'A',
},
op: 'and',
} satisfies BinarySearchClause);
});
test('supports numeric between inclusive', () => {

View File

@@ -521,6 +521,21 @@ const BaseProgramGrouping = z.object({
artwork: MediaArtwork.array(),
});
export const SeasonMetadata = z.object({
...BaseProgramGrouping.shape,
type: z.literal('season'),
studios: z.array(Studio),
index: z.number().nonnegative(),
year: z.number().positive().nullable(),
releaseDate: z.number().nullable(),
releaseDateString: z.string().nullable(),
});
const _SeasonWithTunarrMetadata = z.object({
...SeasonMetadata.shape,
...WithTunarrMetadata.shape,
});
export const ShowMetadata = z.object({
...BaseProgramGrouping.shape,
type: z.literal('show'),
@@ -532,7 +547,7 @@ export const ShowMetadata = z.object({
releaseDateString: z.string().nullable(),
year: z.number().positive().nullable(),
get seasons(): z.ZodOptional<z.ZodArray<typeof _SeasonWithTunarrMetadata>> {
return z.array(Season).optional();
return z.array(_SeasonWithTunarrMetadata).optional();
},
});
@@ -556,21 +571,6 @@ const BaseEpisodeWithoutJoins = z.object({
...WithMediaItemMetadata.shape,
});
export const SeasonMetadata = z.object({
...BaseProgramGrouping.shape,
type: z.literal('season'),
studios: z.array(Studio),
index: z.number().nonnegative(),
year: z.number().positive().nullable(),
releaseDate: z.number().nullable(),
releaseDateString: z.string().nullable(),
});
const _SeasonWithTunarrMetadata = z.object({
...SeasonMetadata.shape,
...WithTunarrMetadata.shape,
});
export const Season = z.object({
...SeasonMetadata.shape,
...WithTunarrMetadata.shape,
@@ -610,19 +610,6 @@ export const EpisodeWithHierarchy = z.object({
season: SeasonWithShow,
});
export const MusicArtistMetadata = z.object({
...BaseProgramGrouping.shape,
type: z.literal('artist'),
get albums(): z.ZodOptional<z.ZodArray<typeof BaseMusicAlbumWithoutJoins>> {
return z.optional(z.array(BaseMusicAlbumWithoutJoins));
},
});
export const MusicArtist = z.object({
...MusicArtistMetadata.shape,
...WithTunarrMetadata.shape,
});
const BaseMusicAlbum = z.object({
...BaseProgramGrouping.shape,
type: z.literal('album'),
@@ -638,17 +625,16 @@ const BaseMusicAlbumWithoutJoins = z.object({
...WithTunarrMetadata.shape,
});
export const MusicAlbumMetadata = z.object({
export const MusicArtistMetadata = z.object({
...BaseProgramGrouping.shape,
...BaseMusicAlbum.shape,
artist: MusicArtist.optional(),
get tracks(): z.ZodOptional<z.ZodArray<typeof BaseMusicTrackWithoutJoins>> {
return z.optional(z.array(BaseMusicTrackWithoutJoins));
type: z.literal('artist'),
get albums(): z.ZodOptional<z.ZodArray<typeof BaseMusicAlbumWithoutJoins>> {
return z.optional(z.array(BaseMusicAlbumWithoutJoins));
},
});
export const MusicAlbum = z.object({
...MusicAlbumMetadata.shape,
export const MusicArtist = z.object({
...MusicArtistMetadata.shape,
...WithTunarrMetadata.shape,
});
@@ -664,6 +650,20 @@ const BaseMusicTrackWithoutJoins = z.object({
...WithMediaItemMetadata.shape,
});
export const MusicAlbumMetadata = z.object({
...BaseProgramGrouping.shape,
...BaseMusicAlbum.shape,
artist: MusicArtist.optional(),
get tracks(): z.ZodOptional<z.ZodArray<typeof BaseMusicTrackWithoutJoins>> {
return z.optional(z.array(BaseMusicTrackWithoutJoins));
},
});
export const MusicAlbum = z.object({
...MusicAlbumMetadata.shape,
...WithTunarrMetadata.shape,
});
export const MusicTrackMetadata = z.object({
...BaseMusicTrack.shape,
album: MusicAlbum.optional(),

View File

@@ -18,6 +18,9 @@
"generate-client": {
"dependsOn": ["@tunarr/server#generate-openapi"],
"cache": false
},
"test": {
"dependsOn": ["^build"]
}
}
}