feat: F4.7 the data exchange window, measured against Java's
One row per frame (its highest layer's), Java's detail tree, the table as Java's text file, "Tabellen löschen" for every card (clearCapture in the room), a tab per card with Java's title, Java's layer colours as tokens, the chosen frame and autoscroll per tab. New oracle ExchangeWindowRun. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
// What the data exchange window writes of a frame in the viewer's language:
|
||||
// Java's words of both bundles, the locale's numbers ("1.000.000" in German,
|
||||
// "1,000,000" in English), the time of day with milliseconds, the row of the
|
||||
// highest layer, the details from the layered rows, the text file.
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { captureRows, TCP_FLAG, type CapturedFrame, type EthernetFrame } from '@mdg-filius/core';
|
||||
import type { TraceFrame } from '@mdg-filius/protocol';
|
||||
import { translate } from '../src/i18n/i18n.js';
|
||||
import { captureWords, exportText, frameCells, frameDetails } from '../src/simulation/captureCells.js';
|
||||
|
||||
/** A TCP segment with data from 10.0.0.1:50000 to 10.0.0.2:80, as the room sends it. */
|
||||
function frame(number: number, timeMilliseconds: number): TraceFrame {
|
||||
const ethernet: EthernetFrame = {
|
||||
identity: number,
|
||||
sourceMacAddress: '02:00:00:00:00:01',
|
||||
destinationMacAddress: '02:00:00:00:00:02',
|
||||
payload: {
|
||||
kind: 'ipv4',
|
||||
packet: {
|
||||
identity: 9,
|
||||
senderIPAddress: '10.0.0.1',
|
||||
receiverIPAddress: '10.0.0.2',
|
||||
timeToLive: 64,
|
||||
protocol: 'tcp',
|
||||
payload: {
|
||||
kind: 'tcp',
|
||||
segment: {
|
||||
sourcePort: 50_000,
|
||||
destinationPort: 80,
|
||||
sequenceNumber: 2_000_001,
|
||||
acknowledgementNumber: 1_000_001,
|
||||
flags: TCP_FLAG.acknowledgement,
|
||||
payload: new TextEncoder().encode('GET / HTTP/1.1\nHost: x\n'),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const captured: CapturedFrame[] = [{ number, timeMilliseconds, frame: ethernet }];
|
||||
return { number, rows: captureRows(captured, { withAddresses: true }), layeredRows: captureRows(captured, { withAddresses: false }) };
|
||||
}
|
||||
|
||||
const words = (language: 'de' | 'en') => captureWords((key) => translate(language, key), language);
|
||||
const clock = new Date(2026, 9, 4, 8, 30, 0, 0).getTime();
|
||||
|
||||
describe("the data exchange window's cells", () => {
|
||||
it("writes a frame's row by its highest layer, in either language", () => {
|
||||
expect(frameCells(frame(3, 1_234), clock, words('de'))).toEqual(['3', '08:30:01.234', '10.0.0.1:50000', '10.0.0.2:80', 'HTTP', 'Anwendung', 'GET / HTTP/1.1\nHost: x\n']);
|
||||
expect(frameCells(frame(3, 1_234), clock, words('en'))).toEqual(['3', '08:30:01.234', '10.0.0.1:50000', '10.0.0.2:80', 'HTTP', 'Application', 'GET / HTTP/1.1\nHost: x\n']);
|
||||
expect(words('de').header).toEqual(['Nr.', 'Zeit', 'Quelle', 'Ziel', 'Protokoll', 'Schicht', 'Bemerkungen / Details']);
|
||||
expect(words('en').header).toEqual(['No.', 'Time', 'Source', 'Destination', 'Protocol', 'Layer', 'Comment / Details']);
|
||||
});
|
||||
|
||||
it("writes the details with the locale's numbers and Java's words", () => {
|
||||
const german = frameDetails(frame(3, 0), clock, words('de')).map((line) => line.text);
|
||||
expect(german[0]).toBe('Nr.: 3 / Zeit: 08:30:00.000');
|
||||
expect(german).toContain('Bemerkungen / Details: SEQ: 2.000.001, ACK: 1.000.001');
|
||||
expect(german).toContain('Bemerkungen / Details: Protokoll: 6, TTL: 64');
|
||||
expect(german).toContain('Bemerkungen / Details (23 Bytes): ');
|
||||
const english = frameDetails(frame(3, 0), clock, words('en')).map((line) => line.text);
|
||||
expect(english[0]).toBe('No.: 3 / Time: 08:30:00.000');
|
||||
expect(english).toContain('Comment / Details: SEQ: 2,000,001, ACK: 1,000,001');
|
||||
expect(english).toContain('Comment / Details: Protocol: 6, TTL: 64');
|
||||
expect(frameDetails({ number: 1, rows: [], layeredRows: [] }, clock, words('de'))).toEqual([]);
|
||||
});
|
||||
|
||||
it('exports the table with the words of its header', () => {
|
||||
const text = exportText([frame(1, 0), frame(2, 5)], clock, words('en'));
|
||||
expect(text.split('\r\n')[1]).toBe(
|
||||
`| No. | Time | Source | Destination | Protocol | Layer | ${'Comment / Details'.padEnd(40)} | `,
|
||||
);
|
||||
expect(text.split('\r\n')[3]).toBe(
|
||||
`| 1 | 08:30:00.000 | 10.0.0.1:50000 | 10.0.0.2:80 | HTTP | Application | ${'GET / HTTP/1.1 Host: x'.padEnd(40)} | `,
|
||||
);
|
||||
expect(text.match(/^\+-/gm)).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
@@ -244,6 +244,26 @@ const FROM_JAVA: Readonly<Record<string, string>> = {
|
||||
'installation.apply': 'installationsdialog_msg2',
|
||||
'mode.currentSpeed': 'guimainmemu_msg15',
|
||||
'menu.showDesktop': 'guievents_msg3',
|
||||
'capture.title': 'lauscherdialog_msg1',
|
||||
'capture.number': 'rp_lauscher_msg1',
|
||||
'capture.time': 'rp_lauscher_msg2',
|
||||
'capture.source': 'rp_lauscher_msg3',
|
||||
'capture.destination': 'rp_lauscher_msg4',
|
||||
'capture.protocol': 'rp_lauscher_msg5',
|
||||
'capture.layer': 'rp_lauscher_msg6',
|
||||
'capture.comment': 'rp_lauscher_msg7',
|
||||
'capture.networkAccess': 'rp_lauscher_msg8',
|
||||
'capture.internet': 'rp_lauscher_msg9',
|
||||
'capture.transport': 'rp_lauscher_msg10',
|
||||
'capture.application': 'rp_lauscher_msg11',
|
||||
'capture.protocolWord': 'rp_lauscher_msg12',
|
||||
'capture.searchForMac': 'rp_lauscher_msg13',
|
||||
'capture.macIs': 'rp_lauscher_msg14',
|
||||
'capture.clear': 'nachrichtentabelle_msg7',
|
||||
'capture.autoscroll': 'nachrichtentabelle_msg8',
|
||||
'capture.export': 'nachrichtentabelle_msg9',
|
||||
'capture.closeTab': 'buttontabcomponent_msg1',
|
||||
'menu.showCapture': 'guievents_msg4',
|
||||
'desktop.home': 'desktoppanel_application',
|
||||
'desktop.installation': 'desktoppanel_msg1',
|
||||
'network.ipAddress': 'network_msg1',
|
||||
|
||||
Reference in New Issue
Block a user