Issue#41 Attempt to fix failing tests with compose + update test paths for artifact
This commit is contained in:
parent
60cfb46ccf
commit
f03c9f7bf2
16 changed files with 227 additions and 159 deletions
|
|
@ -1,21 +1,18 @@
|
|||
package org.fnives.test.showcase.ui
|
||||
|
||||
import androidx.compose.ui.test.MainTestClock
|
||||
import androidx.compose.ui.test.junit4.StateRestorationTester
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.test.espresso.Espresso
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.fnives.test.showcase.R
|
||||
import org.fnives.test.showcase.android.testutil.intent.DismissSystemDialogsRule
|
||||
import org.fnives.test.showcase.android.testutil.screenshot.ScreenshotRule
|
||||
import org.fnives.test.showcase.android.testutil.viewaction.LoopMainThreadFor
|
||||
import org.fnives.test.showcase.compose.screen.AppNavigation
|
||||
import org.fnives.test.showcase.core.integration.fake.FakeUserDataLocalStorage
|
||||
import org.fnives.test.showcase.core.login.IsUserLoggedInUseCase
|
||||
import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario
|
||||
import org.fnives.test.showcase.testutils.MockServerScenarioSetupResetingTestRule
|
||||
import org.fnives.test.showcase.testutils.idling.DatabaseDispatcherTestRule
|
||||
import org.fnives.test.showcase.ui.compose.idle.ComposeNetworkSynchronizationTestRule
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -29,7 +26,9 @@ class AuthComposeInstrumentedTest : KoinTest {
|
|||
private val composeTestRule = createComposeRule()
|
||||
private val stateRestorationTester = StateRestorationTester(composeTestRule)
|
||||
|
||||
private val mockServerScenarioSetupTestRule = MockServerScenarioSetupResetingTestRule()
|
||||
private val mockServerScenarioSetupTestRule = MockServerScenarioSetupResetingTestRule(
|
||||
networkSynchronizationTestRule = ComposeNetworkSynchronizationTestRule(composeTestRule)
|
||||
)
|
||||
private val mockServerScenarioSetup get() = mockServerScenarioSetupTestRule.mockServerScenarioSetup
|
||||
private val dispatcherTestRule = DatabaseDispatcherTestRule()
|
||||
private lateinit var robot: ComposeLoginRobot
|
||||
|
|
@ -72,7 +71,7 @@ class AuthComposeInstrumentedTest : KoinTest {
|
|||
robot.assertLoading()
|
||||
composeTestRule.mainClock.autoAdvance = true
|
||||
|
||||
composeTestRule.mainClock.awaitIdlingResources()
|
||||
composeTestRule.waitForIdle()
|
||||
navigationRobot.assertHomeScreen()
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +85,7 @@ class AuthComposeInstrumentedTest : KoinTest {
|
|||
.assertUsername("banan")
|
||||
.clickOnLogin()
|
||||
|
||||
composeTestRule.mainClock.awaitIdlingResources()
|
||||
composeTestRule.waitForIdle()
|
||||
robot.assertErrorIsShown(R.string.password_is_invalid)
|
||||
.assertNotLoading()
|
||||
navigationRobot.assertAuthScreen()
|
||||
|
|
@ -103,7 +102,7 @@ class AuthComposeInstrumentedTest : KoinTest {
|
|||
.assertPassword("banan")
|
||||
.clickOnLogin()
|
||||
|
||||
composeTestRule.mainClock.awaitIdlingResources()
|
||||
composeTestRule.waitForIdle()
|
||||
robot.assertErrorIsShown(R.string.username_is_invalid)
|
||||
.assertNotLoading()
|
||||
navigationRobot.assertAuthScreen()
|
||||
|
|
@ -129,7 +128,7 @@ class AuthComposeInstrumentedTest : KoinTest {
|
|||
robot.assertLoading()
|
||||
composeTestRule.mainClock.autoAdvance = true
|
||||
|
||||
composeTestRule.mainClock.awaitIdlingResources()
|
||||
composeTestRule.waitForIdle()
|
||||
robot.assertErrorIsShown(R.string.credentials_invalid)
|
||||
.assertNotLoading()
|
||||
navigationRobot.assertAuthScreen()
|
||||
|
|
@ -155,7 +154,7 @@ class AuthComposeInstrumentedTest : KoinTest {
|
|||
robot.assertLoading()
|
||||
composeTestRule.mainClock.autoAdvance = true
|
||||
|
||||
composeTestRule.mainClock.awaitIdlingResources()
|
||||
composeTestRule.waitForIdle()
|
||||
robot.assertErrorIsShown(R.string.something_went_wrong)
|
||||
.assertNotLoading()
|
||||
navigationRobot.assertAuthScreen()
|
||||
|
|
@ -181,15 +180,5 @@ class AuthComposeInstrumentedTest : KoinTest {
|
|||
|
||||
companion object {
|
||||
private const val SPLASH_DELAY = 600L
|
||||
|
||||
// workaround, issue with idlingResources is tracked here https://github.com/robolectric/robolectric/issues/4807
|
||||
/**
|
||||
* Await the idling resource on a different thread while looping main.
|
||||
*/
|
||||
fun MainTestClock.awaitIdlingResources() {
|
||||
Espresso.onView(ViewMatchers.isRoot()).perform(LoopMainThreadFor(100L))
|
||||
|
||||
advanceTimeByFrame()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package org.fnives.test.showcase.ui
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import androidx.compose.ui.test.assertCountEquals
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertTextContains
|
||||
import androidx.compose.ui.test.junit4.ComposeTestRule
|
||||
import androidx.compose.ui.test.onAllNodesWithTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
|
|
@ -13,8 +13,8 @@ import androidx.test.core.app.ApplicationProvider
|
|||
import org.fnives.test.showcase.compose.screen.auth.AuthScreenTag
|
||||
|
||||
class ComposeLoginRobot(
|
||||
composeTestRule: ComposeTestRule,
|
||||
) : ComposeTestRule by composeTestRule {
|
||||
semanticsNodeInteractionsProvider: SemanticsNodeInteractionsProvider,
|
||||
) : SemanticsNodeInteractionsProvider by semanticsNodeInteractionsProvider {
|
||||
|
||||
fun setUsername(username: String): ComposeLoginRobot = apply {
|
||||
onNodeWithTag(AuthScreenTag.UsernameInput).performTextInput(username)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package org.fnives.test.showcase.ui.compose.idle
|
||||
|
||||
import androidx.compose.ui.test.IdlingResource
|
||||
import androidx.compose.ui.test.junit4.ComposeTestRule
|
||||
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.Disposable
|
||||
|
||||
class ComposeIdlingDisposable(
|
||||
private val idlingResource: IdlingResource,
|
||||
private val testRule: ComposeTestRule,
|
||||
) : Disposable {
|
||||
override var isDisposed: Boolean = false
|
||||
private set
|
||||
|
||||
init {
|
||||
testRule.registerIdlingResource(idlingResource)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
isDisposed = true
|
||||
testRule.unregisterIdlingResource(idlingResource)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package org.fnives.test.showcase.ui.compose.idle
|
||||
|
||||
import android.util.Log
|
||||
import androidx.annotation.CheckResult
|
||||
import androidx.compose.ui.test.junit4.ComposeTestRule
|
||||
import okhttp3.OkHttpClient
|
||||
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.CompositeDisposable
|
||||
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.Disposable
|
||||
import org.fnives.test.showcase.android.testutil.synchronization.idlingresources.OkHttp3IdlingResource
|
||||
import org.fnives.test.showcase.network.testutil.NetworkTestConfigurationHelper
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
import org.koin.test.KoinTest
|
||||
|
||||
class ComposeNetworkSynchronizationTestRule(private val composeTestRule: ComposeTestRule) : TestRule, KoinTest {
|
||||
|
||||
private var disposable: Disposable? = null
|
||||
|
||||
override fun apply(base: Statement, description: Description): Statement {
|
||||
return object : Statement() {
|
||||
override fun evaluate() {
|
||||
disposable = registerIdlingResources()
|
||||
try {
|
||||
base.evaluate()
|
||||
} finally {
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
if (disposable == null) {
|
||||
Log.w("ComposeNetworkSynchronizationTestRule", "Was disposed, but registerIdlingResources was not called!")
|
||||
}
|
||||
disposable?.dispose()
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
private fun registerIdlingResources(): Disposable = getOkHttpClients()
|
||||
.associateBy(keySelector = { it.toString() })
|
||||
.map { (key, client) -> OkHttp3IdlingResource.create(key, client) }
|
||||
.map(::EspressoToComposeIdlingResourceAdapter)
|
||||
.map { ComposeIdlingDisposable(it, composeTestRule) }
|
||||
.let(::CompositeDisposable)
|
||||
|
||||
private fun getOkHttpClients(): List<OkHttpClient> =
|
||||
NetworkTestConfigurationHelper.getOkHttpClients()
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.fnives.test.showcase.ui.compose.idle
|
||||
|
||||
import androidx.test.espresso.IdlingResource
|
||||
|
||||
class EspressoToComposeIdlingResourceAdapter(private val idlingResource: IdlingResource) : androidx.compose.ui.test.IdlingResource {
|
||||
override val isIdleNow: Boolean get() = idlingResource.isIdleNow
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue