120 lines
4.6 KiB
TypeScript
120 lines
4.6 KiB
TypeScript
import { expect, it } from 'vitest';
|
|
import { render } from 'svelte/server';
|
|
import LibraryVersions from '../../src/lib/ui/components/LibraryVersions.svelte';
|
|
import GameFileHosts from '../../src/lib/ui/components/GameFileHosts.svelte';
|
|
import type { HostLibraryCache } from '../../src/lib/game-files.js';
|
|
import type { Host } from '../../src/lib/hosts.js';
|
|
|
|
it('shows the promoted version once and keeps a newer failed version distinct', () => {
|
|
const current = { id: 1, version: 1 };
|
|
const promoted = render(LibraryVersions, { props: { current, latest: current } }).body;
|
|
expect(promoted.match(/v1/g)).toHaveLength(1);
|
|
expect(promoted.match(/Promoted/g)).toHaveLength(1);
|
|
const newer = render(LibraryVersions, {
|
|
props: { current, latest: { id: 2, version: 2, state: 'test-failed' } }
|
|
}).body;
|
|
expect(newer).toContain('Test failed');
|
|
expect(newer).toContain('v2');
|
|
expect(newer).toContain('v1');
|
|
expect(newer).toContain('Promoted');
|
|
});
|
|
|
|
it('disambiguates two builds with the same release tag only when needed', () => {
|
|
const current = { id: 1, version: 1, release_version: 'v1.1.0' };
|
|
expect(render(LibraryVersions, { props: { current, latest: current } }).body).not.toContain(
|
|
'upload'
|
|
);
|
|
const body = render(LibraryVersions, {
|
|
props: { current, latest: { ...current, id: 2, version: 2, state: 'untested' } }
|
|
}).body;
|
|
expect(body).toContain('v1.1.0 (upload 1)');
|
|
expect(body).toContain('v1.1.0 (upload 2)');
|
|
expect(body).toContain('Needs testing');
|
|
});
|
|
|
|
it('does not present an active beta as passed or an empty artifact as promoted', () => {
|
|
expect(render(LibraryVersions, { props: { current: null, latest: null } }).body).toContain(
|
|
'No versions'
|
|
);
|
|
const body = render(LibraryVersions, {
|
|
props: { current: null, latest: { id: 1, version: 1, state: 'tested' }, betaId: 12 }
|
|
}).body;
|
|
expect(body).toContain('Beta active');
|
|
expect(body).not.toContain('Test passed');
|
|
expect(body).toContain('Never promoted');
|
|
});
|
|
|
|
const host = (id: string, connected = true) =>
|
|
({
|
|
id,
|
|
name: id,
|
|
connected,
|
|
enrolled: true,
|
|
credentialActive: true,
|
|
mode: 'active',
|
|
readiness: 'ready'
|
|
}) as Host;
|
|
const cache = (
|
|
id: string,
|
|
status: HostLibraryCache['status'],
|
|
error: string | null = null
|
|
): HostLibraryCache => ({
|
|
hostId: id,
|
|
libraryVersionId: 'upload',
|
|
status,
|
|
error,
|
|
bytesDownloaded: 100,
|
|
bytesTotal: 100,
|
|
manifestSha256: null,
|
|
updatedAt: '2026-10-06T12:00:00Z',
|
|
operationId: null
|
|
});
|
|
|
|
it('surfaces failures, transfers and offline hosts before collapsed healthy copies', () => {
|
|
const body = render(GameFileHosts, {
|
|
props: {
|
|
latest: true,
|
|
hosts: [host('healthy'), host('failed'), host('transfer'), host('offline', false)],
|
|
caches: [
|
|
cache('healthy', 'ready'),
|
|
cache('failed', 'failed', 'Checksum mismatch'),
|
|
cache('transfer', 'verifying'),
|
|
cache('offline', 'ready')
|
|
]
|
|
}
|
|
}).body;
|
|
const ready = body.indexOf('Ready hosts (1)');
|
|
expect(body.indexOf('Checksum mismatch')).toBeLessThan(ready);
|
|
expect(body.indexOf('Host verification progress')).toBeLessThan(ready);
|
|
expect(body.indexOf('Offline')).toBeLessThan(ready);
|
|
expect(body.indexOf('href="/hosts/healthy"')).toBeGreaterThan(ready);
|
|
expect(body).toMatch(/<details[^>]*><summary[^>]*>Ready hosts \(1\)/);
|
|
expect(body).not.toMatch(/<details[^>]*open/);
|
|
expect(body).toContain('View host setup');
|
|
});
|
|
|
|
it('explains pending automatic downloads and keeps copy errors visible even for ready status', () => {
|
|
const body = render(GameFileHosts, {
|
|
props: {
|
|
latest: true,
|
|
hosts: [host('waiting', false), host('inconsistent')],
|
|
caches: [
|
|
cache('waiting', 'missing'),
|
|
cache('inconsistent', 'ready', 'Host report needs review')
|
|
]
|
|
}
|
|
}).body;
|
|
expect(body).toContain('Automatic setup resumes when the host reconnects.');
|
|
expect(body).toContain('Host report needs review');
|
|
expect(body).not.toContain('Ready hosts');
|
|
});
|
|
|
|
it('shows script release versions and explicitly labels historical uploads', () => {
|
|
const current = { id: 1, version: 1, release_version: null };
|
|
const body = render(LibraryVersions, {
|
|
props: { kind: 'script', current, latest: { id: 2, version: 2, release_version: '1.2.0' } }
|
|
}).body;
|
|
expect(body).toContain('Unversioned (upload 1)');
|
|
expect(body).toContain('1.2.0 (upload 2)');
|
|
});
|