Files
onyx/Packages/OnyxKit/Tests/OnyxMenuBarTests/MenuBarTextTests.swift
Scarriffle c44bb3af30 Menüleiste springt nicht mehr, Mixer fasst Hilfsprozesse zusammen
Die Breite folgte der Stellenzahl des aktuellen Werts. Aus „14 KB/s" wird
„431 KB/s", und mit der zusätzlichen Stelle wanderte die halbe Leiste. Jetzt
wieder feste Breiten, bemessen am breitesten Wert, der vorkommen kann.

Der frühere Fehler war nicht die feste Breite, sondern der falsche
Bezugswert: gezeichnet wird „63°", bemessen wurde „100 °C" — fünfzehn Punkte
für zwei Zeichen, die nie erscheinen. Nachgemessen: zwei Aufnahmen im
Abstand von sechs Sekunden mit geänderten Werten ergeben identische Breiten.

Der Mixer fasst Hilfsprozesse mit ihrem Programm zusammen. „Google Chrome"
und „Google Chrome Helper" standen als zwei Zeilen nebeneinander, mit
getrennten Reglern für dasselbe Programm — zieht man den einen, hört man
den anderen. Chrome hat je Tab einen Helfer; fünfzehn Regler für einen
Browser sind keine Auskunft.

Abgegriffen wird weiterhin je Prozess, geregelt aber je Programm. Der
Schlüssel der Taps muss deshalb den Prozess mitführen: mehrere Helfer teilen
sich eine Kennung und überschrieben sich sonst gegenseitig. Der Pegel einer
Zeile ist der lauteste ihrer Prozesse.

Die Zeilen sind einzeilig statt zweizeilig: Symbol, Stummschalter, Regler,
Wert. Der Name ist weg — bei einem erkennbaren Programmsymbol ist er
redundant, und die gewonnene Zeile macht die Liste halb so hoch. Dafür ist
das Symbol größer, und wer den Namen braucht, hält den Zeiger darauf.
Popover 420 statt 330 Punkte breit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 13:15:53 +02:00

85 lines
3.3 KiB
Swift

import Testing
import AppKit
@testable import OnyxMenuBar
@Suite("Breite in der Menüleiste")
struct MenuBarTextTests {
@Test("Die Breite folgt dem Text und nicht einer Schätzung")
func widthFollowsText() {
// Genau das war der Fehler: eine feste Zahl je Darstellungsart, so
// großzügig, dass neben jedem Wert Platz für ein weiteres Symbol blieb.
let short = MenuBarText.itemWidth(textWidth: 20, includesSymbol: false)
let long = MenuBarText.itemWidth(textWidth: 60, includesSymbol: false)
#expect(long > short)
#expect(short == 20 + 2 * MenuBarText.sidePadding)
}
@Test("Ein Symbol daneben braucht seinen Platz")
func symbolAddsWidth() {
let without = MenuBarText.itemWidth(textWidth: 40, includesSymbol: false)
let with = MenuBarText.itemWidth(textWidth: 40, includesSymbol: true)
#expect(with - without == MenuBarText.symbolWidth + MenuBarText.innerGap)
}
@Test("Ohne Text bleibt die Mindestbreite")
func emptyKeepsMinimum() {
// Ein Element ohne Zahl zeigt ein Glyph. Schrumpfte es auf null,
// verschwände es aus der Leiste.
#expect(MenuBarText.itemWidth(textWidth: 0, includesSymbol: false)
== MenuBarText.minimumWidth)
}
@Test("Die Breite wird aufgerundet")
func roundsUp() {
// Gebrochene Breiten führen zu unscharfem Text, weil die Zeichenfolge
// dann auf einem halben Bildpunkt sitzt.
let width = MenuBarText.itemWidth(textWidth: 20.3, includesSymbol: false)
#expect(width == width.rounded())
}
@Test("Ein längerer Verweistext ergibt ein breiteres Element")
func referenceDrivesWidth() {
#expect(MenuBarText.width(for: "100 %") > MenuBarText.width(for: "9 %"))
}
@Test("Gleich lange Zahlen sind gleich breit")
func digitsAreMonospaced() {
// Ohne feste Ziffernbreite springt die Leiste bei jedem Messwert.
#expect(MenuBarText.width(of: "111") == MenuBarText.width(of: "888"))
}
}
// Ein Menüleistenelement darf seine Breite **nicht** ändern, wenn sich der
// Messwert ändert sonst rutschen alle Symbole rechts davon mit. Das gilt auch
// dann, wenn eine Stelle dazukommt: aus 14 KB/s" wird 431 KB/s", und die
// halbe Leiste wandert.
//
// Also eine feste Breite je Darstellung, bemessen am breitesten Wert, der
// vorkommen kann. Der frühere Fehler war nicht die feste Breite, sondern ein
// falscher Bezugswert: 100 °C" statt 100°" ist rund 15 Punkte zu viel.
@Suite("Feste Breite")
struct FixedWidthTests {
@Test("Der Bezugswert hängt nicht vom Messwert ab")
func referenceIsIndependentOfValue() {
#expect(MenuBarText.width(for: "100 %") == MenuBarText.width(for: "100 %"))
}
@Test("Ein Bezugswert deckt alle kürzeren ab")
func referenceCoversShorterValues() {
// Was hineinpasst, wird nicht abgeschnitten.
for value in ["0 %", "9 %", "34 %", "100 %"] {
#expect(MenuBarText.width(of: value) <= MenuBarText.width(of: "100 %"))
}
}
@Test("Grad ohne Einheitenbuchstaben ist deutlich schmaler")
func degreeWithoutUnitIsNarrower() {
// Der eigentliche Fund: gezeichnet wird 63°", bemessen wurde früher
// 100 °C".
#expect(MenuBarText.width(of: "100°") < MenuBarText.width(of: "100 °C") - 10)
}
}