From 40847a97e7b34bcb5c42521dc97be19a351dc0f8 Mon Sep 17 00:00:00 2001 From: JoeSemper Date: Thu, 24 Jun 2021 09:57:05 +0300 Subject: [PATCH 1/2] tests hw7 base commit --- app/build.gradle | 3 +++ .../justrecipebook/ExampleInstrumentedTest.kt | 24 ------------------- .../ui/fragments/cart/CartFragment.kt | 4 +--- .../ui/fragments/home/HomeFragment.kt | 6 +++-- app/src/main/res/layout/fragment_main.xml | 2 +- 5 files changed, 9 insertions(+), 30 deletions(-) delete mode 100644 app/src/androidTest/java/com/joesemper/justrecipebook/ExampleInstrumentedTest.kt diff --git a/app/build.gradle b/app/build.gradle index a859e0e..97c6b5c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -94,6 +94,9 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-core-utils:1.0.0' + debugImplementation 'androidx.fragment:fragment-testing:1.3.5' + debugImplementation 'androidx.test.espresso:espresso-contrib:3.3.0' + testImplementation "org.mockito:mockito-core:2.19.0" testImplementation 'org.mockito:mockito-inline:2.8.9' testImplementation('com.nhaarman:mockito-kotlin:1.5.0') { diff --git a/app/src/androidTest/java/com/joesemper/justrecipebook/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/joesemper/justrecipebook/ExampleInstrumentedTest.kt deleted file mode 100644 index c3db9dd..0000000 --- a/app/src/androidTest/java/com/joesemper/justrecipebook/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.joesemper.justrecipebook - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.joesemper.justrecipebook", appContext.packageName) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/cart/CartFragment.kt b/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/cart/CartFragment.kt index e965511..8d46f72 100644 --- a/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/cart/CartFragment.kt +++ b/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/cart/CartFragment.kt @@ -1,8 +1,7 @@ package com.joesemper.justrecipebook.ui.fragments.cart -import android.app.AlertDialog +import androidx.appcompat.app.AlertDialog import android.content.Context -import android.content.DialogInterface import android.os.Build import android.os.Bundle import android.os.VibrationEffect @@ -21,7 +20,6 @@ import com.joesemper.justrecipebook.ui.fragments.dialog.ingredient.IngredientDia import com.joesemper.justrecipebook.ui.interfaces.BackButtonListener import com.joesemper.justrecipebook.ui.util.view.callback.SwipeCallback import kotlinx.android.synthetic.main.fragment_cart.* -import kotlinx.android.synthetic.main.fragment_meal.* import moxy.MvpAppCompatFragment import moxy.ktx.moxyPresenter diff --git a/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/home/HomeFragment.kt b/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/home/HomeFragment.kt index 413a760..663012b 100644 --- a/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/home/HomeFragment.kt +++ b/app/src/main/java/com/joesemper/justrecipebook/ui/fragments/home/HomeFragment.kt @@ -7,6 +7,7 @@ import android.view.View.GONE import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import android.widget.Toast +import android.widget.Toolbar import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.recyclerview.widget.GridLayoutManager @@ -81,8 +82,9 @@ class HomeFragment : MvpAppCompatFragment(), HomeFragmentView, BackButtonListene } private fun initActionBar() { - with(activity as AppCompatActivity) { - setSupportActionBar(toolbar_home) + with(requireActivity()) { + setActionBar(toolbar_home ) +// setSupportActionBar(toolbar_home) } } diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 20cc2ab..29ea619 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -15,7 +15,7 @@ android:layout_height="wrap_content" android:elevation="8dp"> - Date: Thu, 24 Jun 2021 09:58:01 +0300 Subject: [PATCH 2/2] tests hw7 fragment/list test --- .../HomeFragmentEspressoTest.kt | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 app/src/androidTest/java/com/joesemper/justrecipebook/HomeFragmentEspressoTest.kt diff --git a/app/src/androidTest/java/com/joesemper/justrecipebook/HomeFragmentEspressoTest.kt b/app/src/androidTest/java/com/joesemper/justrecipebook/HomeFragmentEspressoTest.kt new file mode 100644 index 0000000..d7c8d7b --- /dev/null +++ b/app/src/androidTest/java/com/joesemper/justrecipebook/HomeFragmentEspressoTest.kt @@ -0,0 +1,198 @@ +package com.joesemper.justrecipebook + +import android.view.View +import androidx.core.os.bundleOf +import androidx.fragment.app.testing.FragmentScenario +import androidx.fragment.app.testing.launchFragmentInContainer +import androidx.lifecycle.Lifecycle +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.* +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.android.material.internal.CheckableImageButton +import com.google.android.material.textfield.TextInputLayout +import com.joesemper.justrecipebook.ui.fragments.home.HomeFragment +import com.joesemper.justrecipebook.ui.fragments.home.adapter.MealsRVAdapter +import com.joesemper.justrecipebook.ui.util.constants.SearchType +import kotlinx.android.synthetic.main.fragment_main.* +import org.hamcrest.Matcher +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class HomeFragmentEspressoTest { + + private lateinit var scenario: FragmentScenario + + @Before + fun setup() { + scenario = launchFragmentInContainer(themeResId = R.style.AppTheme) + } + + @Test + fun test_fragment_notNull() { + scenario.onFragment { + assertNotNull(it) + } + } + + @Test + fun test_fragment_presenter_notNull() { + scenario.onFragment { + assertNotNull(it.presenter) + } + } + + @Test + fun test_bundle_goes_correct() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.QUERY, "MEAL" to "") + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + scenario.onFragment { + assertEquals("", it.presenter.query) + assertEquals(SearchType.QUERY, it.presenter.searchType) + } + } + + @Test + fun test_searchView_isDisplayed() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.QUERY) + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + onView(withId(R.id.text_input_layout_search)).check(matches(isDisplayed())) + } + + @Test + fun test_onFavorites_searchView_isGone() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.FAVORITE) + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + scenario.onFragment { + assertEquals(View.GONE, it.text_input_layout_search.visibility) + } + } + + @Test + fun test_recycler_view_isDisplayed() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.QUERY, "MEAL" to "") + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + onView(withId(R.id.rv_meals)).check(matches(isDisplayed())) + } + + @Test + fun test_recycler_view_empty_search() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.QUERY, "MEAL" to "") + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + onView(isRoot()).perform(delay()) + onView(withId(R.id.rv_meals)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Sugar Pie")) + ) + ) + } + + @Test + fun test_recycler_view_category() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.CATEGORY, "MEAL" to "Pasta") + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + onView(isRoot()).perform(delay()) + onView(withId(R.id.rv_meals)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Lasagne")) + ) + ) + } + + @Test + fun test_recycler_view_favorites() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.FAVORITE) + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + onView(isRoot()).perform(delay()) + onView(withId(R.id.rv_meals)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Sugar Pie")) + ) + ) + } + + @Test + fun test_recycler_view_search() { + val fragmentArgs = bundleOf("SEARCH" to SearchType.QUERY) + val scenario = + launchFragmentInContainer(fragmentArgs, themeResId = R.style.AppTheme) + + onView(withId(R.id.text_input_search)).perform(click()) + onView(withId(R.id.text_input_search)).perform( + replaceText("Chicken"), + ViewActions.closeSoftKeyboard() + ) + +// val viewAction: ViewAction = clickOnEndIconInTextInputLayout(R.id.text_input_layout_search) +// onView(withId(R.id.text_input_layout_search)).perform(viewAction) + + onView(withId(R.id.text_input_end_icon)).perform(click()) + + onView(isRoot()).perform(delay()) + onView(withId(R.id.rv_meals)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Chicken Handi")) + ) + ) + } + + private fun delay(): ViewAction { + return object : ViewAction { + override fun getConstraints(): Matcher = isRoot() + override fun getDescription(): String = "wait for $7 seconds" + override fun perform(uiController: UiController, v: View?) { + uiController.loopMainThreadForAtLeast(7000) + } + } + } + + + + /** + * Не получилось сделать кастомный ViewAction, + * почему-то метод падает с NullPointerException. + * Должен кликать на EndIcon в TextInputLayout + */ + private fun clickOnEndIconInTextInputLayout(id: Int): ViewAction { + return object : ViewAction { + override fun getConstraints(): Matcher? { + return null + } + + override fun getDescription(): String { + return "Clicks on search icon" + } + + override fun perform(uiController: UiController, view: View) { + val v = view.findViewById(id) + (v.findViewById(R.id.text_input_end_icon) as CheckableImageButton).performClick() +// v.findViewById(R.id.text_input_end_icon)?.performClick() + } + } + } +} \ No newline at end of file