// The one list of messages: what the room accepts from a client, and what // it refuses, each with its reason. import { describe, expect, it } from 'vitest'; import { BROWSER_START, browserTitle, CLIENT_MESSAGE_KINDS, HOST_MESSAGE_KINDS, htmlTitle, isTopic, parseClientMessage, parseHostMessage, type BrowserView } from '../src/index.js'; describe("a client's messages", () => { it('reads each kind', () => { const messages = [ { v: 1, kind: 'sub', topics: ['activity', 'trace:port-1', 'app:node-1/terminal'] }, { v: 1, kind: 'unsub', topics: ['activity'] }, { v: 1, kind: 'start' }, { v: 1, kind: 'stop' }, { v: 1, kind: 'speed', value: 50 }, { v: 1, kind: 'drop', on: true }, { v: 1, kind: 'input', node: 'node-1', app: 'terminal', action: 'enter', args: { line: 'ping 1.2.3.4' }, reqId: 'r1' }, ]; expect(messages.map((each) => each.kind)).toEqual([...CLIENT_MESSAGE_KINDS]); for (const each of messages) expect(parseClientMessage(each)).toEqual({ message: each }); // A start in a language, and the language dropped where it is none. for (const language of ['de', 'en']) expect(parseClientMessage({ v: 1, kind: 'start', language })).toEqual({ message: { v: 1, kind: 'start', language } }); expect(parseClientMessage({ v: 1, kind: 'stop', language: 'en' })).toEqual({ message: { v: 1, kind: 'stop' } }); }); it('names what is wrong', () => { const code = (value: unknown) => ('error' in parseClientMessage(value) ? (parseClientMessage(value) as { error: { code: string } }).error.code : 'ok'); expect(code(null)).toBe('badMessage'); expect(code([])).toBe('badMessage'); expect(code({ v: 2, kind: 'start' })).toBe('badVersion'); expect(code({ v: 1, kind: 'reset' })).toBe('unknownKind'); expect(code({ v: 1, kind: 'sub', topics: 'activity' })).toBe('badMessage'); expect(code({ v: 1, kind: 'sub', topics: ['activity', 'trace:'] })).toBe('badTopic'); expect(code({ v: 1, kind: 'unsub', topics: ['app:node/paint'] })).toBe('badTopic'); expect(code({ v: 1, kind: 'start', language: 'fr' })).toBe('badMessage'); expect(code({ v: 1, kind: 'drop', on: 'yes' })).toBe('badMessage'); expect(code({ v: 1, kind: 'sub', topics: ['dropped', 'app:node/sat', 'app:node/nat'] })).toBe('ok'); expect(code({ v: 1, kind: 'start', language: null })).toBe('badMessage'); expect(code({ v: 1, kind: 'speed', value: '50' })).toBe('badMessage'); expect(code({ v: 1, kind: 'speed', value: Number.NaN })).toBe('badMessage'); expect(code({ v: 1, kind: 'input', node: 'n', app: 'terminal', action: 'enter', args: {} })).toBe('badMessage'); expect(code({ v: 1, kind: 'input', node: 'n', app: 'terminal', action: 'enter', args: [], reqId: 'r' })).toBe('badMessage'); expect(code({ v: 1, kind: 'input', node: 'n', app: 'paint', action: 'enter', args: {}, reqId: 'r' })).toBe('unknownApp'); }); it('knows its topics', () => { expect(['activity', 'trace:x', 'app:n/gnutella', 'app:n/webBrowser', 'node:n'].every(isTopic)).toBe(true); expect(['', 'trace:', 'app:/terminal', 'app:n/', 'app:n/terminal/x', 'node:', 'node:n/x', 'nodes:n', 7].some(isTopic)).toBe(false); }); }); describe("a host's messages", () => { it('reads each kind, and names an unknown one', () => { for (const kind of HOST_MESSAGE_KINDS) expect('message' in parseHostMessage({ v: 1, kind })).toBe(true); expect(parseHostMessage({ v: 1, kind: 'nodes' })).toEqual({ error: { code: 'unknownKind', detail: 'kind nodes' } }); expect(parseHostMessage({ v: 0, kind: 'state' })).toEqual({ error: { code: 'badVersion', detail: 'version 0' } }); }); }); describe("the browser window's view", () => { it("reads an HTML page's first title as it is written, none where it is empty", () => { expect(htmlTitle('
Kein Titel
')).toBeUndefined(); }); it("titles the window with the program's name, then the address being loaded, then the page's title once it came", () => { const pageTitle = (page: BrowserView['page']) => (page.kind === 'html' ? htmlTitle(page.html) : page.kind === 'unreachable' ? 'Fehler' : undefined); expect(browserTitle(BROWSER_START, 'Webbrowser', pageTitle)).toBe('Webbrowser'); const shown: BrowserView = { address: 'http://a/', loading: 'http://a/', arrived: true, page: { kind: 'html', html: '