Files
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

69 lines
4.3 KiB
TypeScript

// The e-mail windows' lines and checks against Java's
// (packages/sim/test/mailWindow.java.json, MailWindowRun): each kind of line
// the server's window got there in Java's words, what it leaves out, a
// failure's message, and the checks of a new account.
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import type { EmailServerLogEntry } from '@mdg-filius/core';
import { accountNames, newAccountProblem } from '../src/desktop/EmailServerPanel.js';
import { emailServerLine, mailFailureText } from '../src/desktop/mailLines.js';
import { translate } from '../src/i18n/i18n.js';
const java = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../../sim/test/mailWindow.java.json'), 'utf8')) as { steps: { step: string; log?: string }[] };
const log = (step: string) => java.steps.find((each) => each.step === step)!.log!;
const de = (key: string, values?: Readonly<Record<string, string | number>>) => translate('de', key, values);
const en = (key: string, values?: Readonly<Record<string, string | number>>) => translate('en', key, values);
describe("the e-mail server window's lines", () => {
it("are Java's, line by line", () => {
const after = log('server:after mails');
const entries: EmailServerLogEntry[] = [
{ kind: 'connectionOpened' },
{ kind: 'received', address: '192.168.0.20', text: 'MAIL FROM: <anna@schule.de>' },
{ kind: 'sent', address: '192.168.0.20', text: '250 Sender OK' },
{ kind: 'stored', username: 'anna' },
];
for (const entry of entries) expect(after, entry.kind).toContain(`${emailServerLine(entry, de)}\n`);
expect(log('server:start')).toBe(`${emailServerLine({ kind: 'switched', active: true }, de)}\n`);
expect(log('server:stop').endsWith(`\n${emailServerLine({ kind: 'switched', active: false }, de)}\n`)).toBe(true);
});
it("write the SMTP client's lines, and leave out its failures as Java's window does", () => {
expect(emailServerLine({ kind: 'connectionStarting' }, de)).toBe('----');
expect(emailServerLine({ kind: 'smtpConnected', address: '1.2.3.4', port: 25 }, de)).toBe('Verbindung zu 1.2.3.4:25 hergestellt');
expect(emailServerLine({ kind: 'smtpDisconnected', address: '1.2.3.4', port: 25 }, en)).toBe('Connection to 1.2.3.4:25 disconnected');
expect(emailServerLine({ kind: 'mailSent', recipients: 'a@b.de' }, de)).toBe('Mail versendet an a@b.de');
expect(emailServerLine({ kind: 'sendFailed', address: '1.2.3.4' }, de)).toBe('Fehler beim Senden an 1.2.3.4');
expect(emailServerLine({ kind: 'failed', failure: { kind: 'receiveFailed' } }, de)).toBeUndefined();
});
it("show a failure's message as Java's dialog does", () => {
expect(mailFailureText({ kind: 'answer', text: '-ERR wrong password' }, de)).toBe('-ERR wrong password');
expect(mailFailureText({ kind: 'connect', failure: 'unresolved' }, de)).toBe('Ziel konnte nicht bestimmt werden!');
expect(mailFailureText({ kind: 'connect', failure: 'timedOut' }, en)).toBe('Timeout while connecting');
expect(mailFailureText({ kind: 'connect', failure: 'failed' }, de)).toBe('Aktives Öffnen des Sockets fehlgeschlagen');
expect(mailFailureText({ kind: 'receiveFailed' }, de)).toBe('Verbindung nicht aufgebaut!');
});
});
describe('a new account', () => {
it("is checked as Java's window checks it, and refused where the server has the name", () => {
const accounts = [{ username: 'anna' }];
expect(newAccountProblem('', 'x', accounts)).toBe('missing');
expect(newAccountProblem('bob', '', accounts)).toBe('missing');
for (const name of ['carl os', 'a\tb', 'a\nb']) expect(newAccountProblem(name, 'x', accounts), name).toBe('whiteSpace');
expect(newAccountProblem('ANNA', 'x', accounts)).toBe('exists');
expect(newAccountProblem('bob', 'x', accounts)).toBeUndefined();
});
it("takes the name typed, and Java's placeholders without one", () => {
expect(accountNames('Neue Nutzerin', de)).toEqual({ firstName: 'Neue', lastName: 'Nutzerin' });
expect(accountNames('Anna', de)).toEqual({ firstName: 'Anna', lastName: '' });
expect(accountNames(' ', de)).toEqual({ firstName: 'Vorname', lastName: 'Nachname' });
expect(accountNames('', en)).toEqual({ firstName: 'First name', lastName: 'Last name' });
});
});