diff --git a/android/testutils/BUILD b/android/testutils/BUILD new file mode 100644 index 000000000..abb617d4d --- /dev/null +++ b/android/testutils/BUILD @@ -0,0 +1,36 @@ +load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") +load("@rules_player//kotlin:defs.bzl", "lint") +load("@build_constants//:constants.bzl", "VERSION") +load("//jvm:defs.bzl", "distribution") +load(":deps.bzl", "main_deps") + +kt_android_library( + name = "testutils_android", + srcs = glob(["src/main/java/**/*.kt"]), + custom_package = "com.intuit.playerui.android.testutils", + manifest = ":src/main/AndroidManifest.xml", + resource_files = glob(["src/main/res/**"]), + deps = main_deps, +) + +android_library( + name = "testutils", + custom_package = "com.intuit.playerui.android.testutils", + manifest = ":src/main/AndroidManifest.xml", + resource_files = glob(["src/main/res/**"]), + tags = ["maven_coordinates=com.intuit.playerui.android:testutils:aar:%s" % VERSION], + visibility = ["//visibility:public"], + exports = [":testutils_android"], + deps = main_deps, +) + +distribution( + name = "testutils", + maven_coordinates = "com.intuit.playerui.android:testutils:%s" % VERSION, +) + +lint( + name = "testutils", + srcs = glob(["src/main/**/*.kt"]), + lint_config = "//jvm:lint_config", +) \ No newline at end of file diff --git a/android/testutils/README.md b/android/testutils/README.md new file mode 100644 index 000000000..5175ab487 --- /dev/null +++ b/android/testutils/README.md @@ -0,0 +1,3 @@ +# Test Utilities + +Along with some generic utilities, this module exposes some base test classes to provide some structure to similar Player integration tests or runtime tests. These are built on JUnit Jupiter and require the concrete tests to be written using the JUnit Jupiter API. \ No newline at end of file diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/deps.bzl b/android/testutils/deps.bzl similarity index 100% rename from plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/deps.bzl rename to android/testutils/deps.bzl diff --git a/android/testutils/src/main/AndroidManifest.xml b/android/testutils/src/main/AndroidManifest.xml new file mode 100644 index 000000000..2d1b71c11 --- /dev/null +++ b/android/testutils/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + + diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/Assertions.kt b/android/testutils/src/main/java/com/intuit/playerui/android/testutils/asset/Assertions.kt similarity index 75% rename from plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/Assertions.kt rename to android/testutils/src/main/java/com/intuit/playerui/android/testutils/asset/Assertions.kt index 8f21b6deb..ed7537b42 100644 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/Assertions.kt +++ b/android/testutils/src/main/java/com/intuit/playerui/android/testutils/asset/Assertions.kt @@ -1,4 +1,4 @@ -package com.intuit.playerui.android.reference.assets.test +package com.intuit.playerui.android.testutils.asset import android.view.View import com.intuit.playerui.android.asset.RenderableAsset @@ -10,7 +10,7 @@ import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @OptIn(ExperimentalContracts::class) -inline fun Any?.shouldBeAsset( +public inline fun Any?.shouldBeAsset( block: T.() -> Unit = {}, ): T { shouldBeInstanceOf(this) @@ -19,7 +19,7 @@ inline fun Any?.shouldBeAsset( } @OptIn(ExperimentalContracts::class) -inline fun Any?.shouldBeView(assertions: T.() -> Unit = {}): T { +public inline fun Any?.shouldBeView(assertions: T.() -> Unit = {}): T { val view = if (T::class != SuspendableAsset.AsyncViewStub::class && this is SuspendableAsset.AsyncViewStub) { runBlocking { awaitView() @@ -33,14 +33,14 @@ inline fun Any?.shouldBeView(assertions: T.() -> Unit = {}): } @OptIn(ExperimentalContracts::class) -inline fun PlayerFlowState?.shouldBePlayerState(assertions: T.() -> Unit = {}): T { +public inline fun PlayerFlowState?.shouldBePlayerState(assertions: T.() -> Unit = {}): T { shouldBeInstanceOf(this) assertions() return this } @ExperimentalContracts -inline fun shouldBeInstanceOf( +public inline fun shouldBeInstanceOf( `this`: Any?, ) { contract { diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/AssetTest.kt b/android/testutils/src/main/java/com/intuit/playerui/android/testutils/asset/AssetTest.kt similarity index 78% rename from plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/AssetTest.kt rename to android/testutils/src/main/java/com/intuit/playerui/android/testutils/asset/AssetTest.kt index 903d0df5a..07367d883 100644 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/AssetTest.kt +++ b/android/testutils/src/main/java/com/intuit/playerui/android/testutils/asset/AssetTest.kt @@ -1,4 +1,4 @@ -package com.intuit.playerui.android.reference.assets.test +package com.intuit.playerui.android.testutils.asset import android.content.Context import android.view.View @@ -46,16 +46,16 @@ import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) @Config(sdk = [28]) @OptIn(ExperimentalCoroutinesApi::class) -abstract class AssetTest(val group: String? = null) { +public abstract class AssetTest(private val group: String? = null) { @get:Rule - val name = TestName() + public val name: TestName = TestName() - open val plugins: List by lazy { listOf(ReferenceAssetsPlugin(), CommonTypesPlugin(), PendingTransactionPlugin()) } + protected open val plugins: List by lazy { listOf(ReferenceAssetsPlugin(), CommonTypesPlugin(), PendingTransactionPlugin()) } - val context: Context get() = ApplicationProvider.getApplicationContext() + protected val context: Context get() = ApplicationProvider.getApplicationContext() - val player by lazy { + protected val player: AndroidPlayer by lazy { AndroidPlayer(plugins) } @@ -75,7 +75,7 @@ abstract class AssetTest(val group: String? = null) { throw AssertionError("Expected view to update, but it did not.", exception) } - var currentAssetTree: RenderableAsset? = null; private set(value) { + protected var currentAssetTree: RenderableAsset? = null; private set(value) { // reset view on new asset currentView = null @@ -89,7 +89,7 @@ abstract class AssetTest(val group: String? = null) { } } - var currentView: View? = null; get() = field ?: blockUntilRendered() + protected var currentView: View? = null; get() = field ?: blockUntilRendered() set(value) { field = value.also { // reset replay cache to clear value if the current value is set to null @@ -99,14 +99,14 @@ abstract class AssetTest(val group: String? = null) { protected val currentState: PlayerFlowState get() = player.state - protected val mocks get() = ClassLoaderMocksReader(context.classLoader).mocks.filter { + protected val mocks: List get() = ClassLoaderMocksReader(context.classLoader).mocks.filter { group == null || group == it.group } private val emptyView = View(context) @Before - fun beforeEach() { + public fun beforeEach() { Dispatchers.setMain(TestCoroutineDispatcher()) player.onUpdate { asset, _ -> currentAssetTree = asset } player.hooks.state.tap { state -> @@ -118,34 +118,34 @@ abstract class AssetTest(val group: String? = null) { } @After - fun afterEach() { + public fun afterEach() { Dispatchers.resetMain() } - fun launchMock() = launchMock(name.methodName) + protected fun launchMock(): Unit = launchMock(name.methodName) - fun launchMock(name: String) = launchMock( + protected fun launchMock(name: String): Unit = launchMock( mocks.find { it.name == name || it.name == "$group-$name" } ?: throw IllegalArgumentException("$name not found in mocks: ${mocks.map { "${it.group}/${it.name}" }}"), ) - fun launchMock(mock: Mock<*>) = launchJson( + protected fun launchMock(mock: Mock<*>): Unit = launchJson( when (mock) { is ClassLoaderMock -> mock.getFlow(context.classLoader) else -> throw IllegalArgumentException("mock of type ${mock::class.java.simpleName} not supported") }, ) - fun launchJson(json: JsonElement) = launchJson(Json.encodeToString(json)) + protected fun launchJson(json: JsonElement): Unit = launchJson(Json.encodeToString(json)) - fun launchJson(json: String) = player.start(makeFlow(json)).onComplete { + protected fun launchJson(json: String): Unit = player.start(makeFlow(json)).onComplete { it.exceptionOrNull()?.printStackTrace() } /** Suspend until we have a [View] representation of [currentAssetTree] that is _completely_ hydrated */ - suspend fun awaitRendered(timeout: Long = 5_000): View = consumeLatestView(timeout) + protected suspend fun awaitRendered(timeout: Long = 5_000): View = consumeLatestView(timeout) - fun blockUntilRendered(timeout: Long = 5_000) = runBlocking { + protected fun blockUntilRendered(timeout: Long = 5_000): View = runBlocking { awaitRendered(timeout) } diff --git a/plugins/reference-assets/android/defs.bzl b/plugins/reference-assets/android/defs.bzl index c253463a2..acd8112f9 100644 --- a/plugins/reference-assets/android/defs.bzl +++ b/plugins/reference-assets/android/defs.bzl @@ -14,7 +14,7 @@ def kt_asset_test( test_class = test_class, deps = deps + [ "//tools/mocks:jar", - "//plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test", + "//android/testutils", "//jvm/j2v8:j2v8-all", ], resources = [ diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/action/ActionTest.kt b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/action/ActionTest.kt index aa6d9797d..230404252 100644 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/action/ActionTest.kt +++ b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/action/ActionTest.kt @@ -4,11 +4,11 @@ import android.widget.Button import android.widget.LinearLayout import androidx.core.view.get import com.intuit.playerui.android.reference.assets.R -import com.intuit.playerui.android.reference.assets.test.AssetTest -import com.intuit.playerui.android.reference.assets.test.shouldBeAsset -import com.intuit.playerui.android.reference.assets.test.shouldBePlayerState -import com.intuit.playerui.android.reference.assets.test.shouldBeView import com.intuit.playerui.android.reference.assets.text.Text +import com.intuit.playerui.android.testutils.asset.AssetTest +import com.intuit.playerui.android.testutils.asset.shouldBeAsset +import com.intuit.playerui.android.testutils.asset.shouldBePlayerState +import com.intuit.playerui.android.testutils.asset.shouldBeView import com.intuit.playerui.core.player.state.CompletedState import com.intuit.playerui.core.player.state.ErrorState import com.intuit.playerui.core.player.state.InProgressState diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/collection/CollectionTest.kt b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/collection/CollectionTest.kt index 0bb5e5e62..3252c81a2 100644 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/collection/CollectionTest.kt +++ b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/collection/CollectionTest.kt @@ -5,9 +5,9 @@ import android.widget.LinearLayout import android.widget.TextView import androidx.core.view.get import com.intuit.playerui.android.reference.assets.R -import com.intuit.playerui.android.reference.assets.test.AssetTest -import com.intuit.playerui.android.reference.assets.test.shouldBePlayerState -import com.intuit.playerui.android.reference.assets.test.shouldBeView +import com.intuit.playerui.android.testutils.asset.AssetTest +import com.intuit.playerui.android.testutils.asset.shouldBePlayerState +import com.intuit.playerui.android.testutils.asset.shouldBeView import com.intuit.playerui.core.player.state.InProgressState import org.junit.Assert.assertEquals import org.junit.Test diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/info/InfoTest.kt b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/info/InfoTest.kt index 6b2ebdf5a..f36d53ccc 100644 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/info/InfoTest.kt +++ b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/info/InfoTest.kt @@ -6,9 +6,9 @@ import android.widget.LinearLayout import android.widget.TextView import androidx.core.view.get import com.intuit.playerui.android.reference.assets.R -import com.intuit.playerui.android.reference.assets.test.AssetTest -import com.intuit.playerui.android.reference.assets.test.shouldBePlayerState -import com.intuit.playerui.android.reference.assets.test.shouldBeView +import com.intuit.playerui.android.testutils.asset.AssetTest +import com.intuit.playerui.android.testutils.asset.shouldBePlayerState +import com.intuit.playerui.android.testutils.asset.shouldBeView import com.intuit.playerui.core.player.state.InProgressState import org.junit.Assert.assertEquals import org.junit.Test diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/input/InputTest.kt b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/input/InputTest.kt index 14f164715..e5d0b77a9 100644 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/input/InputTest.kt +++ b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/input/InputTest.kt @@ -5,9 +5,9 @@ import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.get import com.intuit.playerui.android.reference.assets.R -import com.intuit.playerui.android.reference.assets.test.AssetTest -import com.intuit.playerui.android.reference.assets.test.shouldBePlayerState -import com.intuit.playerui.android.reference.assets.test.shouldBeView +import com.intuit.playerui.android.testutils.asset.AssetTest +import com.intuit.playerui.android.testutils.asset.shouldBePlayerState +import com.intuit.playerui.android.testutils.asset.shouldBeView import com.intuit.playerui.core.player.state.InProgressState import com.intuit.playerui.core.player.state.dataModel import org.junit.Assert.assertEquals diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/BUILD b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/BUILD deleted file mode 100644 index 80a0a36f2..000000000 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/test/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -load("@rules_kotlin//kotlin:android.bzl", "kt_android_library") -load("@rules_player//kotlin:defs.bzl", "lint") -load(":deps.bzl", "main_deps") - -kt_android_library( - name = "test", - srcs = [ - "Assertions.kt", - "AssetTest.kt", - ], - visibility = ["//plugins/reference-assets/android:__subpackages__"], - deps = main_deps, -) - -lint( - name = "test", - srcs = glob(["*.kt"]), - lint_config = "//jvm:lint_config", -) diff --git a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/text/TextTest.kt b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/text/TextTest.kt index 79e573875..9aea5e843 100644 --- a/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/text/TextTest.kt +++ b/plugins/reference-assets/android/src/androidTest/java/com/intuit/playerui/android/reference/assets/text/TextTest.kt @@ -4,8 +4,8 @@ import android.widget.LinearLayout import android.widget.TextView import androidx.core.view.get import com.intuit.playerui.android.reference.assets.R -import com.intuit.playerui.android.reference.assets.test.AssetTest -import com.intuit.playerui.android.reference.assets.test.shouldBeView +import com.intuit.playerui.android.testutils.asset.AssetTest +import com.intuit.playerui.android.testutils.asset.shouldBeView import org.junit.Assert.assertEquals import org.junit.Test