From d534647f2eae8236191d77df56fcdd9b6e9b60d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Concei=C3=A7=C3=A3o?= Date: Thu, 25 Jun 2020 11:33:47 -0300 Subject: [PATCH] Add helper classes --- .../testcommons/actions/TextFieldActions.kt | 30 +++++++++++++++++++ .../assertions/TextFieldAssertions.kt | 16 ++++++++++ .../InstantTaskExecutorExtension.kt | 25 ++++++++++++++++ .../testcommons/matchers/DrawableMatcher.kt | 22 ++++++++++++++ .../natura/testcommons/rules/IntentsRule.kt | 20 +++++++++++++ .../net/natura/testcommons/rules/KoinRule.kt | 26 ++++++++++++++++ 6 files changed, 139 insertions(+) create mode 100644 testcommons/src/main/kotlin/net/natura/testcommons/actions/TextFieldActions.kt create mode 100644 testcommons/src/main/kotlin/net/natura/testcommons/assertions/TextFieldAssertions.kt create mode 100644 testcommons/src/main/kotlin/net/natura/testcommons/extensions/InstantTaskExecutorExtension.kt create mode 100644 testcommons/src/main/kotlin/net/natura/testcommons/matchers/DrawableMatcher.kt create mode 100644 testcommons/src/main/kotlin/net/natura/testcommons/rules/IntentsRule.kt create mode 100644 testcommons/src/main/kotlin/net/natura/testcommons/rules/KoinRule.kt diff --git a/testcommons/src/main/kotlin/net/natura/testcommons/actions/TextFieldActions.kt b/testcommons/src/main/kotlin/net/natura/testcommons/actions/TextFieldActions.kt new file mode 100644 index 0000000..9a7e051 --- /dev/null +++ b/testcommons/src/main/kotlin/net/natura/testcommons/actions/TextFieldActions.kt @@ -0,0 +1,30 @@ +package net.natura.testcommons.actions + +import android.view.View +import android.widget.EditText +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom +import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility +import com.natura.android.textfield.TextField +import net.natura.testcommons.R +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.Matcher + +fun typeValueInTextField(text: String) = object : ViewAction { + + override fun getDescription(): String = "type $text in TextField" + + override fun getConstraints(): Matcher { + return allOf( + withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), + isAssignableFrom(TextField::class.java) + ) + } + + override fun perform(uiController: UiController?, view: View?) { + val editText = (view as TextField).findViewById(R.id.text_field_input_value) + editText.setText(text) + } +} \ No newline at end of file diff --git a/testcommons/src/main/kotlin/net/natura/testcommons/assertions/TextFieldAssertions.kt b/testcommons/src/main/kotlin/net/natura/testcommons/assertions/TextFieldAssertions.kt new file mode 100644 index 0000000..58f43e1 --- /dev/null +++ b/testcommons/src/main/kotlin/net/natura/testcommons/assertions/TextFieldAssertions.kt @@ -0,0 +1,16 @@ +package net.natura.testcommons.assertions + +import androidx.test.espresso.ViewAssertion +import com.natura.android.textfield.TextField +import org.junit.Assert.assertEquals + +fun hasErrorInTextField(expectedText: String) = ViewAssertion { view, noMatchingViewException -> + noMatchingViewException?.let { throw it } + + if (view !is TextField) { + throw AssertionError("View is not an instance of TextField") + } + + assertEquals(TextField.State.ERROR, view.state) + assertEquals(expectedText, view.error) +} \ No newline at end of file diff --git a/testcommons/src/main/kotlin/net/natura/testcommons/extensions/InstantTaskExecutorExtension.kt b/testcommons/src/main/kotlin/net/natura/testcommons/extensions/InstantTaskExecutorExtension.kt new file mode 100644 index 0000000..f2115d2 --- /dev/null +++ b/testcommons/src/main/kotlin/net/natura/testcommons/extensions/InstantTaskExecutorExtension.kt @@ -0,0 +1,25 @@ +package net.natura.testcommons.extensions + +import androidx.arch.core.executor.ArchTaskExecutor +import androidx.arch.core.executor.TaskExecutor +import org.junit.jupiter.api.extension.AfterEachCallback +import org.junit.jupiter.api.extension.BeforeEachCallback +import org.junit.jupiter.api.extension.ExtensionContext + +class InstantTaskExecutorExtension : BeforeEachCallback, AfterEachCallback { + + override fun beforeEach(context: ExtensionContext?) { + ArchTaskExecutor.getInstance() + .setDelegate(object : TaskExecutor() { + override fun executeOnDiskIO(runnable: Runnable) = runnable.run() + + override fun postToMainThread(runnable: Runnable) = runnable.run() + + override fun isMainThread(): Boolean = true + }) + } + + override fun afterEach(context: ExtensionContext?) { + ArchTaskExecutor.getInstance().setDelegate(null) + } +} \ No newline at end of file diff --git a/testcommons/src/main/kotlin/net/natura/testcommons/matchers/DrawableMatcher.kt b/testcommons/src/main/kotlin/net/natura/testcommons/matchers/DrawableMatcher.kt new file mode 100644 index 0000000..458117b --- /dev/null +++ b/testcommons/src/main/kotlin/net/natura/testcommons/matchers/DrawableMatcher.kt @@ -0,0 +1,22 @@ +package net.natura.testcommons.matchers + +import android.view.View +import android.widget.ImageView +import androidx.annotation.DrawableRes +import androidx.core.graphics.drawable.toBitmap +import org.hamcrest.Description +import org.hamcrest.TypeSafeMatcher + +fun withDrawable(@DrawableRes id: Int) = object : TypeSafeMatcher() { + + override fun describeTo(description: Description) { + description.appendText("ImageView has drawable with id $id") + } + + override fun matchesSafely(view: View): Boolean { + val context = view.context + val expectedBitmap = context.getDrawable(id)?.toBitmap() + + return view is ImageView && view.drawable.toBitmap().sameAs(expectedBitmap) + } +} \ No newline at end of file diff --git a/testcommons/src/main/kotlin/net/natura/testcommons/rules/IntentsRule.kt b/testcommons/src/main/kotlin/net/natura/testcommons/rules/IntentsRule.kt new file mode 100644 index 0000000..1a0eebd --- /dev/null +++ b/testcommons/src/main/kotlin/net/natura/testcommons/rules/IntentsRule.kt @@ -0,0 +1,20 @@ +package net.natura.testcommons.rules + +import androidx.test.espresso.intent.Intents +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +class IntentsRule : TestRule { + + override fun apply(base: Statement?, description: Description?) = object : Statement() { + override fun evaluate() { + try { + Intents.init() + base?.evaluate() + } finally { + Intents.release() + } + } + } +} \ No newline at end of file diff --git a/testcommons/src/main/kotlin/net/natura/testcommons/rules/KoinRule.kt b/testcommons/src/main/kotlin/net/natura/testcommons/rules/KoinRule.kt new file mode 100644 index 0000000..d91a274 --- /dev/null +++ b/testcommons/src/main/kotlin/net/natura/testcommons/rules/KoinRule.kt @@ -0,0 +1,26 @@ +package net.natura.testcommons.rules + +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement +import org.koin.core.context.startKoin +import org.koin.core.context.stopKoin +import org.koin.core.module.Module + +class KoinRule(private val injectedModule: Module? = null) : TestRule { + + override fun apply(base: Statement?, description: Description?) = object : Statement() { + override fun evaluate() { + try { + startKoin { + injectedModule?.let(::modules) + } + + base?.evaluate() + } finally { + stopKoin() + } + } + + } +}