refactor(GetFonts): tighten mapManagerToParams + add coverage

Collapse the three duplicated getGroup/map/length-guard chains into a
single selectedIn helper. Drop the unnecessary `as string[]` casts —
Property<TValue extends string>.value already yields string at the call
site.

Add unit tests covering empty query, populated query, missing group,
empty group, single + multi selection, unknown group ids, and the
combined param shape.
This commit is contained in:
Ilia Mashkov
2026-05-24 15:45:07 +03:00
parent 30621c33df
commit 3a327e2d92
2 changed files with 139 additions and 17 deletions
@@ -0,0 +1,127 @@
import type { Property } from '$shared/lib';
import {
describe,
expect,
it,
} from 'vitest';
import { createFilterManager } from '../../model/store/filterManager/filterManager.svelte';
import { mapManagerToParams } from './mapManagerToParams';
/**
* Build a Property with explicit selection state.
*/
function prop(value: string, selected = false): Property<string> {
return { id: value, name: value, value, selected };
}
/**
* Build a filter group with a known id and a list of (value, selected) entries.
*/
function group(id: string, props: Array<[string, boolean]>) {
return {
id,
label: id,
properties: props.map(([value, selected]) => prop(value, selected)),
};
}
describe('mapManagerToParams', () => {
describe('search query', () => {
it('omits q when query is empty', () => {
const manager = createFilterManager({ queryValue: '', groups: [] });
expect(mapManagerToParams(manager).q).toBeUndefined();
});
it('passes the debounced query through as q', () => {
// Constructor seeds both immediate and debounced synchronously.
const manager = createFilterManager({ queryValue: 'roboto', groups: [] });
expect(mapManagerToParams(manager).q).toBe('roboto');
});
});
describe('group selections', () => {
it('omits a group entirely when no group with that id exists', () => {
const manager = createFilterManager({ queryValue: '', groups: [] });
const params = mapManagerToParams(manager);
expect(params.providers).toBeUndefined();
expect(params.categories).toBeUndefined();
expect(params.subsets).toBeUndefined();
});
it('omits a group when it exists but has no selections', () => {
const manager = createFilterManager({
queryValue: '',
groups: [group('providers', [['google', false], ['fontshare', false]])],
});
expect(mapManagerToParams(manager).providers).toBeUndefined();
});
it('returns the selected values for a single group', () => {
const manager = createFilterManager({
queryValue: '',
groups: [group('providers', [['google', true], ['fontshare', false]])],
});
expect(mapManagerToParams(manager).providers).toEqual(['google']);
});
it('returns multiple selected values in selection order', () => {
const manager = createFilterManager({
queryValue: '',
groups: [
group('categories', [
['serif', true],
['sans-serif', false],
['display', true],
['monospace', true],
]),
],
});
expect(mapManagerToParams(manager).categories).toEqual(['serif', 'display', 'monospace']);
});
it('maps each of the three recognized group ids independently', () => {
const manager = createFilterManager({
queryValue: '',
groups: [
group('providers', [['google', true]]),
group('categories', [['serif', true], ['sans-serif', true]]),
group('subsets', [['latin', true]]),
],
});
const params = mapManagerToParams(manager);
expect(params.providers).toEqual(['google']);
expect(params.categories).toEqual(['serif', 'sans-serif']);
expect(params.subsets).toEqual(['latin']);
});
it('ignores groups whose id does not match providers/categories/subsets', () => {
const manager = createFilterManager({
queryValue: '',
groups: [group('weights', [['400', true], ['700', true]])],
});
const params = mapManagerToParams(manager);
expect(params.providers).toBeUndefined();
expect(params.categories).toBeUndefined();
expect(params.subsets).toBeUndefined();
});
});
describe('combined output', () => {
it('produces a complete param object when query and selections coexist', () => {
const manager = createFilterManager({
queryValue: 'inter',
groups: [
group('providers', [['google', true]]),
group('categories', [['sans-serif', true]]),
group('subsets', [['latin', false]]),
],
});
expect(mapManagerToParams(manager)).toEqual({
q: 'inter',
providers: ['google'],
categories: ['sans-serif'],
subsets: undefined,
});
});
});
});
@@ -29,25 +29,20 @@ import type { FilterManager } from '../../model';
* ```
*/
export function mapManagerToParams(manager: FilterManager): Partial<ProxyFontsParams> {
const providers = manager.getGroup('providers')?.instance.selectedProperties.map(p => p.value);
const categories = manager.getGroup('categories')?.instance.selectedProperties.map(p => p.value);
const subsets = manager.getGroup('subsets')?.instance.selectedProperties.map(p => p.value);
/**
* Return the list of selected values for a group, or undefined when
* the group is missing or has no selection — matches the API's
* "omit empty filters" contract.
*/
const selectedIn = (id: string): string[] | undefined => {
const values = manager.getGroup(id)?.instance.selectedProperties.map(p => p.value);
return values && values.length > 0 ? values : undefined;
};
return {
// Search query (debounced)
q: manager.debouncedQueryValue || undefined,
// NEW: Support arrays - send all selected values
providers: providers && providers.length > 0
? providers as string[]
: undefined,
categories: categories && categories.length > 0
? categories as string[]
: undefined,
subsets: subsets && subsets.length > 0
? subsets as string[]
: undefined,
providers: selectedIn('providers'),
categories: selectedIn('categories'),
subsets: selectedIn('subsets'),
};
}