Files
mdg-filius/packages/editor/test/serverLines.test.ts
T
julian.kiedaischandClaude Opus 5.5 e31da62ae0 feat: F4.6g1 the echo server and the generic client windows
Oracle EchoWindowRun uses Java's echo server and client windows as a
person does; SaveAfterRunRun echo saves what Java keeps after the run.
The room takes setActive with a port, connect/disconnect/send, sends
both views and writes the server's port and the client's target back.
The editor's windows show Java's buttons, fields and lines; a port that
is no port is marked and not handed over (Java's button throws).
Core fix: an empty message (one empty segment with the push, as Java's
erstelleSegmente makes) counted as a repeat and never arrived.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:04:33 +00:00

81 lines
4.6 KiB
TypeScript

// A server's lines as Java's web server window wrote them
// (packages/sim/test/browserWindow.java.json, BrowserWindowRun): each kind
// the window got there, in Java's words.
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import type { ServerLogEntry, SimpleClientLogEntry } from '@mdg-filius/core';
import { serverLine, simpleClientLine } from '../src/desktop/serverLines.js';
import { translate } from '../src/i18n/i18n.js';
const java = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../../sim/test/browserWindow.java.json'), 'utf8')) as { steps: { step: string; log?: string }[] };
const log = java.steps.find((step) => step.step === 'server:stop')!.log!;
const t = (key: string, values?: Readonly<Record<string, string | number>>) => translate('de', key, values);
describe("a server's lines", () => {
it("are Java's, line by line", () => {
const [, address, port] = /Verbindung zu ([\d.]+):(\d+) hergestellt/.exec(log)!;
const request = 'POST /ziel.html HTTP/1.1\nHost: www.filius.de\n\nname=Fil+ius&c=1&s=y&t=%C3%BC%26%3D&ok=Gut';
const answer = 'HTTP/1.1 200 OK\nContent-type: text/html\n\n<html><head><title>Ziel</title></head><body>Ziel</body></html>';
const entries: ServerLogEntry[] = [
{ kind: 'acceptingStarted' },
{ kind: 'connectionAccepted', address: address!, port: Number(port) },
{ kind: 'received', text: request },
{ kind: 'sent', text: answer },
{ kind: 'connectionClosed', address: address!, port: Number(port) },
{ kind: 'acceptingStopped' },
{ kind: 'serverSocketClosed' },
];
for (const entry of entries) expect(log, entry.kind).toContain(`${serverLine(entry, t)}\n`);
expect(log.startsWith(`${serverLine({ kind: 'acceptingStarted' }, t)}\n`)).toBe(true);
});
it('name a failed send and a port that is taken', () => {
expect(serverLine({ kind: 'sendFailed', failure: 'timedOut' }, t)).toBe('Zeitüberschreitung während des Versands einer Nachricht');
expect(serverLine({ kind: 'sendFailed', failure: 'notConnected' }, (key) => translate('en', key))).toBe('Connection could not be established!');
expect(serverLine({ kind: 'serverSocketFailed' }, t)).toBe('Server-Socket konnte nicht geöffnet werden.');
expect(serverLine({ kind: 'connectionAccepted', address: '1.2.3.4', port: 5 }, (key, values) => translate('en', key, values))).toBe('Connection to 1.2.3.4:5 established');
});
});
// The echo windows' lines against Java's (packages/sim/test/echoWindow.java.json, EchoWindowRun).
const echo = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../../sim/test/echoWindow.java.json'), 'utf8')) as {
steps: { step: string; server: { log: string }; client: { output: string } }[];
};
describe("the echo windows' lines", () => {
it("are Java's, line by line, the server's and the client's", () => {
const last = echo.steps.at(-1)!;
const [, port] = /Verbindung zu 192\.168\.0\.20:(\d+) hergestellt/.exec(last.server.log)!;
const server: ServerLogEntry[] = [
{ kind: 'acceptingStarted' },
{ kind: 'connectionAccepted', address: '192.168.0.20', port: Number(port) },
{ kind: 'received', text: 'Zeile 1\nZeile 2' },
{ kind: 'sent', text: 'Zeile 1\nZeile 2' },
{ kind: 'acceptingStopped' },
{ kind: 'connectionClosed', address: '192.168.0.20', port: Number(port) },
{ kind: 'serverSocketClosed' },
];
for (const entry of server) expect(last.server.log, entry.kind).toContain(`${serverLine(entry, t)}\n`);
const client: SimpleClientLogEntry[] = [
{ kind: 'connected' },
{ kind: 'sent', text: 'Hallo Echo' },
{ kind: 'received', text: 'Hallo Echo' },
{ kind: 'connectionClosed', address: '192.168.0.30', port: 55555 },
{ kind: 'connectFailed', failure: 'timedOut' },
{ kind: 'disconnected' },
{ kind: 'connectFailed', failure: 'unresolved' },
];
for (const entry of client) expect(last.client.output, entry.kind).toContain(`${simpleClientLine(entry, t)}\n`);
// Not in this story, in Java's words all the same (sw_clientbaustein_msg4, sw_tcpsocket_msg3, msg9, msg6).
expect([
simpleClientLine({ kind: 'notConnected' }, t),
simpleClientLine({ kind: 'connectFailed', failure: 'failed' }, t),
simpleClientLine({ kind: 'receiveFailed' }, t),
simpleClientLine({ kind: 'sendFailed', failure: 'notConnected' }, t),
]).toEqual(['Fehler beim Verbindungsaufbau', 'Fehler beim Verbindungsaufbau\nAktives Öffnen des Sockets fehlgeschlagen', 'Keine Verbindung hergestellt!', 'Verbindung nicht aufgebaut!']);
});
});