Anruf: der Lautsprecher -- und warum es kein Freisprech-Knopf ist

Filipe: "die funktion lautsprecher fehlt."

Er ist das Gegenstueck zum Mikrofon: "Mikro aus" heisst, die anderen
hoeren MICH nicht -- "Lautsprecher aus" heisst, ICH hoere sie nicht.
Beides braucht man, aus verschiedenen Gruenden: das Mikro, wenn es bei
einem selbst laut ist; den Lautsprecher, wenn nebenher etwas laeuft
oder jemand ins Zimmer kommt.

WAS BEWUSST NICHT GEBAUT WURDE: der Umschalter zwischen Hoermuschel
und Freisprechen, den ein Telefon hat. Recherchiert statt geraten --
den gibt es im Browser nicht: Auf dem iPhone entscheidet Safari
selbst, wohin der Ton geht, und Android laesst einzelne Toene gar
nicht auf ein anderes Geraet legen (setSinkId ist dort nicht
verfuegbar, weil die Plattform es nicht hergibt). Ein Knopf, der dort
nichts tut, waere schlimmer als keiner -- man drueckt ihn und sucht
den Fehler dann bei sich.

Wo es GEHT (Rechner mit Chrome, Edge, Safari), steht dafuer eine echte
Geraeteauswahl daneben. Sie erscheint nur, wenn es mehr als ein Geraet
gibt UND die Namen bekannt sind; eine Auswahl mit einem Eintrag ist
keine Auswahl, sondern eine Behauptung.

DIE PRUEFUNG, AUF DIE ES ANKOMMT: Kommt jemand dazu oder geht jemand,
werden die Toenelemente NEU GEBAUT -- und neue Elemente wissen nichts
von einem Schalter, der vorher umgelegt wurde. Genau daran scheitern
solche Knoepfe sonst: Sie wirken, bis sich die Runde aendert, und dann
hoert man ploetzlich wieder mit. Gegenprobe (Anwenden nach dem
Neuzeichnen ausgebaut) macht genau diese eine Pruefung rot, waehrend
alle anderen gruen bleiben.

Geprueft: pruef-anruf 73 -> 80, im echten Dreiergespraech im Browser.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-18 17:08:31 +02:00
co-authored by Claude Opus 5
parent 59c84bd248
commit e933de3248
36 changed files with 589 additions and 402 deletions
+63
View File
@@ -628,6 +628,58 @@ melde("=== 8. Zu dritt ===");
`${wer} hoert BEIDE anderen (${z.stroeme} Stroeme, „${z.lage}")`);
}
/* ---- DER LAUTSPRECHER (18.09.2026) -------------------------
Filipe: „die funktion lautsprecher fehlt."
Gegenstueck zum Mikrofon: „Mikro aus" heisst, die anderen
hoeren mich nicht; „Lautsprecher aus" heisst, ich hoere sie
nicht.
DIE PRUEFUNG, AUF DIE ES ANKOMMT, ist die dritte: Kommt
jemand dazu oder geht jemand, werden die Toenelemente NEU
GEBAUT -- und neue Elemente wissen nichts von einem Schalter,
der vorher umgelegt wurde. Genau daran scheitern solche
Knoepfe sonst: Sie wirken, bis sich die Runde aendert, und
dann hoert man ploetzlich wieder mit. */
const stumm = (x) => x.se.evaluate(() =>
[...document.querySelectorAll("#anruf-leute audio, #anruf-leute video")]
.filter((m) => !m.classList.contains("anruf__bild--ich"))
.map((m) => m.muted));
{
const vorher = await stumm(a);
/* Die ANZAHL gehoert in die Bedingung: `every` ist auf einer
leeren Liste wahr, und dann waere diese Pruefung gruen,
ohne ein einziges Element gesehen zu haben. */
ok(vorher.length >= 2 && vorher.every((m) => m === false),
`vorher hoert DogFather beide (${vorher.length} Stroeme, keiner stumm)`);
const knopf = await a.se.evaluate(() => {
const k = document.getElementById("anruf-hoeren");
return k ? { text: k.textContent.trim(), an: k.getAttribute("aria-pressed") } : null;
});
ok(knopf?.text === "Lautsprecher an" && knopf?.an === "true",
`der Lautsprecher-Knopf ist da und steht auf an („${knopf?.text}")`);
await a.se.click("#anruf-hoeren");
await a.se.waitForTimeout(300);
const nachher = await stumm(a);
ok(nachher.length >= 2 && nachher.every((m) => m === true),
`nach dem Druecken ist ALLES stumm (${nachher.length} Stroeme)`);
const knopf2 = await a.se.evaluate(() => {
const k = document.getElementById("anruf-hoeren");
return { text: k.textContent.trim(), an: k.getAttribute("aria-pressed") };
});
ok(knopf2.text === "Lautsprecher aus" && knopf2.an === "false",
`und der Knopf sagt es auch („${knopf2.text}")`);
/* NUR BEI IHM. Ein Schalter, der bei den anderen mitwirkt,
waere kein Lautsprecher, sondern eine Fernbedienung. */
const beiB = await stumm(b);
ok(beiB.length >= 2 && beiB.every((m) => m === false),
`bei der rechten Hand aendert sich nichts (${beiB.length} Stroeme, keiner stumm)`);
}
/* Einer legt auf -- fuer die anderen laeuft es weiter. */
await c.se.click("#anruf-auflegen");
await c.se.waitForTimeout(2000);
@@ -638,6 +690,17 @@ melde("=== 8. Zu dritt ===");
ok(zA.stroeme === 1,
`und bei DogFather ist genau ein Strom weniger (${zA.stroeme})`);
/* DIE FALLE: Die Runde hat sich geaendert, die Elemente wurden
neu gebaut. Bliebe der Schalter dabei auf der Strecke, wuerde
DogFather ploetzlich wieder mithoeren -- ohne dass irgendwo
etwas anders aussieht. */
const nachWechsel = await stumm(a);
ok(nachWechsel.length === 1 && nachWechsel[0] === true,
`und der Lautsprecher bleibt aus, obwohl neu gezeichnet wurde (${nachWechsel.length} Strom)`);
const knopfNoch = await a.se.evaluate(() =>
document.getElementById("anruf-hoeren")?.getAttribute("aria-pressed"));
ok(knopfNoch === "false", "auch der Knopf steht noch richtig");
await a.se.click("#anruf-auflegen");
await b.se.click("#anruf-auflegen");
await a.se.waitForTimeout(1200);