Files
julian.kiedaischandClaude Opus 5.5 12b26f4abe feat(editor): the simulation's properties in a sheet of their own, with a restart for everyone
Who started the simulation, "Pakete verwerfen" and the dropped packets move
from the toolbar into a properties sheet beside the surface. New in it: restart
the simulation, after asking. The room learns a restart message: stopped as by
stop, every capture, dropped frame and program window emptied, started anew
and named after who restarted; refused for readers and frozen projects, logged,
and waiting for asked blobs like a start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:01:41 +00:00

56 lines
2.7 KiB
TypeScript

// The editor as the image delivers it (F5.6b): built, packed, and handed out
// by server F itself, so that the page comes from F's own origin and takes it
// for its server — no `&server=` in the address. Two people in one project
// see each other, and a simulation one starts runs for the other; the
// bundle arrives packed with brotli.
import { mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { expect, test, type Browser, type Page } from '@playwright/test';
import { precompress } from '../../server/src/precompress.js';
import { buildEditor } from './editorPage.js';
import { startServerF, type ServerF } from './serverF.js';
let f: ServerF;
test.beforeAll(async () => {
const folder = mkdtempSync(join(tmpdir(), 'filius-editor-from-f-'));
await buildEditor(folder);
await precompress(folder);
f = await startServerF('http://localhost', folder);
});
test.afterAll(async () => {
await f?.close();
});
async function person(browser: Browser, project: string, name: string, user: string): Promise<{ readonly page: Page; readonly encodings: Map<string, string> }> {
const context = await browser.newContext();
await f.signIn(context, project, { name, user });
const page = await context.newPage();
const encodings = new Map<string, string>();
page.on('response', async (response) => {
const path = new URL(response.url()).pathname;
if (path.startsWith('/assets/index-') && path.endsWith('.js')) encodings.set(path, (await response.allHeaders())['content-encoding'] ?? 'none');
});
await page.goto(`${f.base}/?project=${project}`);
await page.waitForSelector('svg.filius-canvas');
return { page, encodings };
}
test('the editor from F itself: two people, one simulation, the bundle packed', async ({ browser }) => {
const project = await f.project('java-examples/internetwork_komplett.fls');
const [miaUser, benUser] = [crypto.randomUUID(), crypto.randomUUID()];
const mia = await person(browser, project.id, 'Mia', miaUser);
const ben = await person(browser, project.id, 'Ben', benUser);
await expect(mia.page.locator(`[data-person="${benUser}"]`)).toBeVisible();
await expect(ben.page.locator(`[data-person="${miaUser}"]`)).toBeVisible();
await expect(ben.page.locator('g.device')).toHaveCount(await mia.page.locator('g.device').count());
await mia.page.locator('button[name="simulationMode"]').click();
await expect(ben.page.locator('svg.filius-canvas')).toHaveAttribute('data-mode', 'simulation');
await ben.page.getByRole('button', { name: 'Eigenschaften' }).click();
await expect(ben.page.locator('[data-note="startedBy"]')).toHaveText('Simulation gestartet von Mia');
expect([...mia.encodings.values()]).toEqual(['br']);
});