Skip to content

Commit

Permalink
Fix end to end tests
Browse files Browse the repository at this point in the history
  • Loading branch information
klalumiere committed Jun 16, 2024
1 parent a8defda commit ec48eed
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 26 deletions.
39 changes: 39 additions & 0 deletions .idea/androidTestResultsUserPreferences.xml

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

6 changes: 6 additions & 0 deletions .idea/deploymentTargetSelector.xml

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

26 changes: 10 additions & 16 deletions app/src/androidTest/java/klalumiere/repertoire/EndToEndTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import android.view.ViewGroup
import androidx.activity.result.ActivityResultRegistry
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.app.ActivityOptionsCompat
import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
Expand Down Expand Up @@ -40,22 +39,18 @@ import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class EndToEndTest {
private val assetUri = Uri.parse("file:///android_asset/Happy%20Birthday.md")
companion object {
private val assetUri = Uri.parse("file:///android_asset/Happy%20Birthday.md")
}
private val context = ApplicationProvider.getApplicationContext<Context>()
private lateinit var dispatcherInjector: DispatchersFactory.InjectForTests
private lateinit var contentResolverInjector: RepertoireContentResolverFactory.InjectForTests
private lateinit var addSongsLauncherActivityResultRegistryFactory: AddSongsLauncherActivityResultRegistryFactory.InjectForTests

@Test
fun canAddSong() {
val scenario = launchActivity<MainActivity>()

scenario.moveToState(Lifecycle.State.CREATED)
scenario.onActivity { activity ->
activity.injectActivityResultRegistryForTests(
createFakeActivityResultRegistry(assetUri))
}
scenario.moveToState(Lifecycle.State.RESUMED)

onView(withId(R.id.addSongsFAB)).perform(click())

onView(withId(R.id.song_list_view))
Expand All @@ -81,6 +76,7 @@ class EndToEndTest {

onView(withId(R.id.song_list_view))
.perform(actionOnItemAtPosition<SongViewHolder>(0, longClick()))

pressDeleteInOptionMenu()

onView(withId(R.id.song_list_view)).check(matches(isEmpty()))
Expand Down Expand Up @@ -142,29 +138,26 @@ class EndToEndTest {
fun clearDatabase() {
dispatcherInjector = DispatchersFactory.InjectForTests(UnconfinedTestDispatcher())
contentResolverInjector = RepertoireContentResolverFactory.InjectForTests(AssetContentResolver(context))
addSongsLauncherActivityResultRegistryFactory = AddSongsLauncherActivityResultRegistryFactory
.InjectForTests(createFakeActivityResultRegistry(assetUri))
AppDatabase.getInstance(context).songDao().deleteAll()
}

@After
fun closeResources() {
dispatcherInjector.close()
contentResolverInjector.close()
addSongsLauncherActivityResultRegistryFactory.close()
}

private fun addSong(scenario: ActivityScenario<MainActivity>) {
scenario.moveToState(Lifecycle.State.CREATED)
scenario.onActivity { activity ->
activity.injectActivityResultRegistryForTests(
createFakeActivityResultRegistry(assetUri))
}
scenario.moveToState(Lifecycle.State.RESUMED)
onView(withId(R.id.addSongsFAB)).perform(click())
}

private fun createFakeActivityResultRegistry(assetUri: Uri): ActivityResultRegistry {
return object : ActivityResultRegistry() {
override fun <I, O> onLaunch(requestCode: Int, contract: ActivityResultContract<I, O>,
input: I, options: ActivityOptionsCompat?
input: I, options: ActivityOptionsCompat?
) {
dispatchResult(requestCode, listOf(assetUri))
}
Expand All @@ -178,6 +171,7 @@ class EndToEndTest {
}



private class OrientationChange private constructor(private val orientation: Int) : ViewAction
{
companion object {
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/java/klalumiere/repertoire/Factories.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package klalumiere.repertoire

import android.content.Context
import androidx.activity.result.ActivityResultRegistry
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import java.io.Closeable
Expand Down Expand Up @@ -41,3 +42,19 @@ object RepertoireContentResolverFactory {
return injected ?: NativeContentResolver(context)
}
}

object AddSongsLauncherActivityResultRegistryFactory {
private var injected: ActivityResultRegistry? = null
class InjectForTests(rhs: ActivityResultRegistry): AutoCloseable, Closeable {
init {
injected = rhs
}
override fun close() {
injected = null
}
}

fun create(): ActivityResultRegistry? {
return injected
}
}
24 changes: 15 additions & 9 deletions app/src/main/java/klalumiere/repertoire/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import android.net.Uri
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.ActivityResultRegistry
import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
Expand All @@ -19,14 +21,15 @@ import androidx.recyclerview.widget.RecyclerView
import klalumiere.repertoire.databinding.ActivityMainBinding
import klalumiere.repertoire.databinding.ContentMainBinding

class MainActivity : AppCompatActivity() {
open class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
setSupportActionBar(binding.toolbar)

addSongsLauncher = createAddSongsLauncher()
binding.addSongsFAB.setOnClickListener { addSongsLauncher.launch(arrayOf("text/*")) }

linearLayoutManager = LinearLayoutManager(this)
Expand Down Expand Up @@ -65,14 +68,19 @@ class MainActivity : AppCompatActivity() {
songAdapter.tracker?.onSaveInstanceState(outState)
}


fun injectActivityResultRegistryForTests(registry: ActivityResultRegistry) {
addSongsLauncher = registerForActivityResult(contract, registry) { uris: List<Uri> ->
songViewModel.add(uris)
private fun createAddSongsLauncher(): ActivityResultLauncher<Array<String>> {
val registry = AddSongsLauncherActivityResultRegistryFactory.create()
return if (registry == null) {
registerForActivityResult(contract) { uris: List<Uri> ->
songViewModel.add(uris)
}
} else {
registerForActivityResult(contract, registry) { uris: List<Uri> ->
songViewModel.add(uris)
}
}
}


private fun createSelectionObserver(tracker: SelectionTracker<String>)
: SelectionTracker.SelectionObserver<String>
{
Expand Down Expand Up @@ -116,9 +124,7 @@ class MainActivity : AppCompatActivity() {
}
}
}
private var addSongsLauncher = registerForActivityResult(contract) { uris: List<Uri> ->
songViewModel.add(uris)
}
private lateinit var addSongsLauncher: ActivityResultLauncher<Array<String>>
private lateinit var deleteAction: MenuItem
private lateinit var linearLayoutManager: LinearLayoutManager
private lateinit var songAdapter: SongAdapter
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ androidx_recyclerview_recyclerview = "1.3.2"
# Updating `recyclerview-selection` to version `1.1.0` breaks `espresso`'s `longClick`,
# which is used in `EndToEndTests.kt`. Hence, we don't update it for now. See issue at
# https://issuetracker.google.com/issues/188992115
androidx_recyclerview_recyclerview_selection = "1.1.0"
androidx_recyclerview_recyclerview_selection = "1.0.0"
androidx_room = "2.6.1"
androidx_test_core_ktx = "1.5.0"
androidx_test_espresso = "3.5.1"
Expand Down

0 comments on commit ec48eed

Please sign in to comment.