I’m very new in compose, please say why it happens...
# compose
i
I’m very new in compose, please say why it happens: I look into
isSystemInDarkTheme()
sources [1]: but when i try to change uiMode [2] i get nothing [3] If i open
Configuration
sources i see that
uiMode
just
public int
so (theoretically) it must changes and reads as expected but it doesn’t
🧵 1
z
For future reference, it’s courteous to post longer code snippets inside a thread instead of posting in the channel directly, to make the channel more scrollable.
i
Sorry, i’ll fix it quickly
z
The
apply {}
function doesn’t actually do anything, it’s just syntactic sugar. Calling
something.apply {}
is an expression that just returns
something
– it doesn’t have any side effects.
i
[1]
Copy code
@Composable
@ReadOnlyComposable
fun isSystemInDarkTheme(): Boolean {
    val uiMode = LocalConfiguration.current.uiMode
    return (uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
}
🙏 1
[2]
Copy code
@Composable
private fun setDarkTheme() {
    LocalConfiguration.current.apply {
        uiMode = uiMode or Configuration.UI_MODE_NIGHT_MASK
    }
}

@Composable
private fun setLightTheme() {
    LocalConfiguration.current.apply {
        uiMode = uiMode and Configuration.UI_MODE_NIGHT_MASK.inv()
    }
}
[3]
Copy code
class TypographyTest {

    @get:Rule
    val composeTestRule = createAndroidComposeRule<ComponentActivity>()

    @Test
    fun testTypography() {
        composeTestRule.setContent {

            setLightTheme()
            Assert.assertEquals(false, isSystemInDarkTheme())

            setDarkTheme()
            Assert.assertEquals(true, isSystemInDarkTheme()) // Assertion error
.........
Also, I recommend looking at Jetchat for how to test in both light/dark, and in a portable way: https://github.com/android/compose-samples/blob/main/Jetchat/app/src/androidTest/java/com/example/compose/jetchat/ConversationTest.kt
i
@cb thx, but jetchat example not applicable in my case. I want to “mock” call
isSystemInDarkTheme()
directly if it possible, so i’ll try look to
CompositionLocalProvider
@Zach Klippenstein (he/him) [MOD] I understand what actually
apply
do and try to change receiver’s (
LocalConfiguration.current
) field in my snippet. It should work.
z
That’s the same as doing
a.value = 34
-
apply
doesn’t actually do anything there except shift syntax around
So what your code is doing is just mutating a field inside the
Configuration
, but because
Configuration
isn’t aware of compose, changing its fields won’t trigger recomposition at all.
What you’d need to do is create a copy of the configuration, mutate the field on the copy, and then pass the copy down using
CompositionLocalProvider
like Chris suggested. But that’s a lot of unnecessary work when you could just create a more explicit mechanism for selecting between light and dark themes.
☝️ 2
c
Yeah, you no longer need to mock system calls like this for unit testing. IMO, your tests should not rely on any Android specific APIs now. If they are, then they're probably assuming too much. If you wanted to test the system API, write a separate test which changes the uiMode (say via
AppCompatDelegate.setDefaultNightMode
) and assert that the resolved theme is light/dark.
@ppvi probably has opinions here too
i
Let me to explain. In my app i should use design system of my org. I develop android sdk for design system too. Core of all is colors. Colors module just returns colors set depends on
isSystemInDarkTheme()
. Tests placed in another (Typography) module. Typography uses colors and doesn’t aware about day-night theme. I try to check typography changes when system theme changes. There is no more simpler way to check it than mocking
isSystemInDarkTheme
call (i quess)
I don’t want to expose any parts of colors module for simplify testing, because they should be internal for color module, but mocking typography module logic is not enough for proper testing
c
Sure, but I think there's a split here: • Most of tests should verify that the components + styling updates when it is told to use light /dark theme. This can be written to be platform agnostic. • Then the second type verifies that the (system) toggle for light/dark works. This could look at, and modify the Android configuration. Up to you what you do of course, but mocking system APIs usually ends up in lots of pain.
👌 1
2
100 Views