From 93f6fdf98dfc0edca6ce3b4a27497492a55308c7 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Thu, 22 Oct 2026 07:52:47 +0200 Subject: [PATCH] test(prefs): cover the automatic local clock's round trip and restore Also reuse ZoneOffsetFormat.gmtLabel for the Etc/GMT names rather than a second formatter, and bring the city-fallback docs up to date. --- .../clockula/domain/worldclock/ZoneCatalog.kt | 10 ++++++---- .../clockula/ui/worldclock/WorldClockRowState.kt | 2 +- .../clockula/data/prefs/ClockPrefsTest.kt | 2 ++ .../clockula/data/prefs/SettingsPrefsTest.kt | 8 +++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt b/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt index cfdbac1..fd397dc 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt @@ -57,7 +57,8 @@ object ZoneCatalog { /** * The last `/`-segment with underscores replaced by spaces, trimmed; the - * input trimmed when that is blank. Never throws. + * input trimmed when that is blank. `Etc/GMT±n` is the exception: it is + * named by its real offset instead. Never throws. */ fun cityFallbackFor(zoneId: String): String { etcOffsetName(zoneId)?.let { return it } @@ -74,11 +75,12 @@ object ZoneCatalog { private fun etcOffsetName(zoneId: String): String? { val match = ETC_OFFSET.matchEntire(zoneId.trim()) ?: return null val hours = match.groupValues[2].toInt() - if (hours == 0) return "GMT" - val sign = if (match.groupValues[1] == "-") "+" else "-" - return "GMT$sign$hours" + val sign = if (match.groupValues[1] == "-") 1 else -1 + return ZoneOffsetFormat.gmtLabel(sign * hours * MINUTES_PER_HOUR) } + private const val MINUTES_PER_HOUR = 60 + private val ETC_OFFSET = Regex("""Etc/GMT([+-])(\d{1,2})""") /** By `ZoneSearch.fold(city)` ascending, then [ZoneEntry.zoneId] ascending. */ diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt index d54e877..cbd1fda 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt @@ -18,7 +18,7 @@ import kotlin.time.toJavaInstant internal data class WorldClockRowState( val id: Long, val zoneId: String, - /** The user's label when set, else the ICU city, else the id's last segment. Never blank. */ + /** The user's label when set, else the ICU city, else `ZoneCatalog.cityFallbackFor`. Never blank. */ val name: String, /** Truncated to the minute. Non-null **exactly** when [known]. */ val time: LocalTime?, diff --git a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt index 869cca3..de4bf47 100644 --- a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt +++ b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt @@ -53,6 +53,7 @@ class ClockPrefsTest { prefs.setTimerRingtoneUri("content://t") prefs.setDismissChallenge(DismissChallenge.HOLD) prefs.setHomeZoneId("Europe/Berlin") + prefs.setAutomaticLocalClock(false) assertThat(prefs.defaults.first()).isEqualTo( ClockDefaults( @@ -64,6 +65,7 @@ class ClockPrefsTest { timerRingtoneUri = "content://t", dismissChallenge = DismissChallenge.HOLD, homeZoneId = "Europe/Berlin", + automaticLocalClock = false, ), ) } diff --git a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt index 71ead3e..82ddb9d 100644 --- a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt +++ b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt @@ -74,7 +74,12 @@ class SettingsPrefsTest { BackupSettings( themeMode = ThemeMode.DARK, dynamicColor = false, - defaults = ClockDefaults(snoozeMinutes = 99, volumeRampSeconds = 99, alarmRingtoneUri = " "), + defaults = ClockDefaults( + snoozeMinutes = 99, + volumeRampSeconds = 99, + alarmRingtoneUri = " ", + automaticLocalClock = false, + ), timerPresets = listOf(5.minutes, 1.minutes, 5.minutes), ), ) @@ -84,6 +89,7 @@ class SettingsPrefsTest { assertThat(prefs.currentDefaults().snoozeMinutes).isEqualTo(60) assertThat(prefs.currentDefaults().volumeRampSeconds).isEqualTo(60) assertThat(prefs.currentDefaults().alarmRingtoneUri).isNull() + assertThat(prefs.currentDefaults().automaticLocalClock).isFalse() assertThat(prefs.timerPresets.first()).containsExactly(1.minutes, 5.minutes).inOrder() }