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>
197 lines
12 KiB
TypeScript
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 });
|
|
});
|