Skip to content

Instantly share code, notes, and snippets.

@alouanemed
Created March 16, 2018 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alouanemed/dc18aae0287921d55e2d4c150089b26d to your computer and use it in GitHub Desktop.
Save alouanemed/dc18aae0287921d55e2d4c150089b26d to your computer and use it in GitHub Desktop.
public abstract class BaseActivity<P extends BasePresenter<V>, V> extends DaggerAppCompatActivity
implements LoaderManager.LoaderCallbacks<P> {
...
public @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;
@Override public AndroidInjector<Fragment> supportFragmentInjector() {
if (fragmentInjector != null) return fragmentInjector;
return super.supportFragmentInjector();
}
...
}
import android.support.test.InstrumentationRegistry
import android.support.test.espresso.Espresso.onView
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import android.support.test.espresso.action.ViewActions.click
import android.support.test.espresso.assertion.ViewAssertions.doesNotExist
import android.support.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.contrib.DrawerActions
import android.support.test.espresso.contrib.DrawerActions.open
import android.support.test.espresso.contrib.DrawerMatchers.isClosed
import android.support.test.espresso.contrib.DrawerMatchers.isOpen
import android.support.test.espresso.contrib.NavigationViewActions
import android.support.test.espresso.contrib.NavigationViewActions.navigateTo
import android.support.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.matcher.BundleMatchers.hasEntry
import android.support.test.espresso.intent.matcher.IntentMatchers
import android.support.test.espresso.intent.matcher.IntentMatchers.hasExtras
import android.support.test.espresso.intent.rule.IntentsTestRule
import android.support.test.espresso.matcher.ViewMatchers.isDisplayed
import android.support.test.espresso.matcher.ViewMatchers.withId
import android.support.test.espresso.matcher.ViewMatchers.withText
import android.view.Gravity
import com.shop.app.ShopApp
import com.shop.app.MockAndroidInjectorActivity
import com.shop.app.MockAndroidInjectorFragment
import com.shop.app.R
import com.shop.app.buyer.cart.BuyerCartActivity
import com.shop.app.buyer.inbox.BuyerInboxActivity
import com.shop.app.buyer.inbox.BuyerInboxContract
import com.shop.app.buyer.orders.show.BuyerOrdersListContract
import com.shop.app.buyer.orders.show.BuyerOrdersListFragment
import com.shop.app.buyer.shippingaddress.BuyerAddressesFragment
import com.shop.app.common.presenter.loader.PresenterFactory
import com.shop.app.mock
import com.shop.app.products.details.ProductDetailsActivity
import com.shop.app.uicontainer.UiContainerActivity
import dagger.android.dispatchingActivityInjector
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.CoreMatchers.not
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner
@RunWith(MockitoJUnitRunner::class)
class MainActivityTest {
internal val presenterFactors = mock<PresenterFactory<MainContract.Presenter>>()
internal val ordersPresenterFactors = mock<PresenterFactory<BuyerOrdersListContract.Presenter>>()
internal val inboxPresenterFactors = mock<PresenterFactory<BuyerInboxContract.Presenter>>()
@get:Rule
val activityTestRule = object : IntentsTestRule<MainActivity>(MainActivity::class.java, true,
true) {
override fun beforeActivityLaunched() {
super.beforeActivityLaunched()
var myApp = InstrumentationRegistry.getTargetContext().applicationContext as ShopApp
myApp.dispatchingActivityInjector = MockAndroidInjectorActivity<MainActivity> {
mPresenterFactory = presenterFactors
}
}
}
@Before
@Throws(Exception::class)
fun setUp() {
var myApp = InstrumentationRegistry.getTargetContext().applicationContext as ShopApp
myApp.dispatchingActivityInjector = MockAndroidInjectorFragment<BuyerAddressesFragment, UiContainerActivity> {
}
myApp = InstrumentationRegistry.getTargetContext().applicationContext as ShopApp
myApp.dispatchingActivityInjector = MockAndroidInjectorActivity<BuyerInboxActivity> {
this.mPresenterFactory = inboxPresenterFactors
}
myApp = InstrumentationRegistry.getTargetContext().applicationContext as ShopApp
myApp.dispatchingActivityInjector = MockAndroidInjectorFragment<BuyerOrdersListFragment, MainActivity> {
this.mPresenterFactory = ordersPresenterFactors
}
}
@Test
fun testInitViews() {
onView(withId(R.id.fab)).check(matches(not(isDisplayed())))
}
@Test
fun clickOnInboxNavigationItem_ShowsInbox() {
// Open Drawer to click on navigation.
onView(withId(R.id.drawer_layout))
.check(matches(isClosed(Gravity.LEFT)))
.perform(open())
// Start Inbox screen.
onView(withId(R.id.nav_view))
.perform(navigateTo(R.id.nav_msg))
// Check that Inbox Activity was opened.
onView(withId(R.id.pb_dialogs_list)).check(matches(isDisplayed()))
}
@Test
fun clickOnAndroidHomeIcon_OpensNavigationAndLogOut() {
// Check that left drawer is closed at startup
onView(withId(R.id.drawer_layout))
.check(matches(isClosed(Gravity.LEFT)))
// Open Drawer
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
// Check if drawer is open
onView(withId(R.id.drawer_layout))
.check(matches(isOpen(Gravity.LEFT)))
onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_log_out))
}
@Test
fun clickOnAndroidHomeIcon_openAddresses() {
// Check that left drawer is closed at startup
onView(withId(R.id.drawer_layout))
.check(matches(isClosed(Gravity.LEFT)))
// Open Drawer
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
// Check if drawer is open
onView(withId(R.id.drawer_layout))
.check(matches(isOpen(Gravity.LEFT)))
onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_user_addresses))
intended(allOf(
hasExtras(allOf(
hasEntry(equalTo("FragmentView"),
equalTo(UiContainerActivity.FragmentViews.SHIPADDSHOW))))))
}
@Test
fun clickMenuIcon_openCart() {
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext())
//onView(withId(R.id.ho__main_action_cart)).perform(click())
onView(withText("Cart")).perform(click())
intended(IntentMatchers.hasComponent(BuyerCartActivity::class.java.name))
}
}
package com.shop.app
import android.app.Activity
import android.support.test.InstrumentationRegistry
import android.support.v4.app.Fragment
import com.shop.app.common.BaseActivity
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.DispatchingAndroidInjector_Factory
import dagger.android.dispatchingActivityInjector
import org.mockito.Mockito
import javax.inject.Provider
inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)
inline fun <reified T : Activity> MockAndroidInjectorActivity(crossinline block: T.() -> Unit)
: DispatchingAndroidInjector<Activity> {
val injector = AndroidInjector<Activity> { instance ->
if (instance is T) {
instance.block()
}
}
val factory = AndroidInjector.Factory<Activity> { injector }
val map = mapOf(
Pair<Class<out Activity>, Provider<AndroidInjector.Factory<out Activity>>>(T::class.java,
Provider { factory }))
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(map)
}
inline fun <reified F : Fragment, reified T : BaseActivity<*, *>> MockAndroidInjectorFragment(
crossinline block: F.() -> Unit)
: DispatchingAndroidInjector<Activity> {
var originalFragmentInjector: AndroidInjector<Fragment>? = null
// obtain the application level injector
val myApp = InstrumentationRegistry.getTargetContext().applicationContext as ShopApp
val originalDispatchingActivityInjector = myApp.dispatchingActivityInjector
// set the fragment injector which apply the original injector and than apply our block
val fragmentInjector = AndroidInjector<Fragment> { fragment ->
originalFragmentInjector?.inject(fragment)
if (fragment is F) {
fragment.block()
}
}
val fragmentFactory = AndroidInjector.Factory<Fragment> { fragmentInjector }
val fragmentMap = mapOf(
Pair<Class<out Fragment>, Provider<AndroidInjector.Factory<out Fragment>>>(F::class.java,
Provider { fragmentFactory }))
// obtain the activity injector
val activityInjector = AndroidInjector<Activity> { activity ->
originalDispatchingActivityInjector.inject(activity)
if (activity is T) {
originalFragmentInjector = activity.supportFragmentInjector()
activity.fragmentInjector = DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
fragmentMap)
}
}
val activityFactory = AndroidInjector.Factory<Activity> { activityInjector }
val activityMap = mapOf(
Pair<Class<out Activity>, Provider<AndroidInjector.Factory<out Activity>>>(T::class.java,
Provider { activityFactory }))
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(activityMap)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment