fix(cron): preserve chosen clock time across repeat changes

This commit is contained in:
yilsem committed 2026-10-08 02:43:32 +03:00
1 parent 8161f3bf09
commit 1f692044d2
3 files changed
+15 -15

No files matched your search

@@ -1,7 +1,6 @@
package com.m57.hermescontrol.ui.cron
import android.graphics.Bitmap
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -10,12 +9,10 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.getValue
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.test.hasContentDescription
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithText
@@ -34,13 +31,8 @@ class SchedulePickerTest {
@Test
fun repeatDropdownAndClockPreserveSchedule() {
var schedule by mutableStateOf("59 23 * * *")
val baseContext = InstrumentationRegistry.getInstrumentation().targetContext
val configuration = Configuration(baseContext.resources.configuration).apply {
setLocale(java.util.Locale.forLanguageTag("tr-TR"))
}
val context = baseContext.createConfigurationContext(configuration)
val context = InstrumentationRegistry.getInstrumentation().targetContext
compose.setContent {
CompositionLocalProvider(LocalContext provides context, LocalConfiguration provides configuration) {
MaterialTheme {
Surface {
Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp)) {
@@ -48,11 +40,11 @@ class SchedulePickerTest {
}
}
}
}
}
fun text(id: Int) = context.getString(id)
fun screenshot(name: String) {
compose.waitForIdle()
android.os.SystemClock.sleep(500)
val bitmap = InstrumentationRegistry.getInstrumentation().uiAutomation.takeScreenshot()
File(context.getExternalFilesDir(null), "$name.png").outputStream().use {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, it)
@@ -62,7 +54,7 @@ class SchedulePickerTest {
compose.onNodeWithText("23:59").performClick()
screenshot("schedule-clock-360")
compose.onNodeWithText("59").performClick()
compose.onNodeWithText("55").performClick()
compose.onNode(hasContentDescription("55", substring = true)).performClick()
compose.onNodeWithText(text(R.string.action_ok)).performClick()
compose.runOnIdle { assertEquals("55 23 * * *", schedule) }
compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick()
@@ -71,6 +63,12 @@ class SchedulePickerTest {
compose.runOnIdle { assertEquals("55 23 1 1 *", schedule) }
screenshot("schedule-yearly-360")
compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick()
compose.onAllNodesWithText(text(R.string.cron_repeat_hourly))[0].performClick()
compose.runOnIdle { assertEquals("55 * * * *", schedule) }
compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick()
compose.onAllNodesWithText(text(R.string.cron_schedule_mode_daily))[0].performClick()
compose.runOnIdle { assertEquals("55 23 * * *", schedule) }
compose.onNodeWithText(text(R.string.cron_repeat_label)).performClick()
compose.onAllNodesWithText(text(R.string.cron_repeat_minutely))[0].performClick()
compose.runOnIdle { assertEquals("* * * * *", schedule) }
}
@@ -1004,8 +1004,8 @@ internal fun SchedulePickerSection(
val parsed = remember(schedule) { parseSchedule(schedule) }
var mode by remember(schedule) { mutableStateOf(parsed.mode) }
var hour by remember(schedule) { mutableStateOf(parsed.hour) }
var minute by remember(schedule) { mutableStateOf(parsed.minute) }
var hour by remember { mutableStateOf(parsed.hour) }
var minute by remember { mutableStateOf(parsed.minute) }
var intervalCount by remember(schedule) { mutableStateOf(parsed.intervalCount) }
var intervalUnit by remember(schedule) { mutableStateOf(parsed.intervalUnit) }
var selectedDays by remember(schedule) { mutableStateOf(parsed.selectedDays) }
@@ -1055,6 +1055,8 @@ internal fun SchedulePickerSection(
} else {
val fallback = parseSchedule(schedule)
mode = fallback.mode
hour = fallback.hour
minute = fallback.minute
}
},
) {
@@ -17,7 +17,7 @@ internal data class ParsedSchedule(
val minute: Int = 0,
val intervalCount: Int = 1,
val intervalUnit: String = "h",
val selectedDays: Set<Int> = setOf(1, 2, 3, 4, 5),
val selectedDays: Set<Int> = setOf(1),
val dayOfMonth: Int = 1,
val month: Int = 1,
val raw: String = "",