Skip to content

Commit

Permalink
Create ViewModelProvider to abstract the UI from the factory impl
Browse files Browse the repository at this point in the history
  • Loading branch information
JoaquimLey committed Apr 27, 2018
1 parent fab650e commit d2a2b73
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 48 deletions.
4 changes: 0 additions & 4 deletions transport-eta-android/mobile-ui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ android {
}
}

// testOptions {
// execution 'ANDROID_TEST_ORCHESTRATOR'
// }

packagingOptions {
exclude 'LICENSE.txt'
exclude 'META-INF/DEPENDENCIES'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ package com.joaquimley.transporteta.ui.di.module

import android.app.Application
import android.content.Context
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModelFactory
import com.joaquimley.transporteta.ui.home.favorite.FavoritesViewModelProvider
import com.joaquimley.transporteta.ui.injection.scope.PerApplication
import dagger.Module
import dagger.Provides
import org.mockito.Mockito.mock

@Module
class TestAppModule {

@Provides
fun provideFavoritesViewModelProvider(favoritesViewModelFactory: FavoritesViewModelFactory): FavoritesViewModelProvider {
return mock(FavoritesViewModelProvider::class.java)
}

@Provides
@PerApplication
fun provideContext(application: Application): Context {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
package com.joaquimley.transporteta.ui.di.module

import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModelFactory
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModelFactoryImpl
import dagger.Module
import dagger.Provides
import org.mockito.Mockito.mock

@Module
class TestFavoriteFragmentModule {

companion object {
@JvmStatic val favoritesViewModelsFactory = mock(FavoritesViewModelFactory::class.java)
}

@Provides
fun provideFavoritesViewModelFactory(): FavoritesViewModelFactory {
return favoritesViewModelsFactory
}
// companion object {
// @JvmStatic val favoritesViewModelProvider = mock(FavoritesViewModelProvider::class.java)
// }
//
// @Provides
// fun provideFavoritesViewModelProvider(favoritesViewModelFactory: FavoritesViewModelFactory): FavoritesViewModelProvider {
// return FavoritesViewModelProvider(favoritesViewModelFactory)
// }
//
// @Provides
// fun provideSmsController(): SmsController {
// return mock(SmsController::class.java)
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,19 @@ class FavoritesFragmentTest {
private val results = MutableLiveData<Resource<List<FavoriteView>>>()
private val viewModel = mock(FavoritesViewModel::class.java)


private lateinit var favoritesFragment: FavoritesFragment

@Before
fun setup() {
// Init mock ViewModel
`when`(TestFavoriteFragmentModule.favoritesViewModelsFactory.create(FavoritesViewModel::class.java)).thenReturn(viewModel)
// `when`(TestFavoriteFragmentModule.favoritesViewModelProvider.invoke(favoritesFragment)).thenReturn(viewModel)
`when`(viewModel.getFavourites()).thenReturn(results)
`when`(viewModel.getAcceptingRequests()).thenReturn(requestsAvailable)
// Instantiate fragment and add to the TestFragmentActivity
favoritesFragment = FavoritesFragment.newInstance()
`when`(favoritesFragment.viewModelProvider.invoke(favoritesFragment)).thenReturn(viewModel)

activityRule.activity.addFragment(favoritesFragment)
}

Expand Down Expand Up @@ -95,14 +98,6 @@ class FavoritesFragmentTest {
onView(withId(R.id.recycler_view)).check(matches(not(isDisplayed())))
}

/**
* Due to Android P non-sdk access an alert dialog is shown making this test flaky
*
* Issue: android.support.test.espresso.NoMatchingViewException:
* No views in hierarchy found matching: with id: com.joaquimley.transporteta.debug:id/recycler_view
*
* https://developer.android.com/preview/restrictions-non-sdk-interfaces.html
*/
@Test
fun whenThereIsDataAndErrorOccursErrorMessageIsShown() {
// When there is data
Expand Down Expand Up @@ -194,9 +189,6 @@ class FavoritesFragmentTest {
}
}

/**
* TODO: Not correctly implemented
*/
@Test
fun whenRequestButtonIsClickedViewModelRequestIsCalled() {
// Given
Expand Down Expand Up @@ -236,7 +228,7 @@ class FavoritesFragmentTest {

@Test
fun whenAcceptingRequestStateIsFalseRequestSmsButtonsAreDisabled() {
// Given (make sure requesting is not being shown)
// Given
val resultsList = TestFactoryFavoriteView.generateFavoriteViewList()
results.postValue(Resource.success(resultsList))
// When
Expand All @@ -256,16 +248,21 @@ class FavoritesFragmentTest {

@Test
fun whenAcceptingRequestStateIsTrueRequestSmsButtonsAreEnabled() {
// Given (make sure requesting is not being shown)
// Given
val resultsList = TestFactoryFavoriteView.generateFavoriteViewList()
results.postValue(Resource.success(resultsList))
// When
requestsAvailable.postValue(true)
requestsAvailable.postValue(false)
// Then ALL request ETA buttons are enabled
for (favoriteView in resultsList.withIndex()) {
// Scroll to item favoriteView.index
onView(RecyclerViewMatcher.withRecyclerView(R.id.recycler_view).atPosition(favoriteView.index))
.check(matches(hasDescendant(withId(R.id.eta_button)))).check(matches(isEnabled()))
favoritesFragment.findViewById<RecyclerView>(R.id.recycler_view)?.let {
RecyclerViewMatcher.waitForAdapterChange(it)
for (favoriteView in resultsList.withIndex()) {
// Scroll to item at favoriteView.index
onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.scrollToPosition<FavoritesAdapter.FavoriteViewHolder>(favoriteView.index))
// Check item is displayed correctly
onView(RecyclerViewMatcher.withRecyclerView(R.id.recycler_view).atPosition(favoriteView.index))
.check(matches(hasDescendant(withId(R.id.eta_button)))).check(matches(isEnabled()))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ package com.joaquimley.transporteta.ui.di.module
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModelFactory
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModelFactoryImpl
import com.joaquimley.transporteta.sms.SmsController
import com.joaquimley.transporteta.ui.home.favorite.FavoritesViewModelProvider
import dagger.Module
import dagger.Provides

@Module
class FavoriteFragmentModule {

@Provides
fun provideViewModelProvider(viewModelFactory: FavoritesViewModelFactory): FavoritesViewModelProvider {
return FavoritesViewModelProvider(viewModelFactory)
}


@Provides
fun provideFavouritesViewModelFactory(smsController: SmsController): FavoritesViewModelFactory {
return FavoritesViewModelFactoryImpl(smsController)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package com.joaquimley.transporteta.ui.home.favorite

import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.content.Context
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.design.widget.TextInputEditText
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.text.TextUtils
Expand All @@ -18,8 +16,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.joaquimley.transporteta.R
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModel
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModelFactory
import com.joaquimley.transporteta.presentation.model.FavoriteView
import com.joaquimley.transporteta.ui.model.data.ResourceState
import com.joaquimley.transporteta.ui.util.extensions.*
Expand All @@ -36,8 +32,9 @@ class FavoritesFragment : Fragment() {

private lateinit var adapter: FavoritesAdapter
private lateinit var requestingSnackbar: Snackbar
private lateinit var viewModel: FavoritesViewModel
@Inject lateinit var viewModelFactory: FavoritesViewModelFactory

@Inject lateinit var viewModelProvider: FavoritesViewModelProvider
private val viewModel by lazy { viewModelProvider(this) }

override fun onAttach(context: Context) {
AndroidSupportInjection.inject(this)
Expand All @@ -56,7 +53,7 @@ class FavoritesFragment : Fragment() {

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initViewModel()
// initViewModel()
observeFavourites()
observeRequestsEnabled()
}
Expand Down Expand Up @@ -127,11 +124,6 @@ class FavoritesFragment : Fragment() {
}
}


private fun initViewModel() {
viewModel = ViewModelProviders.of(activity as AppCompatActivity, viewModelFactory).get(FavoritesViewModel::class.java)
}

private fun setupRequestSnackbar() {
requestingSnackbar = Snackbar.make(favorites_fragment_container, R.string.info_requesting, Snackbar.LENGTH_INDEFINITE)
requestingSnackbar.setAction(R.string.action_cancel, {
Expand Down Expand Up @@ -205,4 +197,4 @@ class FavoritesFragment : Fragment() {
return fragment
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.joaquimley.transporteta.ui.home.favorite

import android.arch.lifecycle.ViewModelProviders
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModel
import com.joaquimley.transporteta.presentation.home.favorite.FavoritesViewModelFactory

class FavoritesViewModelProvider(private val viewModelFactory: FavoritesViewModelFactory) {

operator fun invoke(fragment: Fragment): FavoritesViewModel {
return provide(fragment)
}

operator fun invoke(activity: AppCompatActivity): FavoritesViewModel {
return provide(activity)
}

private fun provide(fragment: Fragment): FavoritesViewModel {
return ViewModelProviders.of(fragment, viewModelFactory).get(FavoritesViewModel::class.java)
}

private fun provide(activity: AppCompatActivity): FavoritesViewModel {
return ViewModelProviders.of(activity, viewModelFactory).get(FavoritesViewModel::class.java)
}
}

0 comments on commit d2a2b73

Please sign in to comment.