web-player: add Vitest, unit tests and pure queue operations
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { appendUnique, shuffle } from './collections';
|
||||
|
||||
describe('appendUnique', () => {
|
||||
const keyOf = (item: { id: number }) => item.id;
|
||||
it('appends only unseen keys', () => {
|
||||
const result = appendUnique([{ id: 1 }], [{ id: 1 }, { id: 2 }, { id: 2 }, { id: 3 }], keyOf);
|
||||
expect(result).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]);
|
||||
});
|
||||
it('returns the same array when nothing is new', () => {
|
||||
const current = [{ id: 1 }];
|
||||
expect(appendUnique(current, [{ id: 1 }], keyOf)).toBe(current);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shuffle', () => {
|
||||
it('keeps the same elements and does not mutate the input', () => {
|
||||
const input = [1, 2, 3, 4, 5, 6];
|
||||
const result = shuffle(input);
|
||||
expect([...result].sort()).toEqual(input);
|
||||
expect(input).toEqual([1, 2, 3, 4, 5, 6]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { findConflict, genreHue } from './genres';
|
||||
|
||||
describe('genreHue', () => {
|
||||
it('is stable and within 0-359', () => {
|
||||
for (const genre of ['rock', 'something-unknown', 'ñandú']) {
|
||||
const hue = genreHue(genre);
|
||||
expect(hue).toBe(genreHue(genre));
|
||||
expect(hue).toBeGreaterThanOrEqual(0);
|
||||
expect(hue).toBeLessThan(360);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('findConflict', () => {
|
||||
const options = [
|
||||
{ genre: 'a', incompatibleWith: ['b'] },
|
||||
{ genre: 'b', incompatibleWith: ['a'] },
|
||||
{ genre: 'c', incompatibleWith: [] }
|
||||
];
|
||||
it('returns the first incompatible pair', () => {
|
||||
expect(findConflict(['c', 'a', 'b'], options)).toEqual(['a', 'b']);
|
||||
});
|
||||
it('returns undefined when compatible or unknown', () => {
|
||||
expect(findConflict(['a', 'c'], options)).toBeUndefined();
|
||||
expect(findConflict(['x', 'y'], options)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { findTopResult } from './search';
|
||||
|
||||
const empty = { tracks: [], albums: [], playlists: [], users: [] };
|
||||
|
||||
describe('findTopResult', () => {
|
||||
it('prefers prefix matches by kind: user, track, album, playlist', () => {
|
||||
const result = findTopResult({
|
||||
query: 'Ab',
|
||||
users: [{ name: 'Zed' }, { name: 'abel' }],
|
||||
tracks: [{ title: 'Abc' }],
|
||||
albums: [{ title: 'Abd' }],
|
||||
playlists: [{ name: 'Abe' }]
|
||||
});
|
||||
expect(result).toEqual({ kind: 'user', user: { name: 'abel' } });
|
||||
});
|
||||
it('matches case-insensitively and ignores surrounding spaces', () => {
|
||||
const result = findTopResult({ ...empty, query: ' SO ', tracks: [{ title: 'song' }] });
|
||||
expect(result).toEqual({ kind: 'track', track: { title: 'song' } });
|
||||
});
|
||||
it('falls back to the first available result', () => {
|
||||
const result = findTopResult({ ...empty, query: 'zzz', albums: [{ title: 'Other' }] });
|
||||
expect(result).toEqual({ kind: 'album', album: { title: 'Other' } });
|
||||
});
|
||||
it('returns null without results', () => {
|
||||
expect(findTopResult({ ...empty, query: 'x' })).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user