Files
mdg-filius/packages/editor/browser/firewall.spec.ts
T
julian.kiedaischandClaude Opus 5.5 16d9cc2095 feat(editor): the simulation opens sheets, not windows in the window
A tap on a device in the simulation now only chooses it; its three-dot
button (or a long press) opens what Java's click opened: the desktop, and
newly a switch's SAT table and a home router's NAT table, beside each
card's data exchange.

The desktop, the tables and the data exchange are no windows in the
window any more but the simulation's sheet (SimulationSheet), after the
dashboard's AppSheet: below the toolbar to the bottom, a head with icon,
title, who else has it open, see-through and close. One at a time — it
covers the surface. It stays over a return to the design with the program
open on a desktop; a sheet whose device was removed closes. See-through
fades the body (0.55) and keeps the head; the choice is kept in the
browser. Java opens these as movable windows, several at once, with a
click; named in CHANGES.md.

Tests open through the menu (showFromMenu, showDesktop in editorPage.ts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 17:18:25 +00:00

109 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// A computer's firewall on its desktop in Chromium (F4.6g3), on FILIUS'
// example email_komplett with the firewall installed on its web server:
// Java's boxes, a port refused and one added, a notebook's browser let
// through by the rule, ICMP no longer allowed and a ping dropped (both in the
// log), the firewall switched off (the boxes beneath it can no longer be
// changed), the rule chosen and removed.
import { expect, test, type Page } from '@playwright/test';
import { drawing, onDevice, openEditor, serveEditor, showDesktop } from './editorPage.js';
let server: { readonly base: string; readonly close: () => Promise<void> };
test.beforeAll(async () => {
server = await serveEditor();
});
test.afterAll(async () => {
await server.close();
});
async function desktopOf(page: Page, name: string) {
const id = (await drawing(page)).nodes.find((node) => node.name === name)!.id;
return showDesktop(page, id);
}
async function install(page: Page, desktop: ReturnType<Page['locator']>, program: string) {
await desktop.locator('[data-program="installation"]').click();
const installation = desktop.locator('[data-program-window="installation"]');
await installation.locator('[data-list="available"] [role="option"]').filter({ hasText: program }).click();
await installation.getByRole('button', { name: 'Installieren' }).click();
await installation.getByRole('button', { name: 'Änderungen annehmen' }).click();
}
test('keeps a computer’s firewall as Java’s window does, and the firewall lets through what its rules open', async ({ page }) => {
test.setTimeout(120_000);
await openEditor(page, server.base, 'email_komplett.fls');
await page.getByRole('button', { name: 'Wechselt in den Aktionsmodus' }).click();
await expect(page.locator('svg.filius-canvas')).toHaveAttribute('data-mode', 'simulation');
const desktop = await desktopOf(page, 'Web-Server');
await install(page, desktop, 'Firewall');
await desktop.locator('[data-program="firewall"]').click();
const window = desktop.locator('[data-program-window="firewall"]');
await expect(window.locator('.program-titlebar h3')).toHaveText('Firewall');
await expect(window.getByRole('tab')).toHaveText(['Konfiguration', 'Log']);
const active = window.getByRole('checkbox', { name: 'Firewall aktivieren' });
const icmp = window.getByRole('checkbox', { name: 'Internet Control Message Protocol (Ping etc.) erlauben' });
await expect(active).toBeChecked();
await expect(icmp).toBeChecked();
await expect(window.getByRole('checkbox', { name: 'Aktiviere UDP-Datenverkehrfilter' })).toBeChecked();
await expect(window.getByText('Die Firewall blockiert alle eingehenden IP-Pakete')).toBeVisible();
// A port that is none is marked and not handed over; 80 is added and the field emptied.
const port = window.getByRole('textbox', { name: 'Zulässiger Port/Protokoll:' });
const add = window.getByRole('button', { name: 'Hinzufügen' });
await port.fill('70000');
await expect(port).toHaveAttribute('aria-invalid', 'true');
await expect(add).toBeDisabled();
await port.fill('80');
await add.click();
const rows = window.getByRole('table', { name: 'Regeln' }).locator('tbody tr');
await expect(rows).toHaveCount(1);
await expect(rows.first().locator('td')).toHaveText(['TCP', '80', 'Alle Absender']);
await expect(port).toHaveValue('');
// A notebook's browser is let through by the rule; the log says so.
await desktop.locator('.simulation-sheet__close').click();
const notebook = await desktopOf(page, 'Rechner 1');
await notebook.locator('[data-program="webBrowser"]').click();
const browser = notebook.locator('[data-program-window="webBrowser"]');
const address = browser.getByRole('textbox', { name: 'Adresse' });
await address.fill('141.99.50.231');
await address.press('Enter');
await expect(browser.frameLocator('iframe[title="Seite"]').locator('body')).not.toBeEmpty({ timeout: 30_000 });
// ICMP no longer allowed: the notebook's ping is dropped.
await notebook.locator('.simulation-sheet__close').click();
await desktopOf(page, 'Web-Server');
await desktop.locator('[data-program="firewall"]').click();
await icmp.click();
await expect(icmp).not.toBeChecked();
await desktop.locator('.simulation-sheet__close').click();
await desktopOf(page, 'Rechner 1');
await install(page, notebook, 'Befehlszeile');
await notebook.locator('[data-program="commandPrompt"]').click();
const input = notebook.locator('input[name="terminalInput"]');
await input.fill('ping 141.99.50.231');
await input.press('Enter');
await expect(notebook.locator('.terminal-text')).toContainText('0 Paket(e) empfangen', { timeout: 60_000 });
await notebook.locator('.simulation-sheet__close').click();
await desktopOf(page, 'Web-Server');
await desktop.locator('[data-program="firewall"]').click();
await window.getByRole('tab', { name: 'Log' }).click();
const log = window.getByRole('tabpanel', { name: 'Log' });
await expect(log).toContainText('Portregel wurde hinzugefügt: 80/TCP\nFirewall-Regel hat gegriffen: #1 (*/* -> */*; TCP:80 => ACCEPT) -> akzeptieren');
await expect(log).toContainText('ICMP-Paket verworfen: 141.99.50.181 -> 141.99.50.231 (code: 0, type: 8)');
// Off: the two boxes beneath it can no longer be changed; the rule chosen and removed.
await window.getByRole('tab', { name: 'Konfiguration' }).click();
await active.click();
await expect(active).not.toBeChecked();
await expect(icmp).toBeDisabled();
await expect(window.getByRole('button', { name: 'Löschen' })).toBeDisabled();
await rows.first().dispatchEvent('pointerdown');
await window.getByRole('button', { name: 'Löschen' }).click();
await expect(rows).toHaveCount(0);
await window.getByRole('tab', { name: 'Log' }).click();
await expect(log).toContainText('Portregel wurde entfernt.');
});