Skip to content

Commit

Permalink
native, js, wasm platforms support (#73)
Browse files Browse the repository at this point in the history
* native, js, wasm support

* 2.5.0-alpha06
  • Loading branch information
alex-tiurin authored Jul 2, 2024
1 parent 7ce968d commit 35d059f
Show file tree
Hide file tree
Showing 14 changed files with 392 additions and 95 deletions.
32 changes: 18 additions & 14 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig

plugins {
alias(libs.plugins.kotlinMultiplatform)
Expand All @@ -26,23 +25,26 @@ kotlin {
dependencies {
implementation(libs.androidx.ui.test.junit4.android)
debugImplementation(libs.androidx.ui.test.manifest)
implementation(project(":ultron-compose"))
}
}
}

jvm("desktop")

// listOf(
// iosX64(),
// iosArm64(),
// iosSimulatorArm64()
// ).forEach { iosTarget ->
// iosTarget.binaries.framework {
// baseName = "ComposeApp"
// isStatic = true
// }
// }

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp"
isStatic = true
}
}
js(IR)
@OptIn(ExperimentalWasmDsl::class)
wasmJs()

sourceSets {
val desktopMain by getting

Expand Down Expand Up @@ -70,13 +72,15 @@ kotlin {
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
}
// Adds the desktop test dependency
val desktopTest by getting {
dependencies {
implementation(compose.desktop.uiTestJUnit4)
implementation(compose.desktop.currentOs)
}
}
@OptIn(ExperimentalWasmDsl::class)
wasmJs()
val wasmJsTest by getting
}
}

Expand Down
23 changes: 17 additions & 6 deletions composeApp/src/commonTest/kotlin/AppTest.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
import repositories.ContactRepository
import com.atiurin.ultron.core.common.options.TextContainsOption
import com.atiurin.ultron.core.compose.list.UltronComposeListItem
import com.atiurin.ultron.core.compose.list.composeList
import com.atiurin.ultron.core.compose.nodeinteraction.click
import com.atiurin.ultron.core.compose.runUltronUiTest
import com.atiurin.ultron.extensions.assertIsDisplayed
import com.atiurin.ultron.extensions.click
import com.atiurin.ultron.extensions.withAssertion
import com.atiurin.ultron.page.Screen
import repositories.ContactRepository
import kotlin.test.Test

@OptIn(ExperimentalTestApi::class)
Expand All @@ -20,7 +19,7 @@ class AppTest {
setContent {
App()
}
hasText("Click me!").withAssertion(){
hasText("Click me!").withAssertion() {
hasTestTag("greeting")
.assertIsDisplayed()
.assertTextContains("Compose: Hello,", option = TextContainsOption(substring = true))
Expand All @@ -32,10 +31,17 @@ class AppTest {
setContent {
App()
}
val contact = ContactRepository.getFirst()
composeList(hasTestTag("contactsListTestTag"))
.assertIsDisplayed().assertNotEmpty()
.firstVisibleItem().assertIsDisplayed()
}

@Test
fun testListItemChildElements() = runUltronUiTest {
setContent {
App()
}
val contact = ContactRepository.getFirst()
ListScreen {
list.assertContentDescriptionEquals(contactsListContentDesc)
list.getFirstVisibleItem<ListScreen.ListItem>().apply {
Expand All @@ -49,9 +55,14 @@ class AppTest {
object ListScreen : Screen<ListScreen>() {
const val contactsListTestTag = "contactsListTestTag"
const val contactsListContentDesc = "contactsListContentDesc"
val list = composeList(hasTestTag(contactsListTestTag))
val list = composeList(
listMatcher = hasTestTag(contactsListTestTag),
initBlock = {
registerItem { ListItem() }
}
)

class ListItem : UltronComposeListItem(){
class ListItem : UltronComposeListItem() {
val name by child { hasTestTag("contactNameTestTag") }
val status by child { hasTestTag("contactStatusTestTag") }
}
Expand Down
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ android.useAndroidX=true
android.nonTransitiveRClass=true
org.jetbrains.compose.experimental.wasm.enabled=true
org.jetbrains.compose.experimental.jscanvas.enabled=true
org.jetbrains.compose.experimental.macos.enabled=true
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.mpp.enableCInteropCommonization=true


GROUP=com.atiurin
POM_ARTIFACT_ID=ultron
VERSION_NAME=2.5.0-alpha05
VERSION_NAME=2.5.0-alpha06
12 changes: 6 additions & 6 deletions iosApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objectVersion = 60;
objects = {

/* Begin PBXBuildFile section */
Expand All @@ -17,7 +17,7 @@
058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
7555FF7B242A565900829871 /* sample-kmp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = sample-kmp.app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF7B242A565900829871 /* sample-kmp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "sample-kmp.app"; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AB3632DC29227652001CCB65 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
Expand Down Expand Up @@ -127,7 +127,7 @@
};
};
buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */;
compatibilityVersion = "Xcode 14.0";
compatibilityVersion = "Xcode 15.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
Expand Down Expand Up @@ -326,7 +326,7 @@
"$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
);
INFOPLIST_FILE = iosApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -358,7 +358,7 @@
"$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
);
INFOPLIST_FILE = iosApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -400,4 +400,4 @@
/* End XCConfigurationList section */
};
rootObject = 7555FF73242A565900829871 /* Project object */;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object AssertUtils {
try {
block()
} catch (ex: Throwable) {
throw ex
// throw ex
exceptionOccurs = true
}
Assert.assertEquals(expected, exceptionOccurs)
Expand Down
43 changes: 38 additions & 5 deletions ultron-common/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
Expand All @@ -10,16 +14,35 @@ group = project.findProperty("GROUP")!!
version = project.findProperty("VERSION_NAME")!!

kotlin {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
}
// targets
jvm()
androidTarget {
publishLibraryVariants("release")
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}

applyDefaultHierarchyTemplate()
macosX64()
macosArm64()
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp"
isStatic = true
}
}
@OptIn(ExperimentalWasmDsl::class)
wasmJs()
js(IR)
sourceSets {
commonMain.dependencies {
implementation(libs.okio)
Expand All @@ -42,6 +65,16 @@ kotlin {
implementation(kotlin("stdlib-jdk8"))
}
}
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
}
}
val wasmJsMain by getting {
dependencies {
implementation(kotlin("stdlib"))
}
}
}
}

Expand Down
45 changes: 41 additions & 4 deletions ultron-compose/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
Expand All @@ -13,14 +17,36 @@ version = project.findProperty("VERSION_NAME")!!

kotlin {
jvm()
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0)
}
androidTarget {
publishLibraryVariants("release")
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}
@OptIn(ExperimentalKotlinGradlePluginApi::class)
applyDefaultHierarchyTemplate {
}
macosX64()
macosArm64()
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp"
isStatic = true
}
}

@OptIn(ExperimentalWasmDsl::class)
wasmJs()
js(IR)

sourceSets {
commonMain.dependencies {
Expand All @@ -32,6 +58,7 @@ kotlin {
implementation(libs.atomicfu)
}
val androidMain by getting {
// dependsOn(jvmMain.get())
dependencies {
api(project(":ultron-common"))
implementation(Libs.androidXRunner)
Expand All @@ -44,6 +71,16 @@ kotlin {
implementation(kotlin("stdlib-jdk8"))
}
}
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
}
}
val wasmJsMain by getting {
dependencies {
implementation(kotlin("stdlib"))
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.atiurin.ultron.core.compose.list

import androidx.compose.ui.test.SemanticsMatcher
import com.atiurin.ultron.exceptions.UltronException

actual inline fun <reified T : UltronComposeListItem> getComposeListItemInstance(
ultronComposeList: UltronComposeList,
itemMatcher: SemanticsMatcher
): T {
val item = createUltronComposeListItemInstance<T>()
item.setExecutor(ultronComposeList, itemMatcher)
return item
}

actual inline fun <reified T : UltronComposeListItem> getComposeListItemInstance(
ultronComposeList: UltronComposeList,
position: Int,
isPositionPropertyConfigured: Boolean
): T {
val item = createUltronComposeListItemInstance<T>()
item.setExecutor(ultronComposeList, position, isPositionPropertyConfigured)
return item
}

inline fun <reified T : UltronComposeListItem> createUltronComposeListItemInstance(): T {
return try {
T::class.java.newInstance()
} catch (ex: Exception) {
val desc = when {
T::class.isInner -> {
"${T::class.simpleName} is an inner class so you have to delete inner modifier (It is often when kotlin throws 'has no zero argument constructor' but real reason is an inner modifier)"
}

T::class.constructors.find { it.parameters.isEmpty() } == null -> {
"${T::class.simpleName} doesn't have a constructor without params (create an empty constructor)"
}

else -> ex.message
}
throw UltronException(
"""
|Couldn't create an instance of ${T::class.simpleName}.
|Possible reason: $desc
|Original exception: ${ex.message}, cause ${ex.cause}
""".trimMargin()
)
}
}
Loading

0 comments on commit 35d059f

Please sign in to comment.