Files
mdg-filius/packages/editor/browser/mail.spec.ts
T
julian.kiedaischandClaude Opus 5.5 11f13bca84 feat(editor): F4.6e the e-mail program and e-mail server on a computer's desktop
The oracle MailWindowRun uses Java's e-mail windows as a person does and
answers their dialogs. The core sets and saves the program's account,
deletes a mail, checks a form as Java's window does, and gives the server
its domain, new and removed accounts and the window's own line; the room
sends both programs' views and takes their actions; the editor has both
windows. Better than Java: a name field for a new account, a user name the
server has is refused, deleting hits the folder shown, a new domain goes
into the accounts file at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:44:36 +00:00

197 lines
12 KiB
TypeScript

// The e-mail program and the e-mail server on a computer's desktop in
// Chromium (F4.6e), on FILIUS' example email_komplett: a mail written with
// Java's checks and sent, the server's accounts and lines, the mail fetched,
// chosen, answered and deleted, the account dialog; the server's new account,
// its question before it removes one, its domain only while it is off.
import { expect, test, 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 start(page: Page): Promise<void> {
await page.getByRole('button', { name: 'Wechselt in den Aktionsmodus' }).click();
await expect(page.locator('svg.filius-canvas')).toHaveAttribute('data-mode', 'simulation');
}
/** Opens a computer's desktop with a tap and a program's window on it. */
async function openProgram(page: Page, name: string, program: string) {
const id = (await drawing(page)).nodes.find((node) => node.name === name)!.id;
const at = await onDevice(page, id);
await page.mouse.click(at.x, at.y);
const desktop = page.locator(`section[data-desktop="${id}"]`);
await desktop.locator(`[data-program="${program}"]`).click();
return { desktop, window: desktop.locator(`[data-program-window="${program}"]`) };
}
test("writes, sends, fetches, answers and deletes mails as Java's e-mail program does", async ({ page }) => {
test.setTimeout(120_000);
await openEditor(page, server.base, 'email_komplett.fls');
await start(page);
const one = await openProgram(page, 'Rechner 1', 'emailClient');
const window = one.window;
await expect(window.locator('.mail-welcome')).toHaveText('Willkommen in der E-Mail-Anwendung!');
await expect(window.getByRole('tab', { name: 'Posteingang' })).toHaveAttribute('aria-selected', 'true');
// The account dialog shows the account, as Java's does.
await window.getByRole('button', { name: 'Konto einrichten' }).click();
const dialog = window.getByRole('form', { name: 'E-Mail-Konto verwalten' });
await expect(dialog.getByRole('textbox', { name: 'Name:', exact: true })).toHaveValue('Rechner 1');
await expect(dialog.getByRole('textbox', { name: 'E-Mail-Adresse:' })).toHaveValue('rechner1@filius.de');
await dialog.getByRole('textbox', { name: 'SMTP-Port:' }).fill('25x');
await dialog.getByRole('button', { name: 'Speichern' }).click();
await expect(window.getByRole('alertdialog')).toHaveText(/Die Angaben sind entweder fehlerhaft oder unvollständig!/);
await window.getByRole('alertdialog').getByRole('button', { name: 'OK' }).click();
await dialog.getByRole('button', { name: 'Abbrechen' }).click();
await expect(dialog).toHaveCount(0);
// Writing: Java's checks, then sent; the window shows the sent mails.
await window.getByRole('button', { name: 'Neue E-Mail verfassen' }).click();
const compose = window.getByRole('form', { name: 'E-Mail verfassen' });
await compose.getByRole('textbox', { name: 'An:' }).fill('rechner2@filius.de, kein');
await expect(compose.getByRole('textbox', { name: 'An:' })).toHaveAttribute('aria-invalid', 'true');
await compose.getByRole('button', { name: 'Senden' }).click();
await expect(window.getByRole('alertdialog')).toHaveText(/Mindestens eine eingegebene E-Mail-Adresse ist nicht korrekt!/);
await window.getByRole('alertdialog').getByRole('button', { name: 'OK' }).click();
await compose.getByRole('textbox', { name: 'An:' }).fill('');
await compose.getByRole('button', { name: 'Senden' }).click();
await expect(window.getByRole('alertdialog')).toHaveText(/Sie müssen mindestens eine Empfänger-Adresse eingeben!/);
await window.getByRole('alertdialog').getByRole('button', { name: 'OK' }).click();
await compose.getByRole('textbox', { name: 'An:' }).fill('rechner2@filius.de');
await compose.getByRole('textbox', { name: 'Betreff:' }).fill('Hallo Zwei');
await compose.getByRole('textbox', { name: 'Text der E-Mail' }).fill('Erste Zeile\nZweite Zeile');
await compose.getByRole('button', { name: 'Senden' }).click();
await expect(compose).toHaveCount(0);
await expect(window.getByRole('tab', { name: 'Gesendete' })).toHaveAttribute('aria-selected', 'true');
await expect(window.getByRole('tabpanel').locator('tbody tr').last()).toHaveText(/<rechner2@filius\.de>\s*Hallo Zwei/, { timeout: 30_000 });
await one.desktop.getByRole('button', { name: 'Schließen' }).click();
// The server holds it; its lines show the dialogue.
const mailServer = await openProgram(page, 'Mail-Server (filius.de)', 'emailServer');
await mailServer.window.getByRole('tab', { name: 'Konten-Liste' }).click();
await expect(mailServer.window.getByRole('tabpanel').locator('tbody tr')).toHaveText([/rechner1@filius\.de/, /rechner2@filius\.de\s*\d+/]);
await mailServer.window.getByRole('tab', { name: 'Log Fenster' }).click();
await expect(mailServer.window.getByRole('tabpanel')).toContainText('E-Mail für rechner2 im Postfach gespeichert.');
await mailServer.desktop.getByRole('button', { name: 'Schließen' }).click();
// Fetched, chosen, answered, deleted.
const two = await openProgram(page, 'Rechner 2', 'emailClient');
// Fetching shows the inbox, from any folder.
await two.window.getByRole('tab', { name: 'Gesendete' }).click();
await two.window.getByRole('button', { name: 'E-Mails abrufen' }).click();
await expect(two.window.getByRole('tab', { name: 'Posteingang' })).toHaveAttribute('aria-selected', 'true');
const rows = two.window.getByRole('tabpanel').locator('tbody tr');
await expect(rows.filter({ hasText: 'Hallo Zwei' })).toHaveCount(1, { timeout: 30_000 });
await expect(rows.filter({ hasText: 'Hallo Zwei' })).toHaveText(/Rechner 1\s*Hallo Zwei/);
await rows.filter({ hasText: 'Hallo Zwei' }).click();
await expect(two.window.locator('.mail-preview pre')).toHaveText(/Erste Zeile\nZweite Zeile/);
await two.window.getByRole('button', { name: 'E-Mail beantworten' }).click();
const reply = two.window.getByRole('form', { name: 'E-Mail verfassen' });
await expect(reply.getByRole('textbox', { name: 'An:' })).toHaveValue('Rechner 1 <rechner1@filius.de>');
await expect(reply.getByRole('textbox', { name: 'Betreff:' })).toHaveValue('RE: Hallo Zwei');
await expect(reply.getByRole('textbox', { name: 'Text der E-Mail' })).toHaveValue(/^\n\nRechner 1 <rechner1@filius\.de> schrieb:\n> Erste Zeile\n> Zweite Zeile/);
// Sent: the window shows the sent mails, the answer among them.
await reply.getByRole('button', { name: 'Senden' }).click();
await expect(two.window.getByRole('tab', { name: 'Gesendete' })).toHaveAttribute('aria-selected', 'true');
await expect(rows.filter({ hasText: 'RE: Hallo Zwei' })).toHaveCount(1, { timeout: 30_000 });
// The mail chosen belongs to its folder: chosen here, nothing is chosen in the inbox, and deleting deletes nothing there (Java's deleted one).
await rows.filter({ hasText: 'RE: Hallo Zwei' }).click();
await expect(two.window.locator('.mail-preview pre')).toHaveText(/schrieb:/);
await two.window.getByRole('tab', { name: 'Posteingang' }).click();
const inboxBefore = await rows.count();
await expect(two.window.locator('.mail-welcome')).toBeVisible();
await two.window.getByRole('button', { name: 'E-Mail löschen' }).click();
await expect(rows).toHaveCount(inboxBefore);
const before = await rows.count();
await rows.filter({ hasText: 'Hallo Zwei' }).click();
await two.window.getByRole('button', { name: 'E-Mail löschen' }).click();
await expect(rows).toHaveCount(before - 1);
await expect(rows.filter({ hasText: 'Hallo Zwei' })).toHaveCount(0);
await expect(two.window.locator('.mail-welcome')).toBeVisible();
});
test("makes and removes accounts and sets the domain as Java's e-mail server window does", async ({ page }) => {
test.setTimeout(120_000);
await openEditor(page, server.base, 'email_komplett.fls');
await start(page);
const { window } = await openProgram(page, 'Mail-Server (filius.de)', 'emailServer');
const domain = window.getByRole('textbox', { name: 'Maildomain:' });
await expect(domain).toHaveValue('filius.de');
await expect(domain).toBeDisabled();
// A new account: Java's checks, one the server has already, then made.
const form = window.getByRole('tabpanel', { name: 'Neues Konto' });
const create = form.getByRole('button', { name: 'Konto erstellen' });
await create.click();
await expect(form.getByRole('status')).toHaveText('Geben Sie einen Benutzernamen und ein Passwort ein!');
await form.getByRole('textbox', { name: 'Benutzername:' }).fill('carl os');
await form.getByLabel('Passwort:').fill('x');
await create.click();
await expect(form.getByRole('status')).toHaveText('Der Benutzername darf keine Leerzeichen enthalten!');
await form.getByRole('textbox', { name: 'Benutzername:' }).fill('RECHNER1');
await create.click();
await expect(form.getByRole('status')).toHaveText('Das Benutzerkonto RECHNER1 gibt es schon.');
await form.getByRole('textbox', { name: 'Benutzername:' }).fill('neu');
await form.getByRole('textbox', { name: 'Vorname und Nachname:' }).fill('Neue Nutzerin');
await create.click();
await expect(form.getByRole('status')).toHaveText('Das Benutzerkonto neu wurde angelegt.');
await expect(form.getByRole('textbox', { name: 'Benutzername:' })).toHaveValue('');
// The list: chosen, asked, removed.
await window.getByRole('tab', { name: 'Konten-Liste' }).click();
const list = window.getByRole('tabpanel', { name: 'Konten-Liste' });
await expect(list.locator('tbody tr')).toHaveText([/rechner1@filius\.de/, /rechner2@filius\.de/, /neu@filius\.de\s*0/]);
await expect(list.getByRole('button', { name: 'Markiertes Konto entfernen' })).toBeDisabled();
await list.locator('tbody tr').filter({ hasText: 'neu@' }).click();
await list.getByRole('button', { name: 'Markiertes Konto entfernen' }).click();
const question = list.getByRole('alertdialog', { name: 'Sicherheitsabfrage!' });
await expect(question).toContainText("Wollen Sie das Konto 'neu' wirklich entfernen?");
await question.getByRole('button', { name: 'Abbrechen' }).click();
await expect(list.locator('tbody tr')).toHaveCount(3);
await list.getByRole('button', { name: 'Markiertes Konto entfernen' }).click();
await list.getByRole('alertdialog').getByRole('button', { name: 'Ja' }).click();
await expect(list.locator('tbody tr')).toHaveCount(2);
// Stopped: the domain can be set, red where Java's pattern does not take it.
await window.getByRole('button', { name: 'Anhalten' }).click();
await expect(window.getByRole('button', { name: 'Starten' })).toBeVisible();
await expect(domain).toBeEnabled();
await domain.fill('kein domain!');
await expect(domain).toHaveAttribute('aria-invalid', 'true');
await domain.fill('schule.de');
await domain.press('Enter');
await expect(list.locator('tbody tr')).toHaveText([/rechner1@schule\.de/, /rechner2@schule\.de/]);
await window.getByRole('tab', { name: 'Log Fenster' }).click();
await expect(window.getByRole('tabpanel')).toContainText('POP3- und SMTP-Server wurden angehalten.');
});
test("shows the program's failure as Java's dialog does, and saves a new account", async ({ page }) => {
test.setTimeout(120_000);
await openEditor(page, server.base, 'email_komplett.fls');
await start(page);
const { window } = await openProgram(page, 'Rechner 1', 'emailClient');
await window.getByRole('button', { name: 'Konto einrichten' }).click();
const dialog = window.getByRole('form', { name: 'E-Mail-Konto verwalten' });
await dialog.getByRole('textbox', { name: 'SMTP-Server:' }).fill('niemand.filius.de');
await dialog.getByRole('textbox', { name: 'Name:', exact: true }).fill('Anna Maria Muster');
await dialog.getByRole('button', { name: 'Speichern' }).click();
await expect(dialog).toHaveCount(0);
await window.getByRole('button', { name: 'Konto einrichten' }).click();
await expect(dialog.getByRole('textbox', { name: 'Name:', exact: true })).toHaveValue('Anna Maria Muster');
await expect(dialog.getByRole('textbox', { name: 'SMTP-Server:' })).toHaveValue('niemand.filius.de');
await dialog.getByRole('button', { name: 'Abbrechen' }).click();
await window.getByRole('button', { name: 'Neue E-Mail verfassen' }).click();
const compose = window.getByRole('form', { name: 'E-Mail verfassen' });
await compose.getByRole('textbox', { name: 'An:' }).fill('rechner2@filius.de');
await compose.getByRole('button', { name: 'Senden' }).click();
await expect(window.getByRole('alertdialog')).toHaveText(/Ziel konnte nicht bestimmt werden!/, { timeout: 60_000 });
});