Files
mdg-filius/packages/editor/browser/gnutella.spec.ts
T
julian.kiedaischandClaude Opus 5.5 5224e1a28b feat: F4.6g4 the Gnutella window, measured against Java's
GnutellaWindowRun uses Java's Gnutella window on terminal-net beside the
line of GnutellaRun's story "search". The core cancels a search as Java
does (every connection of the program's own requests closed, passed-on
queries kept), lets the number of peers change and lists /peer2peer's
files; the room takes the window's actions and sends its view; the editor
shows Java's four tabs with Java's symbols. Not adopted from Java: a number
of peers of one digit only, a results table that keeps the last search's
rows, a files table that lags behind the folder.

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

113 lines
5.6 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.
// Gnutella on two notebooks' desktops in Chromium (F4.6g4), on FILIUS'
// example email_komplett with the program installed during the run: Java's
// four tabs, an address refused with Java's words, a peer joined, a file
// found on the other notebook and downloaded (the files tab shows it), the
// number of peers saved (also one Java refuses, and what is no number), the
// network left.
import { expect, test, type Locator, type Page } from '@playwright/test';
import { drawing, onDevice, openEditor, serveEditor } 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 idOf(page: Page, name: string) {
return (await drawing(page)).nodes.find((node) => node.name === name)!.id;
}
async function desktopOf(page: Page, name: string) {
const id = await idOf(page, name);
const at = await onDevice(page, id);
await page.mouse.click(at.x, at.y);
return page.locator(`section[data-desktop="${id}"]`);
}
async function install(desktop: 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('joins, searches and downloads as Java’s Gnutella window does', 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');
// The other notebook shares a file.
const other = await desktopOf(page, 'Rechner 2');
await install(other, 'Gnutella');
await expect(other.locator('[data-program="gnutella"]')).toBeVisible();
const otherId = await idOf(page, 'Rechner 2');
await page.evaluate(
(id) => (window as unknown as { filiusDev: { writeFile: (id: string, path: string, text: string) => void } }).filiusDev.writeFile(id, '/peer2peer/lied.txt', 'La la la'),
otherId,
);
await other.locator('.desktop-close').click();
const desktop = await desktopOf(page, 'Rechner 1');
await install(desktop, 'Gnutella');
await desktop.locator('[data-program="gnutella"]').click();
const window = desktop.locator('[data-program-window="gnutella"]');
await expect(window.locator('.program-titlebar h3')).toHaveText('Gnutella');
await expect(window.getByRole('tab')).toHaveText(['Netzwerk', 'Suche', 'Dateien', 'Einstellungen']);
// What is no address: red, and Java's words.
const address = window.getByRole('textbox', { name: 'Teilnehmer IP-Adresse:' });
await expect(address).toHaveValue('192.168.0.1');
await address.fill('141.99.50.300');
await expect(address).toHaveAttribute('aria-invalid', 'true');
await window.getByRole('button', { name: 'Netz beitreten' }).click();
await expect(window.getByRole('alert')).toHaveText('Dies ist keine gültige IP-Adresse');
await address.fill('141.99.50.182');
await window.getByRole('button', { name: 'Netz beitreten' }).click();
const peers = window.getByRole('table', { name: 'Liste der verbundenen Nachbarn:' }).locator('tbody tr');
await expect(peers).toHaveCount(1, { timeout: 30_000 });
await expect(peers.first().locator('td')).toHaveText(['1', '141.99.50.182']);
// The other's file found and downloaded.
await window.getByRole('tab', { name: 'Suche' }).click();
await window.getByRole('textbox', { name: 'Suchbegriff:' }).fill('lied');
await window.getByRole('button', { name: 'Suchen' }).click();
const results = window.getByRole('table', { name: 'Suche' }).locator('tbody tr');
await expect(results).toHaveCount(1, { timeout: 30_000 });
await expect(results.first().locator('td')).toHaveText(['141.99.50.182', 'lied.txt', '8 B']);
const download = window.getByRole('button', { name: 'Herunterladen' });
await expect(download).toBeDisabled();
await results.first().dispatchEvent('pointerdown');
await download.click();
// The list emptied: nothing is chosen any more.
await window.getByRole('button', { name: 'Liste leeren' }).click();
await expect(results).toHaveCount(0);
await expect(download).toBeDisabled();
await window.getByRole('tab', { name: 'Dateien' }).click();
await expect(window.getByRole('table', { name: 'Dateien' }).locator('tbody tr td')).toHaveText(['lied.txt', 'txt'], { timeout: 30_000 });
// The number of peers: 12 saved (Java takes one digit only), what is no number refused with Java's words.
await window.getByRole('tab', { name: 'Einstellungen' }).click();
const maximum = window.getByRole('textbox', { name: 'Maximale Anzahl direkter Nachbarn:' });
await expect(maximum).toHaveValue('3');
await maximum.fill('012');
await window.getByRole('button', { name: 'Speichern' }).click();
// The field shows the program's number once it is saved.
await expect(maximum).toHaveValue('12');
await expect(window.getByRole('alert')).toHaveCount(0);
await maximum.fill('x');
await expect(maximum).toHaveAttribute('aria-invalid', 'true');
await window.getByRole('button', { name: 'Speichern' }).click();
await expect(window.getByRole('alert')).toHaveText('Es sind nur Zahlen erlaubt!');
// The network left.
await window.getByRole('tab', { name: 'Netzwerk' }).click();
await window.getByRole('button', { name: 'Netz verlassen' }).click();
await expect(peers).toHaveCount(0);
});