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")) } } // Eine Breite, die dem Höchstwert der letzten Messungen folgt, ist bei einem // Wert, der ständig schwankt, fast immer zu groß: der Netzwerkdurchsatz // wechselt im Sekundentakt, und das Element blieb dauerhaft auf der Breite // eines vergangenen Ausschlags stehen. Die Differenz stand als Lücke daneben. // // Stattdessen: die Ziffern durch Neunen ersetzen. Das ergibt die breiteste // Zeichenfolge **derselben Gestalt** — die Breite ändert sich dann nur noch, // wenn eine Stelle dazukommt oder die Einheit wechselt. @Suite("Breite gleicher Gestalt") struct DigitShapeTests { @Test("Ziffern werden zu Neunen") func digitsBecomeNines() { #expect(MenuBarText.widestOfSameShape("↓ 14 KB/s") == "↓ 99 KB/s") #expect(MenuBarText.widestOfSameShape("34 %") == "99 %") } @Test("Alles außer Ziffern bleibt stehen") func nonDigitsSurvive() { #expect(MenuBarText.widestOfSameShape("↑ 2,4 MB/s") == "↑ 9,9 MB/s") } @Test("Gleich lange Zahlen ergeben dieselbe Gestalt") func sameLengthIsStable() { // Genau darum geht es: von 14 auf 37 KB/s darf sich nichts bewegen. #expect(MenuBarText.widestOfSameShape("↓ 14 KB/s") == MenuBarText.widestOfSameShape("↓ 37 KB/s")) } @Test("Eine Stelle mehr ist eine andere Gestalt") func moreDigitsIsWider() { #expect(MenuBarText.widestOfSameShape("↓ 999 KB/s") != MenuBarText.widestOfSameShape("↓ 99 KB/s")) } @Test("Ohne Ziffern bleibt der Text, wie er ist") func textWithoutDigitsIsUnchanged() { #expect(MenuBarText.widestOfSameShape("–") == "–") } }