Skip to content

Commit

Permalink
commonize ui tests
Browse files Browse the repository at this point in the history
  • Loading branch information
softartdev committed Apr 1, 2024
1 parent c758b44 commit e555472
Show file tree
Hide file tree
Showing 51 changed files with 538 additions and 101 deletions.
2 changes: 1 addition & 1 deletion android-compose-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ dependencies {
coreLibraryDesugaring(libs.desugar)
testImplementation(libs.junit)
testImplementation(libs.bundles.mockito)
androidTestImplementation(project(":jvm-compose-test"))
androidTestImplementation(project(":shared-compose-test"))
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.androidx.test.runner)
androidTestUtil(libs.androidx.test.orchestrator)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
@file:OptIn(ExperimentalTestApi::class)

package com.softartdev.notedelight.ui

import androidx.compose.ui.test.AndroidComposeUiTest
import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.espresso.Espresso
import androidx.test.espresso.IdlingRegistry
Expand All @@ -18,12 +24,18 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class AndroidUiTests : AbstractUiTests() {

override val composeTestRule = createAndroidComposeRule<MainActivity>()
private val androidComposeRule = createAndroidComposeRule<MainActivity>()

@get:Rule
val rules: RuleChain = RuleChain.outerRule(TestDescriptionHolder)
.around(DetectLeaksAfterTestSuccess())
.around(composeTestRule)
.around(androidComposeRule)

override val composeTestRule: ComposeUiTest by lazy {
val field = AndroidComposeTestRule::class.java.getDeclaredField("composeTest")
field.isAccessible = true
return@lazy field.get(androidComposeRule) as AndroidComposeUiTest<*>
}

override fun setUp() {
super.setUp()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
@file:OptIn(ExperimentalTestApi::class)

package com.softartdev.notedelight.ui

import androidx.compose.ui.test.*
import androidx.compose.ui.test.AndroidComposeUiTest
import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.test.espresso.Espresso
import androidx.test.espresso.IdlingRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
Expand Down Expand Up @@ -32,6 +37,12 @@ class SignInTest {
.around(DetectLeaksAfterTestSuccess())
.around(composeTestRule)

private val composeUiTest: ComposeUiTest by lazy {
val field = AndroidComposeTestRule::class.java.getDeclaredField("composeTest")
field.isAccessible = true
return@lazy field.get(composeTestRule) as AndroidComposeUiTest<*>
}

@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(IdlingRes.countingIdlingResource)
Expand All @@ -45,5 +56,5 @@ class SignInTest {
}

@Test
fun signInTest() = SignInTestCase(composeTestRule, Espresso::closeSoftKeyboard).invoke()
fun signInTest() = SignInTestCase(composeUiTest, Espresso::closeSoftKeyboard).invoke()
}
2 changes: 1 addition & 1 deletion desktop-compose-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ kotlin {
implementation(libs.koin.core.jvm)
}
jvmTest.dependencies {
implementation(project(":jvm-compose-test"))
implementation(project(":shared-compose-test"))
implementation(kotlin("test"))
implementation(compose.desktop.uiTestJUnit4)
implementation(compose.desktop.currentOs)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
@file:OptIn(ExperimentalTestApi::class, InternalTestApi::class)

package com.softartdev.notedelight.ui

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.DesktopComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.InternalTestApi
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.DesktopComposeTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.performClick
Expand All @@ -27,7 +34,14 @@ import org.koin.java.KoinJavaComponent.get
class DesktopUiTests : AbstractUiTests() {

@get:Rule
override val composeTestRule: ComposeContentTestRule = createComposeRule()
val composeContentTestRule: ComposeContentTestRule = createComposeRule()

override val composeTestRule: ComposeUiTest by lazy {
val desktopRule: DesktopComposeTestRule = composeContentTestRule as DesktopComposeTestRule
val field = DesktopComposeTestRule::class.java.getDeclaredField("composeTest")
field.isAccessible = true
return@lazy field.get(desktopRule) as DesktopComposeUiTest
}

@Before
override fun setUp() {
Expand Down Expand Up @@ -73,7 +87,7 @@ class DesktopUiTests : AbstractUiTests() {
override fun settingPasswordTest() = super.settingPasswordTest()

override fun pressBack() {
composeTestRule.onNodeWithContentDescription(label = Icons.Default.ArrowBack.name)
composeTestRule.onNodeWithContentDescription(label = Icons.AutoMirrored.Filled.ArrowBack.name)
.assertIsDisplayed()
.performClick()
}
Expand Down
2 changes: 1 addition & 1 deletion iosApp/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 0dc93a6f6109335ea8cd3f91d2c87cc8c99f04a3

COCOAPODS: 1.15.2
COCOAPODS: 1.12.1
2 changes: 1 addition & 1 deletion iosApp/Pods/Manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions iosApp/Pods/Pods.xcodeproj/project.pbxproj

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 0 additions & 25 deletions jvm-compose-test/build.gradle.kts

This file was deleted.

2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ rootProject.name = "NoteDelight"

include(":shared")
include(":shared-compose-ui")
include(":jvm-compose-test")
include(":shared-compose-test")
include(":android-compose-app")
include(":desktop-compose-app")
include(":ios-compose-kit")
Expand Down
File renamed without changes.
51 changes: 51 additions & 0 deletions shared-compose-test/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.compose)
}
compose {
kotlinCompilerPlugin.set(libs.versions.composeCompiler.get())
}
kotlin {
jvmToolchain(libs.versions.jdk.get().toInt())
jvm {
compilations.all {
kotlinOptions.jvmTarget = libs.versions.jdk.get()
}
}
iosArm64()
iosSimulatorArm64()
applyDefaultHierarchyTemplate()
sourceSets {
commonMain.dependencies {
implementation(project(":shared"))
implementation(project(":shared-compose-ui"))

implementation(kotlin("test"))

implementation(compose.ui)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.material3)
implementation(compose.materialIconsExtended)

@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.uiTest)

implementation(libs.koin.core)
implementation(libs.turbine)
}
commonTest.dependencies {
}
jvmMain.dependencies {
implementation(libs.decompose)
implementation(libs.koin.core.jvm)
implementation(compose.desktop.uiTestJUnit4)
implementation(compose.desktop.currentOs)
implementation(libs.coroutines.swing)
}
jvmTest.dependencies {
implementation(compose.desktop.currentOs)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ package com.softartdev.notedelight
import com.softartdev.notedelight.shared.PlatformSQLiteState
import com.softartdev.notedelight.shared.db.SafeRepo
import io.github.aakira.napier.Napier
import org.koin.java.KoinJavaComponent.inject
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.koin.mp.KoinPlatformTools

object DbTestEncryptor : () -> Unit {

const val PASSWORD = "password"

override fun invoke() {
val safeRepo: SafeRepo by inject(SafeRepo::class.java)
// val safeRepo: SafeRepo by inject(SafeRepo::class.java)
val safeRepo: SafeRepo = KoinPlatformTools.defaultContext().get().get()
while (safeRepo.databaseState == PlatformSQLiteState.DOES_NOT_EXIST) {
safeRepo.buildDbIfNeed()
Thread.sleep(1000)
// Thread.sleep(1000)
runBlocking { delay(1000) }
Napier.d("databaseState = ${safeRepo.databaseState.name}")
}
safeRepo.encrypt(StringBuilder(PASSWORD))
safeRepo.encrypt(PASSWORD)
safeRepo.closeDatabase()
Napier.d("databaseState = ${safeRepo.databaseState.name}")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
@file:OptIn(ExperimentalTestApi::class, ExperimentalTestApi::class)

package com.softartdev.notedelight

import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.SemanticsNodeInteraction
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.ComposeTestRule
import io.github.aakira.napier.Napier

const val ASSERT_WAIT_TIMEOUT_MILLIS: Long = 60_000

inline fun ComposeTestRule.waitUntilDisplayed(
inline fun ComposeUiTest.waitUntilDisplayed(
crossinline blockSNI: () -> SemanticsNodeInteraction,
) = waitUntil(timeoutMillis = ASSERT_WAIT_TIMEOUT_MILLIS) {
try {
Expand All @@ -20,7 +23,7 @@ inline fun ComposeTestRule.waitUntilDisplayed(
return@waitUntil true
}

inline fun ComposeTestRule.waitAssert(
inline fun ComposeUiTest.waitAssert(
crossinline assert: () -> Unit
) = waitUntil(timeoutMillis = ASSERT_WAIT_TIMEOUT_MILLIS) {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
@file:OptIn(ExperimentalTestApi::class, ExperimentalTestApi::class)

package com.softartdev.notedelight.ui

import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import com.softartdev.notedelight.ComposeIdlingRes
import com.softartdev.notedelight.ui.cases.CrudTestCase
import com.softartdev.notedelight.ui.cases.EditTitleAfterCreateTestCase
Expand All @@ -10,7 +13,7 @@ import com.softartdev.notedelight.ui.cases.PrepopulateDbTestCase
import com.softartdev.notedelight.ui.cases.SettingPasswordTestCase

abstract class AbstractUiTests {
abstract val composeTestRule: ComposeContentTestRule
abstract val composeTestRule: ComposeUiTest

open fun setUp() = composeTestRule.registerIdlingResource(ComposeIdlingRes)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
@file:OptIn(ExperimentalTestApi::class)

package com.softartdev.notedelight.ui

import androidx.compose.ui.test.junit4.ComposeContentTestRule
import com.softartdev.notedelight.ui.screen.dialog.CommonDialog
import com.softartdev.notedelight.ui.screen.dialog.CommonDialogImpl
import com.softartdev.notedelight.ui.screen.dialog.ConfirmPasswordDialog
import com.softartdev.notedelight.ui.screen.dialog.EnterPasswordDialog
import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import com.softartdev.notedelight.ui.screen.MainTestScreen
import com.softartdev.notedelight.ui.screen.NoteScreen
import com.softartdev.notedelight.ui.screen.SettingsTestScreen
import com.softartdev.notedelight.ui.screen.SignInScreen
import com.softartdev.notedelight.ui.screen.dialog.ChangePasswordDialog
import com.softartdev.notedelight.ui.screen.dialog.CommonDialog
import com.softartdev.notedelight.ui.screen.dialog.CommonDialogImpl
import com.softartdev.notedelight.ui.screen.dialog.ConfirmPasswordDialog
import com.softartdev.notedelight.ui.screen.dialog.EditTitleDialog
import com.softartdev.notedelight.ui.screen.dialog.EnterPasswordDialog

abstract class BaseTestCase(val composeTestRule: ComposeContentTestRule) {
abstract class BaseTestCase(val composeTestRule: ComposeUiTest) {

private val commonDialog: CommonDialog = CommonDialogImpl(composeTestRule)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
@file:OptIn(ExperimentalTestApi::class)

package com.softartdev.notedelight.ui.cases

import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import com.softartdev.notedelight.ui.BaseTestCase
import com.softartdev.notedelight.ui.screen.MainTestScreen.Companion.noteItemTitleText
import com.softartdev.notedelight.util.UUID
import com.softartdev.notedelight.waitUntilDisplayed
import java.util.UUID

class CrudTestCase(
composeTestRule: ComposeContentTestRule
composeTestRule: ComposeUiTest
) : () -> Unit, BaseTestCase(composeTestRule) {

private val actualNoteText = UUID.randomUUID().toString().substring(0, 30)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
@file:OptIn(ExperimentalTestApi::class)

package com.softartdev.notedelight.ui.cases

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.ComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
Expand All @@ -10,11 +12,11 @@ import com.softartdev.mr.contextLocalized
import com.softartdev.notedelight.MR
import com.softartdev.notedelight.ui.BaseTestCase
import com.softartdev.notedelight.ui.screen.MainTestScreen.Companion.noteItemTitleText
import com.softartdev.notedelight.util.UUID
import com.softartdev.notedelight.waitUntilDisplayed
import java.util.UUID

class EditTitleAfterCreateTestCase(
composeTestRule: ComposeContentTestRule
composeTestRule: ComposeUiTest
) : () -> Unit, BaseTestCase(composeTestRule) {

private val actualNoteTitle = "title"
Expand Down
Loading

0 comments on commit e555472

Please sign in to comment.