Browse Source

Fix native xml parser and add ios native tests (#4207)

Co-authored-by: Da Risk <da_risk@geekorum.com>
pull/4215/head
Konstantin 10 months ago committed by GitHub
parent
commit
b4881ffe01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      components/resources/library/build.gradle.kts
  2. 28
      components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt
  3. 1
      components/resources/library/src/commonTest/resources/strings.xml
  4. 169
      components/resources/library/src/desktopTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.desktop.kt
  5. 4
      components/resources/library/src/nativeMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/DomXmlParser.kt
  6. 6
      components/test.sh

4
components/resources/library/build.gradle.kts

@ -1,3 +1,4 @@
import org.jetbrains.compose.ExperimentalComposeLibrary
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
@ -76,6 +77,9 @@ kotlin {
dependencies { dependencies {
implementation(libs.kotlinx.coroutines.test) implementation(libs.kotlinx.coroutines.test)
implementation(kotlin("test")) implementation(kotlin("test"))
implementation(compose.material3)
@OptIn(ExperimentalComposeLibrary::class)
implementation(compose.uiTest)
} }
} }
val blockingMain by creating { val blockingMain by creating {

28
components/resources/library/src/androidInstrumentedTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.android.kt → components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt

@ -6,23 +6,14 @@ import androidx.compose.runtime.*
import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.runComposeUiTest import androidx.compose.ui.test.runComposeUiTest
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import org.junit.Assert.assertEquals import kotlin.test.*
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@OptIn(ExperimentalTestApi::class, ExperimentalResourceApi::class, InternalResourceApi::class) @OptIn(ExperimentalTestApi::class, ExperimentalResourceApi::class, InternalResourceApi::class)
class ComposeResourceTest { class ComposeResourceTest {
@Before init {
fun dropCaches() {
dropStringsCache() dropStringsCache()
dropImageCache() dropImageCache()
}
@Before
fun configureTestEnvironment() {
getResourceEnvironment = ::getTestEnvironment getResourceEnvironment = ::getTestEnvironment
} }
@ -111,6 +102,10 @@ class ComposeResourceTest {
"Compose Resources App", "Compose Resources App",
stringResource(TestStringResource("app_name")) stringResource(TestStringResource("app_name"))
) )
assertEquals(
"Créer une table",
stringResource(TestStringResource("accentuated_characters"))
)
assertEquals( assertEquals(
"Hello, test-name! You have 42 new messages.", "Hello, test-name! You have 42 new messages.",
stringResource(TestStringResource("str_template"), "test-name", 42) stringResource(TestStringResource("str_template"), "test-name", 42)
@ -127,12 +122,12 @@ class ComposeResourceTest {
@Test @Test
fun testLoadStringResource() = runBlockingTest { fun testLoadStringResource() = runBlockingTest {
kotlin.test.assertEquals("Compose Resources App", getString(TestStringResource("app_name"))) assertEquals("Compose Resources App", getString(TestStringResource("app_name")))
kotlin.test.assertEquals( assertEquals(
"Hello, test-name! You have 42 new messages.", "Hello, test-name! You have 42 new messages.",
getString(TestStringResource("str_template"), "test-name", 42) getString(TestStringResource("str_template"), "test-name", 42)
) )
kotlin.test.assertEquals(listOf("item 1", "item 2", "item 3"), getStringArray(TestStringResource("str_arr"))) assertEquals(listOf("item 1", "item 2", "item 3"), getStringArray(TestStringResource("str_arr")))
} }
@Test @Test
@ -143,17 +138,18 @@ class ComposeResourceTest {
val error = assertFailsWith<IllegalStateException> { val error = assertFailsWith<IllegalStateException> {
getString(TestStringResource("unknown_id")) getString(TestStringResource("unknown_id"))
} }
kotlin.test.assertEquals("String ID=`unknown_id` is not found!", error.message) assertEquals("String ID=`unknown_id` is not found!", error.message)
} }
@Test @Test
fun testReadFileResource() = runBlockingTest { fun testReadFileResource() = runBlockingTest {
val bytes = readResourceBytes("strings.xml") val bytes = readResourceBytes("strings.xml")
kotlin.test.assertEquals( assertEquals(
""" """
<resources> <resources>
<string name="app_name">Compose Resources App</string> <string name="app_name">Compose Resources App</string>
<string name="hello">😊 Hello world!</string> <string name="hello">😊 Hello world!</string>
<string name="accentuated_characters">Créer une table</string>
<string name="str_template">Hello, %1${'$'}s! You have %2${'$'}d new messages.</string> <string name="str_template">Hello, %1${'$'}s! You have %2${'$'}d new messages.</string>
<string-array name="str_arr"> <string-array name="str_arr">
<item>item 1</item> <item>item 1</item>

1
components/resources/library/src/commonTest/resources/strings.xml

@ -1,6 +1,7 @@
<resources> <resources>
<string name="app_name">Compose Resources App</string> <string name="app_name">Compose Resources App</string>
<string name="hello">😊 Hello world!</string> <string name="hello">😊 Hello world!</string>
<string name="accentuated_characters">Créer une table</string>
<string name="str_template">Hello, %1$s! You have %2$d new messages.</string> <string name="str_template">Hello, %1$s! You have %2$d new messages.</string>
<string-array name="str_arr"> <string-array name="str_arr">
<item>item 1</item> <item>item 1</item>

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

@ -1,169 +0,0 @@
package org.jetbrains.compose.resources
import androidx.compose.foundation.Image
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.runComposeUiTest
import kotlinx.coroutines.flow.MutableStateFlow
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@OptIn(ExperimentalTestApi::class, ExperimentalResourceApi::class, InternalResourceApi::class)
class ComposeResourceTest {
@Before
fun dropCaches() {
dropStringsCache()
dropImageCache()
}
@Before
fun configureTestEnvironment() {
getResourceEnvironment = ::getTestEnvironment
}
@Test
fun testCountRecompositions() = runComposeUiTest {
runBlockingTest {
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
val recompositionsCounter = RecompositionsCounter()
setContent {
CompositionLocalProvider(LocalComposeEnvironment provides TestComposeEnvironment) {
val res by imagePathFlow.collectAsState()
val imgRes = imageResource(res)
recompositionsCounter.content {
Image(bitmap = imgRes, contentDescription = null)
}
}
}
awaitIdle()
imagePathFlow.emit(DrawableResource("2.png"))
awaitIdle()
assertEquals(2, recompositionsCounter.count)
}
}
@Test
fun testImageResourceCache() = runComposeUiTest {
runBlockingTest {
val testResourceReader = TestResourceReader()
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
setContent {
CompositionLocalProvider(
LocalResourceReader provides testResourceReader,
LocalComposeEnvironment provides TestComposeEnvironment
) {
val res by imagePathFlow.collectAsState()
Image(painterResource(res), null)
}
}
awaitIdle()
imagePathFlow.emit(DrawableResource("2.png"))
awaitIdle()
imagePathFlow.emit(DrawableResource("1.png"))
awaitIdle()
assertEquals(
expected = listOf("1.png", "2.png"), //no second read of 1.png
actual = testResourceReader.readPaths
)
}
}
@Test
fun testStringResourceCache() = runComposeUiTest {
runBlockingTest {
val testResourceReader = TestResourceReader()
val stringIdFlow = MutableStateFlow(TestStringResource("app_name"))
setContent {
CompositionLocalProvider(
LocalResourceReader provides testResourceReader,
LocalComposeEnvironment provides TestComposeEnvironment
) {
val res by stringIdFlow.collectAsState()
Text(stringResource(res))
Text(stringArrayResource(TestStringResource("str_arr")).joinToString())
}
}
awaitIdle()
stringIdFlow.emit(TestStringResource("hello"))
awaitIdle()
stringIdFlow.emit(TestStringResource("app_name"))
awaitIdle()
assertEquals(
expected = listOf("strings.xml"), //just one string.xml read
actual = testResourceReader.readPaths
)
}
}
@Test
fun testReadStringResource() = runComposeUiTest {
runBlockingTest {
setContent {
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()
}
}
@Test
fun testLoadStringResource() = runBlockingTest {
kotlin.test.assertEquals("Compose Resources App", getString(TestStringResource("app_name")))
kotlin.test.assertEquals(
"Hello, test-name! You have 42 new messages.",
getString(TestStringResource("str_template"), "test-name", 42)
)
kotlin.test.assertEquals(listOf("item 1", "item 2", "item 3"), getStringArray(TestStringResource("str_arr")))
}
@Test
fun testMissingResource() = runBlockingTest {
assertFailsWith<MissingResourceException> {
readResourceBytes("missing.png")
}
val error = assertFailsWith<IllegalStateException> {
getString(TestStringResource("unknown_id"))
}
kotlin.test.assertEquals("String ID=`unknown_id` is not found!", error.message)
}
@Test
fun testReadFileResource() = runBlockingTest {
val bytes = readResourceBytes("strings.xml")
kotlin.test.assertEquals(
"""
<resources>
<string name="app_name">Compose Resources App</string>
<string name="hello">😊 Hello world!</string>
<string name="str_template">Hello, %1${'$'}s! You have %2${'$'}d new messages.</string>
<string-array name="str_arr">
<item>item 1</item>
<item>item 2</item>
<item>item 3</item>
</string-array>
</resources>
""".trimIndent(),
bytes.decodeToString()
)
}
}

4
components/resources/library/src/nativeMain/kotlin/org/jetbrains/compose/resources/vector/xmldom/DomXmlParser.kt

@ -94,7 +94,9 @@ private class DomXmlParser : NSObject(), NSXMLParserDelegateProtocol {
} }
override fun parser(parser: NSXMLParser, foundCharacters: String) { override fun parser(parser: NSXMLParser, foundCharacters: String) {
nodeStack.lastOrNull()?.textContent = foundCharacters nodeStack.lastOrNull()?.let { node ->
node.textContent = node.textContent.orEmpty() + foundCharacters
}
} }
override fun parser( override fun parser(

6
components/test.sh

@ -2,10 +2,6 @@
cd "$(dirname "$0")" # Run always in current dir cd "$(dirname "$0")" # Run always in current dir
set -euo pipefail # Fail fast set -euo pipefail # Fail fast
# Unit tests
./gradlew :resources:library:test
./gradlew :resources:library:desktopTest ./gradlew :resources:library:desktopTest
# Android integration tests
./gradlew :resources:library:pixel5DebugAndroidTest ./gradlew :resources:library:pixel5DebugAndroidTest
./gradlew :resources:library:iosSimulatorArm64Test

Loading…
Cancel
Save