feat: Etherpad-Anbindung ausgebaut (D78)
D31 lieh sich fuer die Echtzeit-Zusammenarbeit ein Etherpad: Das Pad war die Schreibflaeche, Werkbaum die Ansicht. Richtig fuer den Zeitpunkt - die schwere Arbeit war dort getan, und Werkbaum hatte kein Backend. Jetzt hat es eins (D76), das dasselbe besser und im Editor selbst kann. D31 bleibt stehen: Was dort gemessen wurde, ist der Grund, warum die Anbindung nie gut wurde - Export-Drosselung (10 je 90 s), SameSite=Lax beim Autoren-Cookie, abgelehnter Socket-Upgrade. Uebrig blieb ein Neu-laden-Knopf und ein schreibgeschuetztes Textfeld. Ein alter ?etherpad=-Link meldet sich, statt still nichts zu tun: Der Parameter bleibt erkannt und ergibt die zeilenlose Warnung padGone, die auf ?live= zeigt (neun Sprachen). Geholt wird nichts - nachgemessen geht keine Anfrage mehr an den Pad-Host. Vorhandene Pad-Dokumente bleiben liegen und werden dabei besser: ohne Schreibschutz sind sie bearbeitbar und sammeln fruehere Staende. Mit ausgebaut, weil sie nur der Anbindung dienten: remote.js samt Tests, der Ansichts-Waehler und sein Splitter, der Neu-laden-Knopf samt Drosselungs-Zaehler, die Warnungen sourceTimeout/padRateLimit, elf i18n- Schluessel x 9 Sprachen - und src.readOnly ganz, denn nur Pad-Dokumente haben es gesetzt (mit ihm updateSnapBtn und sieben tote Waechter). Auch #srcArea faellt weg: den Kasten gab es nur, damit Pad-Rahmen und Spiegel sich einen Bereich teilen. ?sourceUrl= bleibt unangetastet - beide teilten sich einen Fetch-Pfad, das war die Stelle, an der nichts verrutschen durfte. Im Plan wird aus dem #col.pad-Zweig (14 Knoten samt der ganzen "Update by itself"-Gruppe) ein verworfener Knoten mit Begruendung; der gemeinsame Zeigefinger wandert als #col.point heraus, denn !!! gilt jedem geteilten Dokument. 196 Knoten, 0 Warnungen. Nebengewinn: Der README bekommt endlich den Abschnitt zu ?live= - den gab es nie, die Einstiegs-Beschreibung stand weiter beim Pad. Nachgemessen im Browser: ?etherpad= zeigt die Warnung ohne Netz-Anfrage, ?sourceUrl= laedt unveraendert und ist beschreibbar, Textfeld und Zahlenstreifen liegen buendig, Legenden-Splitter teilt wie zuvor (954+10+300), Falten und Staende funktionieren. 501 Tests, 946 Zeilen weniger.
This commit is contained in:
@@ -1,69 +0,0 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { padUrls } from '../src/remote.js';
|
||||
|
||||
const PAD = 'https://pad.example.org/p/mein-plan';
|
||||
|
||||
describe('padUrls — Pad-Adresse normalisieren (D31)', () => {
|
||||
it('hängt den Klartext-Export an', () => {
|
||||
expect(padUrls(PAD)).toEqual({ pad: PAD, text: PAD + '/export/txt' });
|
||||
});
|
||||
|
||||
/* Derselbe Pad soll genau EIN Dokument ergeben — die Identität leitet sich
|
||||
aus `pad` ab, also müssen alle Schreibweisen darauf zusammenfallen. */
|
||||
it.each([
|
||||
['Schrägstrich am Ende', PAD + '/'],
|
||||
['mehrere Schrägstriche', PAD + '///'],
|
||||
['Export-Pfad mitgegeben', PAD + '/export/txt'],
|
||||
['anderer Export', PAD + '/export/html'],
|
||||
['Timeslider', PAD + '/timeslider'],
|
||||
['Query dran', PAD + '?showChat=false'],
|
||||
['Fragment dran', PAD + '#anker'],
|
||||
['Query und Schrägstrich', PAD + '/?showControls=false'],
|
||||
])('fällt auf dieselbe Pad-URL zusammen: %s', (_name, input) => {
|
||||
expect(padUrls(input)).toEqual({ pad: PAD, text: PAD + '/export/txt' });
|
||||
});
|
||||
|
||||
it('erlaubt eine Montage unter einem Unterpfad', () => {
|
||||
const sub = 'https://example.org/etherpad/p/plan';
|
||||
expect(padUrls(sub)).toEqual({ pad: sub, text: sub + '/export/txt' });
|
||||
});
|
||||
|
||||
it('erlaubt http neben https', () => {
|
||||
const h = 'http://pad.example.org/p/plan';
|
||||
expect(padUrls(h).pad).toBe(h);
|
||||
});
|
||||
|
||||
it('behält den Port', () => {
|
||||
const h = 'https://pad.example.org:9001/p/plan';
|
||||
expect(padUrls(h)).toEqual({ pad: h, text: h + '/export/txt' });
|
||||
});
|
||||
|
||||
/* Zwei Pads gleichen Namens auf verschiedenen Hosts müssen unterscheidbar
|
||||
bleiben — deshalb ist der Name die vollständige URL, nicht der Pad-Name. */
|
||||
it('unterscheidet gleichnamige Pads verschiedener Hosts', () => {
|
||||
expect(padUrls('https://a.example/p/plan').pad)
|
||||
.not.toBe(padUrls('https://b.example/p/plan').pad);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['kein /p/-Pfad', 'https://pad.example.org/mein-plan'],
|
||||
['nur der Host', 'https://pad.example.org'],
|
||||
['/p/ ohne Namen', 'https://pad.example.org/p/'],
|
||||
['fremdes Schema', 'file:///tmp/plan.txt'],
|
||||
['javascript:', 'javascript:alert(1)'],
|
||||
['data:', 'data:text/plain,foo'],
|
||||
['gar keine URL', 'nicht mal eine URL'],
|
||||
['leer', ''],
|
||||
])('weist ab: %s', (_name, input) => {
|
||||
expect(padUrls(input)).toBeNull();
|
||||
});
|
||||
|
||||
it('löst relative Angaben gegen die Seite auf, wenn eine Basis da ist', () => {
|
||||
expect(padUrls('/p/plan', 'https://pad.example.org/x/y').pad)
|
||||
.toBe('https://pad.example.org/p/plan');
|
||||
});
|
||||
|
||||
it('ohne Basis bleibt eine relative Angabe unbrauchbar', () => {
|
||||
expect(padUrls('/p/plan')).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -21,18 +21,11 @@ describe('formatWarning — vereinheitlichtes Warnungs-Modell', () => {
|
||||
expect(out).toBe('sourceLoadWarn|{"url":"https://a/?x=1&y=2","error":"HTTP 404"}');
|
||||
});
|
||||
|
||||
/* Eigener Typ, weil sourceLoadWarn auf CORS zeigt: Bei Etherpads Drosselung
|
||||
(10 Abrufe je 90 s) schickte das den Leser auf die falsche Fährte (D31). */
|
||||
it('sourceTimeout ist ein eigener Typ und nennt die Sekunden', () => {
|
||||
const out = formatWarning({type: 'sourceTimeout', url: 'https://p/x&y', seconds: 20}, t);
|
||||
expect(out).toBe('sourceTimeoutWarn|{"url":"https://p/x&y","seconds":20}');
|
||||
});
|
||||
|
||||
/* Kein `url` im Objekt: Der Nutzer hat gar nichts angefordert, was scheitern
|
||||
konnte — Werkbaum hat den Abruf verhindert (D31). */
|
||||
it('padRateLimit nennt die Restzeit und braucht keine URL', () => {
|
||||
expect(formatWarning({type: 'padRateLimit', seconds: 7}, t))
|
||||
.toBe('padRateLimitWarn|{"seconds":7}');
|
||||
/* Ein alter ?etherpad=-Link soll nicht still ins Leere laufen: Die Anbindung
|
||||
ist ausgebaut (D78), der Text zeigt auf ?live=. Ohne Platzhalter — die
|
||||
Meldung hat nichts einzusetzen. */
|
||||
it('padGone meldet den ausgebauten Eingang ohne Platzhalter', () => {
|
||||
expect(formatWarning({type: 'padGone'}, t)).toBe('padGoneWarn|undefined');
|
||||
});
|
||||
|
||||
it('unbekannter Typ fällt auf eine generische, escapte Meldung zurück', () => {
|
||||
|
||||
Reference in New Issue
Block a user