Fix variant-aware fleet card map labels (Refs #150)
CI / checks (push) Successful in 5m47s

This commit is contained in:
2026-10-12 19:55:26 -04:00
parent 106d3a5ded
commit bcd3b99ee4
5 changed files with 220 additions and 10 deletions
+190
View File
@@ -0,0 +1,190 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import { flushSync, mount, unmount, type ComponentProps } from 'svelte';
import { fromStore, writable } from 'svelte/store';
import ServerCard from '../../src/lib/ui/components/ServerCard.svelte';
import ServerIdentity from '../../src/lib/ui/components/ServerIdentity.svelte';
import PlayerScoreboard from '../../src/lib/ui/components/PlayerScoreboard.svelte';
import { fleetIdentity } from '../../src/lib/fleet-overview.js';
import { gameEvent } from '../helpers/telemetry.js';
afterEach(async () => {
await Promise.all(components.splice(0).map((component) => unmount(component)));
document.body.replaceChildren();
});
vi.mock('$app/stores', () => ({
page: writable({ url: new URL('http://localhost/') })
}));
const components: ReturnType<typeof mount>[] = [];
type MapServer = Parameters<typeof fleetIdentity>[0];
const town: MapServer = {
name: 't6_zombie_town_1',
game: 't6',
map: 'zm_transit',
last_map: 'zm_transit'
};
function show(
initial: MapServer,
options: Partial<ComponentProps<typeof ServerCard>> = {},
fleetHeading = true
) {
const store = writable(initial);
const state = fromStore(store);
const identity = () => fleetIdentity(state.current);
components.push(
mount(ServerCard, {
target: document.body,
props: {
get name() {
return state.current.name;
},
get game() {
return state.current.game;
},
get map() {
return state.current.last_map ?? state.current.map;
},
get mapSlug() {
return state.current.map_slug;
},
get gameMode() {
return state.current.game_mode;
},
get mapLabelOverride() {
return fleetHeading ? identity().map : undefined;
},
health: 'online',
players: 4,
...options
}
}),
mount(ServerIdentity, {
target: document.body,
props: {
get name() {
return state.current.name;
},
get mapLabel() {
return identity().map;
}
}
}),
mount(PlayerScoreboard, {
target: document.body,
props: {
get report() {
return {
...gameEvent(
'heartbeat',
12,
4,
state.current.name,
state.current.last_map ?? state.current.map ?? ''
),
receivedAt: new Date().toISOString()
};
},
get mapLabel() {
return identity().map;
}
}
})
);
flushSync();
return (next: Partial<MapServer>) => {
store.update((server) => ({ ...server, ...next }));
flushSync();
};
}
function expectLabels(label: string) {
expect(document.querySelector('h3')?.textContent).toBe(label);
expect(document.querySelector('.identity .map')?.textContent).toBe(label);
expect(document.querySelector('.match-title h2')?.textContent).toBe(label);
expect(document.querySelector('.map-note')).toBeNull();
}
const variants = [
['town', 'Town Survival'],
['farm', 'Farm Survival'],
['busdepot', 'Bus Depot Survival'],
['transit', 'TranZit']
];
describe('variant-aware rendered map labels', () => {
it.each(variants)('keeps %s consistent across card, list, and detail', (slug, label) => {
const update = show({ ...town, name: `t6_zombie_${slug}_1` });
expectLabels(label);
update({ name: 'Friday lobby', map_slug: slug, game_mode: 'zombie' });
expectLabels(label);
});
it.each([undefined, null, 'unknown'])('does not infer TranZit from variant %s', (map_slug) => {
const server = { ...town, name: 'Custom lobby', map_slug };
show(server);
expectLabels('zm_transit (variant unknown)');
expect(fleetIdentity(server).launch).toBeNull();
});
it('lets unknown stored metadata override a recognized name', () => {
show({ ...town, map_slug: 'unknown' });
expectLabels('zm_transit (variant unknown)');
});
it('updates map and variant metadata reactively without retaining an obsolete launch shortcut', () => {
const update = show(town);
expectLabels('Town Survival');
update({ last_map: 'zm_tomb' });
expectLabels('Origins');
expect(fleetIdentity({ ...town, last_map: 'zm_tomb' }).launch).toBeNull();
update({ last_map: 'zm_transit', map_slug: 'farm' });
expectLabels('Farm Survival');
expect(fleetIdentity({ ...town, map_slug: 'farm' }).launch).toEqual({
game: 't6',
slug: 'farm'
});
update({ map_slug: 'unknown' });
expectLabels('zm_transit (variant unknown)');
update({ last_map: 'zm_buried' });
expectLabels('Buried');
});
it.each(['stale', 'offline'] as const)(
'keeps the selected variant for %s observations',
(health) => {
show(town, { health, lastSeenAt: '2026-01-01T00:00:00Z' });
expectLabels('Town Survival');
}
);
it.each([true, false])('preserves empty-card compact=%s behavior', (compactEmpty) => {
show(town, { players: 0, compactEmpty });
expectLabels('Town Survival');
expect(document.querySelector('article')?.classList.contains('compact')).toBe(compactEmpty);
expect(document.querySelector('article .metrics') === null).toBe(compactEmpty);
});
it.each([
['online', 'Current map'],
['stale', 'Last map'],
['offline', 'Last map']
] as const)('retains useful %s map context with a name-based heading', (health, prefix) => {
const update = show(town, { health }, false);
expect(document.querySelector('.map-note')).toBeNull();
update({ last_map: 'zm_tomb' });
expect(document.querySelector('h3')?.textContent).toBe('Town Survival');
expect(document.querySelector('.map-note')?.textContent?.trim()).toBe(`${prefix}: Origins`);
});
it('hides additional map context in compact cards', () => {
show({ ...town, last_map: 'zm_tomb' }, { players: 0 }, false);
expect(document.querySelector('.map-note')).toBeNull();
});
it('uses stored variant metadata for a custom heading and does not invent a missing observation', () => {
const update = show({ ...town, name: 'Friday lobby', map_slug: 'town' }, {}, false);
expect(document.querySelector('.map-note')?.textContent?.trim()).toBe(
'Current map: Town Survival'
);
update({ map: null, last_map: null });
expect(document.querySelector('.map-note')).toBeNull();
});
});