Files

72 lines
3.2 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest';
import { render } from 'svelte/server';
import Freshness from '../../src/lib/ui/components/Freshness.svelte';
import { stripGameColorCodes } from '../../src/lib/ui/log-text.js';
afterEach(() => vi.useRealTimers());
describe('quiet refresh feedback', () => {
it('shows relative receipt time with an exact tooltip without announcing every tick', () => {
vi.useFakeTimers();
vi.setSystemTime('2026-10-07T12:03:00Z');
const body = render(Freshness, {
props: {
updatedAt: Date.parse('2026-10-07T12:00:00Z'),
intervalLabel: 'Updates every 5 seconds'
}
}).body;
expect(body).toContain('Live');
expect(body).toContain('3 min ago');
expect(body).toContain('datetime="2026-10-07T12:00:00.000Z"');
expect(body).toMatch(/<time[^>]+title="[^"]+"/);
expect(body).toContain('Updates every 5 seconds');
expect(body).not.toMatch(/aria-live|role="status"|>Retry</);
});
it('does not claim live updates or an automatic schedule while paused', () => {
const body = render(Freshness, {
props: { paused: true, updatedAt: Date.now(), intervalLabel: 'Updates every 5 seconds' }
}).body;
expect(body).toContain('Paused');
expect(body).not.toMatch(/Live|Updates every/);
});
it('replaces live claims with a retry on failures and treats invalid timestamps as unknown', () => {
const body = render(Freshness, {
props: {
updatedAt: Date.now(),
error: 'Log updates interrupted.',
intervalLabel: 'Updates every 5 seconds',
onRetry: () => {},
retryDisabled: true
}
}).body;
expect(body).toContain('Log updates interrupted.');
expect(body).toMatch(/<button[^>]+disabled[^>]*>Retry<\/button>/);
expect(body).not.toMatch(/Live|Updates every/);
const waiting = render(Freshness, { props: { updatedAt: Number.NaN } }).body;
expect(waiting).toContain('Waiting for update');
expect(waiting).not.toContain('<time');
});
});
describe('readable game logs', () => {
it('strips digit colour directives while preserving log whitespace and other carets', () => {
const raw = ' [12:30] ^1Red^7 player\t^2joined^0\r\npath ^name, exponent x^y, trailing ^';
expect(stripGameColorCodes(raw)).toBe(
' [12:30] Red player\tjoined\r\npath ^name, exponent x^y, trailing ^'
);
expect(raw).toContain('^1Red^7');
});
it('allows searches across embedded colour changes without mutating downloadable source lines', () => {
const raw = ['^1Con^2nection^7 accepted', ' Player ^3Jamie^7 joined '];
const displayed = raw.map(stripGameColorCodes);
expect(displayed.filter((line) => line.toLowerCase().includes('connection'))).toEqual([
'Connection accepted'
]);
expect(displayed.join('\n')).toBe('Connection accepted\n Player Jamie joined ');
expect(raw.join('\n')).toBe('^1Con^2nection^7 accepted\n Player ^3Jamie^7 joined ');
});
});