Browse Source

Add TestComposeEnvironment for resource tests (#4056)

pull/4057/head
Konstantin 5 months ago committed by GitHub
parent
commit
4c6bebb237
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      components/resources/library/src/androidInstrumentedTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.android.kt
  2. 2
      components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/FontResources.android.kt
  3. 2
      components/resources/library/src/blockingMain/kotlin/org/jetbrains/compose/resources/ResourceState.blocking.kt
  4. 2
      components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ImageResources.kt
  5. 36
      components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt
  6. 13
      components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/TestComposeEnvironment.kt
  7. 40
      components/resources/library/src/desktopTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.desktop.kt
  8. 2
      components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt

44
components/resources/library/src/androidInstrumentedTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.android.kt

@ -2,9 +2,7 @@ package org.jetbrains.compose.resources
import androidx.compose.foundation.Image
import androidx.compose.material3.Text
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.*
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.runComposeUiTest
import kotlinx.coroutines.flow.MutableStateFlow
@ -29,10 +27,12 @@ class ComposeResourceTest {
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
val recompositionsCounter = RecompositionsCounter()
setContent {
val res by imagePathFlow.collectAsState()
val imgRes = imageResource(res)
recompositionsCounter.content {
Image(bitmap = imgRes, contentDescription = null)
CompositionLocalProvider(LocalComposeEnvironment provides TestComposeEnvironment) {
val res by imagePathFlow.collectAsState()
val imgRes = imageResource(res)
recompositionsCounter.content {
Image(bitmap = imgRes, contentDescription = null)
}
}
}
awaitIdle()
@ -48,7 +48,10 @@ class ComposeResourceTest {
val testResourceReader = TestResourceReader()
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
setContent {
CompositionLocalProvider(LocalResourceReader provides testResourceReader) {
CompositionLocalProvider(
LocalResourceReader provides testResourceReader,
LocalComposeEnvironment provides TestComposeEnvironment
) {
val res by imagePathFlow.collectAsState()
Image(painterResource(res), null)
}
@ -72,7 +75,10 @@ class ComposeResourceTest {
val testResourceReader = TestResourceReader()
val stringIdFlow = MutableStateFlow(TestStringResource("app_name"))
setContent {
CompositionLocalProvider(LocalResourceReader provides testResourceReader) {
CompositionLocalProvider(
LocalResourceReader provides testResourceReader,
LocalComposeEnvironment provides TestComposeEnvironment
) {
val res by stringIdFlow.collectAsState()
Text(stringResource(res))
Text(stringArrayResource(TestStringResource("str_arr")).joinToString())
@ -95,12 +101,20 @@ class ComposeResourceTest {
fun testReadStringResource() = runComposeUiTest {
runBlockingTest {
setContent {
assertEquals("Compose Resources App", stringResource(TestStringResource("app_name")))
assertEquals(
"Hello, test-name! You have 42 new messages.",
stringResource(TestStringResource("str_template"), "test-name", 42)
)
assertEquals(listOf("item 1", "item 2", "item 3"), stringArrayResource(TestStringResource("str_arr")))
CompositionLocalProvider(LocalComposeEnvironment provides TestComposeEnvironment) {
assertEquals(
"Compose Resources App",
stringResource(TestStringResource("app_name"))
)
assertEquals(
"Hello, test-name! You have 42 new messages.",
stringResource(TestStringResource("str_template"), "test-name", 42)
)
assertEquals(
listOf("item 1", "item 2", "item 3"),
stringArrayResource(TestStringResource("str_arr"))
)
}
}
awaitIdle()
}

2
components/resources/library/src/androidMain/kotlin/org/jetbrains/compose/resources/FontResources.android.kt

@ -8,7 +8,7 @@ import androidx.compose.ui.text.font.*
@ExperimentalResourceApi
@Composable
actual fun Font(resource: FontResource, weight: FontWeight, style: FontStyle): Font {
val environment = rememberEnvironment()
val environment = LocalComposeEnvironment.current.rememberEnvironment()
val path = remember(environment) { resource.getPathByEnvironment(environment) }
return Font(path, LocalContext.current.assets, weight, style)
}

2
components/resources/library/src/blockingMain/kotlin/org/jetbrains/compose/resources/ResourceState.blocking.kt

@ -9,7 +9,7 @@ internal actual fun <T> rememberResourceState(
getDefault: () -> T,
block: suspend (ResourceEnvironment) -> T
): State<T> {
val environment = rememberEnvironment()
val environment = LocalComposeEnvironment.current.rememberEnvironment()
return remember(key, environment) {
mutableStateOf(
runBlocking { block(environment) }

2
components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ImageResources.kt

@ -44,7 +44,7 @@ fun DrawableResource(path: String): DrawableResource = DrawableResource(
@ExperimentalResourceApi
@Composable
fun painterResource(resource: DrawableResource): Painter {
val environment = rememberEnvironment()
val environment = LocalComposeEnvironment.current.rememberEnvironment()
val filePath = remember(resource, environment) { resource.getPathByEnvironment(environment) }
val isXml = filePath.endsWith(".xml", true)
if (isXml) {

36
components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt

@ -12,23 +12,33 @@ internal data class ResourceEnvironment(
val density: DensityQualifier
)
@Composable
internal fun rememberEnvironment(): ResourceEnvironment {
val composeLocale = Locale.current
val composeTheme = isSystemInDarkTheme()
val composeDensity = LocalDensity.current
internal interface ComposeEnvironment {
@Composable
fun rememberEnvironment(): ResourceEnvironment
}
internal val DefaultComposeEnvironment = object : ComposeEnvironment {
@Composable
override fun rememberEnvironment(): ResourceEnvironment {
val composeLocale = Locale.current
val composeTheme = isSystemInDarkTheme()
val composeDensity = LocalDensity.current
//cache ResourceEnvironment unless compose environment is changed
return remember(composeLocale, composeTheme, composeDensity) {
ResourceEnvironment(
LanguageQualifier(composeLocale.language),
RegionQualifier(composeLocale.region),
ThemeQualifier.selectByValue(composeTheme),
DensityQualifier.selectByDensity(composeDensity.density)
)
//cache ResourceEnvironment unless compose environment is changed
return remember(composeLocale, composeTheme, composeDensity) {
ResourceEnvironment(
LanguageQualifier(composeLocale.language),
RegionQualifier(composeLocale.region),
ThemeQualifier.selectByValue(composeTheme),
DensityQualifier.selectByDensity(composeDensity.density)
)
}
}
}
//ComposeEnvironment provider will be overridden for tests
internal val LocalComposeEnvironment = staticCompositionLocalOf { DefaultComposeEnvironment }
/**
* Provides the resource environment for non-composable access to string resources.
* It is an expensive operation! Don't use it in composable functions with no cache!

13
components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/TestComposeEnvironment.kt

@ -0,0 +1,13 @@
package org.jetbrains.compose.resources
import androidx.compose.runtime.Composable
internal val TestComposeEnvironment = object : ComposeEnvironment {
@Composable
override fun rememberEnvironment() = ResourceEnvironment(
language = LanguageQualifier("en"),
region = RegionQualifier("US"),
theme = ThemeQualifier.LIGHT,
density = DensityQualifier.XHDPI
)
}

40
components/resources/library/src/desktopTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.desktop.kt

@ -27,10 +27,12 @@ class ComposeResourceTest {
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
val recompositionsCounter = RecompositionsCounter()
setContent {
val res by imagePathFlow.collectAsState()
val imgRes = imageResource(res)
recompositionsCounter.content {
Image(bitmap = imgRes, contentDescription = null)
CompositionLocalProvider(LocalComposeEnvironment provides TestComposeEnvironment) {
val res by imagePathFlow.collectAsState()
val imgRes = imageResource(res)
recompositionsCounter.content {
Image(bitmap = imgRes, contentDescription = null)
}
}
}
awaitIdle()
@ -46,7 +48,10 @@ class ComposeResourceTest {
val testResourceReader = TestResourceReader()
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
setContent {
CompositionLocalProvider(LocalResourceReader provides testResourceReader) {
CompositionLocalProvider(
LocalResourceReader provides testResourceReader,
LocalComposeEnvironment provides TestComposeEnvironment
) {
val res by imagePathFlow.collectAsState()
Image(painterResource(res), null)
}
@ -70,7 +75,10 @@ class ComposeResourceTest {
val testResourceReader = TestResourceReader()
val stringIdFlow = MutableStateFlow(TestStringResource("app_name"))
setContent {
CompositionLocalProvider(LocalResourceReader provides testResourceReader) {
CompositionLocalProvider(
LocalResourceReader provides testResourceReader,
LocalComposeEnvironment provides TestComposeEnvironment
) {
val res by stringIdFlow.collectAsState()
Text(stringResource(res))
Text(stringArrayResource(TestStringResource("str_arr")).joinToString())
@ -93,12 +101,20 @@ class ComposeResourceTest {
fun testReadStringResource() = runComposeUiTest {
runBlockingTest {
setContent {
assertEquals("Compose Resources App", stringResource(TestStringResource("app_name")))
assertEquals(
"Hello, test-name! You have 42 new messages.",
stringResource(TestStringResource("str_template"), "test-name", 42)
)
assertEquals(listOf("item 1", "item 2", "item 3"), stringArrayResource(TestStringResource("str_arr")))
CompositionLocalProvider(LocalComposeEnvironment provides TestComposeEnvironment) {
assertEquals(
"Compose Resources App",
stringResource(TestStringResource("app_name"))
)
assertEquals(
"Hello, test-name! You have 42 new messages.",
stringResource(TestStringResource("str_template"), "test-name", 42)
)
assertEquals(
listOf("item 1", "item 2", "item 3"),
stringArrayResource(TestStringResource("str_arr"))
)
}
}
awaitIdle()
}

2
components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt

@ -12,7 +12,7 @@ internal actual fun <T> rememberResourceState(
getDefault: () -> T,
block: suspend (ResourceEnvironment) -> T
): State<T> {
val environment = rememberEnvironment()
val environment = LocalComposeEnvironment.current.rememberEnvironment()
val state = remember(key) { mutableStateOf(getDefault()) }
LaunchedEffect(key) {
state.value = block(environment)

Loading…
Cancel
Save