Browse Source

web: add tests for constructors with Composable parameters

pull/1077/head
Oleksandr Karpovich 3 years ago
parent
commit
4eedafc5fa
  1. 38
      web/compose-compiler-integration/build.gradle.kts
  2. 88
      web/compose-compiler-integration/src/jsMain/kotlin/CrossmoduleTestsDependencies.kt
  3. 283
      web/compose-compiler-integration/src/jsTest/kotlin/ComposablesInConstructorTests.kt
  4. 13
      web/core/src/jsTest/kotlin/FailingTestCases.kt

38
web/compose-compiler-integration/build.gradle.kts

@ -1,3 +1,41 @@
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
}
kotlin {
js(IR) {
browser() {
testTask {
testLogging.showStandardStreams = true
useKarma {
useChromeHeadless()
useFirefox()
}
}
}
binaries.executable()
}
sourceSets {
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
implementation(compose.runtime)
implementation(project(":web-core"))
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}
fun cloneTemplate(templateName: String, contentMain: String, contentLib: String): File { fun cloneTemplate(templateName: String, contentMain: String, contentLib: String): File {
val tempDir = file("${project.buildDir.absolutePath}/temp/cloned-$templateName") val tempDir = file("${project.buildDir.absolutePath}/temp/cloned-$templateName")
tempDir.deleteRecursively() tempDir.deleteRecursively()

88
web/compose-compiler-integration/src/jsMain/kotlin/CrossmoduleTestsDependencies.kt

@ -0,0 +1,88 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import kotlinx.browser.document
data class DataClassTakesValComposable(val c: @Composable () -> Unit)
data class DataClassTakesValComposableTyped<T>(val c: @Composable (T) -> Unit)
data class DataClassTakesVarComposable(var c: @Composable () -> Unit)
class ClassTakesValComposable(val c: @Composable () -> Unit)
class ClassTakesValComposableTyped<T>(val c: @Composable (T) -> Unit)
class ClassTakesVarComposable(var c: @Composable () -> Unit)
class ClassTakesComposablePrivateVal(private val c: @Composable () -> Unit) {
@Composable
fun callPrivateComposablePassedIntoConstructor() {
c()
}
}
interface HasComposable {
val composable: @Composable () -> Unit
}
class ImplementsHasComposable(override val composable: @Composable () -> Unit): HasComposable
interface HasComposableTyped<T> {
val composable: @Composable (T) -> Unit
}
class ImplementsHasComposableTyped<T>(override val composable: @Composable (T) -> Unit): HasComposableTyped<T>
class ClassSavesComposableIntoVar(c: @Composable () -> Unit) {
var composableVar: @Composable () -> Unit = c
}
class ClassSavesComposableIntoLateinitVar(c: @Composable () -> Unit) {
lateinit var composableVar: @Composable () -> Unit
init {
composableVar = c
}
}
class ClassSavesComposableIntoNullableVar(c: @Composable () -> Unit) {
var composableVar: (@Composable () -> Unit)? = null
init {
composableVar = c
}
}
class ClassSavesTypedComposableIntoVar<T>(c: @Composable (T) -> Unit) {
var composableVar: @Composable (T) -> Unit = c
}
class ClassSavesTypedComposableIntoLateinitVar<T>(c: @Composable (T) -> Unit) {
lateinit var composableVar: @Composable (T) -> Unit
init {
composableVar = c
}
}
class ClassWithSecondaryConstructorSavesComposable(val c: @Composable () -> Unit) {
constructor(): this({
SideEffect {
document.body!!.innerHTML = "Secondary constructor composable content"
}
})
}
data class DataClassTakesValStringAndComposable(
val s: String, val c: @Composable DataClassTakesValStringAndComposable.() -> Unit
)
class ClassTakesValStringAndComposable(
val s: String, val c: @Composable ClassTakesValStringAndComposable.() -> Unit
)
class ClassSavesStringAndComposableIntoVar(
s: String, c: @Composable ClassSavesStringAndComposableIntoVar.() -> Unit
) {
var composableVar: @Composable ClassSavesStringAndComposableIntoVar.() -> Unit = c
var stringVar: String = s
}

283
web/compose-compiler-integration/src/jsTest/kotlin/ComposablesInConstructorTests.kt

@ -0,0 +1,283 @@
import androidx.compose.runtime.SideEffect
import kotlinx.browser.document
import org.jetbrains.compose.web.renderComposableInBody
import kotlin.test.Test
import kotlin.test.assertEquals
/**
* Classes under tests are defined in jsMain intentionally.
* The reason is to test cross-module compilation + runtime behaviour.
*
* Reporeted Issues:
* https://github.com/JetBrains/compose-jb/issues/746
* https://github.com/JetBrains/compose-jb/issues/1052
*/
class ComposablesInConstructorTests {
@Test
fun valComposableInDataClass() {
val d = DataClassTakesValComposable {
SideEffect {
document.body!!.innerText = "DataClassTakesValComposable"
}
}
renderComposableInBody {
d.c()
}
assertEquals("DataClassTakesValComposable", document.body!!.innerText)
}
@Test
fun valTypedComposableInDataClass() {
val d = DataClassTakesValComposableTyped<String> {
SideEffect {
document.body!!.innerText = "DataClassTakesValComposableTyped-$it"
}
}
renderComposableInBody {
d.c("WORKS")
}
assertEquals("DataClassTakesValComposableTyped-WORKS", document.body!!.innerText)
}
@Test
fun varComposableInDataClass() {
val d = DataClassTakesVarComposable {
SideEffect {
document.body!!.innerText = "DataClassTakesVarComposable"
}
}
renderComposableInBody {
d.c()
}
assertEquals("DataClassTakesVarComposable", document.body!!.innerText)
}
@Test
fun valComposableInClass() {
val d = ClassTakesValComposable {
SideEffect {
document.body!!.innerText = "ClassTakesValComposable"
}
}
renderComposableInBody {
d.c()
}
assertEquals("ClassTakesValComposable", document.body!!.innerText)
}
@Test
fun valTypedComposableInClass() {
val d = ClassTakesValComposableTyped<Int> {
SideEffect {
document.body!!.innerText = "ClassTakesValComposableTyped-$it"
}
}
renderComposableInBody {
d.c(100500)
}
assertEquals("ClassTakesValComposableTyped-100500", document.body!!.innerText)
}
@Test
fun varComposableInClass() {
val d = ClassTakesVarComposable {
SideEffect {
document.body!!.innerText = "ClassTakesVarComposable"
}
}
renderComposableInBody {
d.c()
}
assertEquals("ClassTakesVarComposable", document.body!!.innerText)
}
@Test
fun implementsHasComposable() {
val d: HasComposable = ImplementsHasComposable {
SideEffect {
document.body!!.innerText = "ImplementsHasComposable"
}
}
renderComposableInBody {
d.composable()
}
assertEquals("ImplementsHasComposable", document.body!!.innerText)
}
@Test
fun implementsHasComposableTyped() {
val d: HasComposableTyped<Int> = ImplementsHasComposableTyped {
SideEffect {
document.body!!.innerText = "ImplementsHasComposableTyped-$it"
}
}
renderComposableInBody {
d.composable(123456)
}
assertEquals("ImplementsHasComposableTyped-123456", document.body!!.innerText)
}
@Test
fun classSavesComposableIntoVar() {
val d = ClassSavesComposableIntoVar {
SideEffect {
document.body!!.innerText = "ClassSavesComposableIntoVar"
}
}
renderComposableInBody {
d.composableVar()
}
assertEquals("ClassSavesComposableIntoVar", document.body!!.innerText)
}
@Test
fun classSavesComposableIntoLateinitVar() {
val d = ClassSavesComposableIntoLateinitVar {
SideEffect {
document.body!!.innerText = "ClassSavesComposableIntoLateinitVar"
}
}
renderComposableInBody {
d.composableVar()
}
assertEquals("ClassSavesComposableIntoLateinitVar", document.body!!.innerText)
}
@Test
fun classSavesComposableIntoNullableVar() {
val d = ClassSavesComposableIntoNullableVar {
SideEffect {
document.body!!.innerText = "ClassSavesComposableIntoNullableVar"
}
}
renderComposableInBody {
d.composableVar!!.invoke()
}
assertEquals("ClassSavesComposableIntoNullableVar", document.body!!.innerText)
}
@Test
fun classSavesTypedComposableIntoVar() {
val d = ClassSavesTypedComposableIntoVar<String> {
SideEffect {
document.body!!.innerText = "ClassSavesTypedComposableIntoVar-$it"
}
}
renderComposableInBody {
d.composableVar("ABC")
}
assertEquals("ClassSavesTypedComposableIntoVar-ABC", document.body!!.innerText)
}
@Test
fun classSavesTypedComposableIntoLateinitVar() {
val d = ClassSavesTypedComposableIntoLateinitVar<String> {
SideEffect {
document.body!!.innerText = "ClassSavesTypedComposableIntoLateinitVar-$it"
}
}
renderComposableInBody {
d.composableVar("ABC")
}
assertEquals("ClassSavesTypedComposableIntoLateinitVar-ABC", document.body!!.innerText)
}
@Test
fun classWithSecondaryConstructorSavesComposable() {
val d = ClassWithSecondaryConstructorSavesComposable()
renderComposableInBody {
d.c()
}
assertEquals("Secondary constructor composable content", document.body!!.innerText)
}
@Test
fun dataClassTakesValStringAndComposable() {
val d = DataClassTakesValStringAndComposable("String1") {
SideEffect {
document.body!!.innerText = "DataClassTakesValStringAndComposable-${this.s}"
}
}
renderComposableInBody {
d.c(d)
}
assertEquals("DataClassTakesValStringAndComposable-String1", document.body!!.innerText)
}
@Test
fun classTakesValStringAndComposable() {
val d = ClassTakesValStringAndComposable("123123") {
SideEffect {
document.body!!.innerText = "ClassTakesValStringAndComposable-${this.s}"
}
}
renderComposableInBody {
d.c(d)
}
assertEquals("ClassTakesValStringAndComposable-123123", document.body!!.innerText)
}
@Test
fun classSavesStringAndComposableIntoVar() {
val d = ClassSavesStringAndComposableIntoVar("098765") {
SideEffect {
document.body!!.innerText = "ClassSavesStringAndComposableIntoVar-${this.stringVar}"
}
}
renderComposableInBody {
d.composableVar(d)
}
assertEquals("ClassSavesStringAndComposableIntoVar-098765", document.body!!.innerText)
}
@Test
fun classTakesComposablePrivateVal() {
val d = ClassTakesComposablePrivateVal {
SideEffect {
document.body!!.innerText = "ClassTakesComposablePrivateVal"
}
}
renderComposableInBody {
d.callPrivateComposablePassedIntoConstructor()
}
assertEquals("ClassTakesComposablePrivateVal", document.body!!.innerText)
}
}

13
web/core/src/jsTest/kotlin/FailingTestCases.kt

@ -24,19 +24,6 @@ class FailingTestCases {
} }
assertTrue(expectedErrorThrown) assertTrue(expectedErrorThrown)
} }
data class DataClassTakesComposable(val c: @Composable () -> Unit)
class UsualClassTakesComposable(val c: @Composable () -> Unit)
@Test
fun passingComposableIntoConstructorOfDataClass() {
check(DataClassTakesComposable {}.c == null) // Expected behaviour: c != null
}
@Test
fun passingComposableIntoConstructorOfUsualClass() {
check(UsualClassTakesComposable {}.c == null) // Expected behaviour: c != null
}
} }
@Suppress("Unused", "NOTHING_TO_INLINE", "NESTED_CLASS_IN_EXTERNAL_INTERFACE", "INLINE_EXTERNAL_DECLARATION", "WRONG_BODY_OF_EXTERNAL_DECLARATION", "NESTED_EXTERNAL_DECLARATION", "ClassName") @Suppress("Unused", "NOTHING_TO_INLINE", "NESTED_CLASS_IN_EXTERNAL_INTERFACE", "INLINE_EXTERNAL_DECLARATION", "WRONG_BODY_OF_EXTERNAL_DECLARATION", "NESTED_EXTERNAL_DECLARATION", "ClassName")

Loading…
Cancel
Save