diff --git a/app/instrumentation-tests/resources/lazy_videos_no_videos.ccz b/app/instrumentation-tests/resources/lazy_videos_no_videos.ccz new file mode 100644 index 000000000..7c21b7279 Binary files /dev/null and b/app/instrumentation-tests/resources/lazy_videos_no_videos.ccz differ diff --git a/app/instrumentation-tests/src/org/commcare/androidTests/LazyVideosTests.kt b/app/instrumentation-tests/src/org/commcare/androidTests/LazyVideosTests.kt new file mode 100644 index 000000000..798ad9716 --- /dev/null +++ b/app/instrumentation-tests/src/org/commcare/androidTests/LazyVideosTests.kt @@ -0,0 +1,172 @@ +package org.commcare.androidTests + + +import android.content.Intent +import android.os.Build +import android.util.Log +import androidx.test.espresso.Espresso +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.RootMatchers +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.* +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.LargeTest +import androidx.test.filters.SdkSuppress +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.commcare.CommCareApplication +import org.commcare.annotations.BrowserstackTests +import org.commcare.dalvik.R +import org.commcare.utils.CustomMatchers +import org.commcare.utils.InstrumentationUtility +import org.commcare.utils.isPresent +import org.hamcrest.CoreMatchers +import org.hamcrest.Matchers.* +import org.junit.After +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + + +@RunWith(AndroidJUnit4::class) +@LargeTest +@BrowserstackTests +class LazyVideosTests : BaseTest() { + + companion object { + const val CCZ_NAME = "lazy_videos_no_videos.ccz" + const val APP_NAME = "Lazy Videos" + } + + @Before + fun setup() { + if (CommCareApplication.instance().currentApp == null) { + InstrumentationUtility.installApp(CCZ_NAME) + } else { + InstrumentationUtility.uninstallCurrentApp() + InstrumentationUtility.installApp(CCZ_NAME) + } + Espresso.pressBack() + updateApp() + } + + @After + fun tearDown() { + InstrumentationUtility.logout() + } + + @Test + fun testVideosWithReferences() { + testVideosWithValidReference() + testVideosWithNoReferences() + } + + private fun updateApp(){ + InstrumentationUtility.openOptionsMenu() + onView(withText("Go To App Manager")) + .perform(click()) + onView(withText(APP_NAME)).perform(click()) + onView(withText("Update")) + .perform(click()) + InstrumentationUtility.waitForView(withSubstring("Update to version")) + gotoLogin() + } + + private fun gotoLogin() { + for (i in 0..2) { // Try atmost 3 times. + if (onView(withId(R.id.edit_username)).isPresent()) { + return + } else { + Espresso.pressBack() + } + } + } + private fun testVideosWithValidReference() { + InstrumentationUtility.login("test1", "123") + InstrumentationUtility.openForm(1, 0) + InstrumentationUtility.waitForView(withId(R.id.video_button)) + onView(withTagValue(CoreMatchers.`is`(R.drawable.update_download_icon))).check(matches(isDisplayed())) + InstrumentationUtility.stubIntentWithAction(Intent.ACTION_SEND) + onView(withTagValue(CoreMatchers.`is`(R.drawable.update_download_icon))).perform(click()) +// InstrumentationUtility.sleep(1) + InstrumentationUtility.waitForView(withSubstring("Download started"),5000) +// InstrumentationUtility.sleep(2) + InstrumentationUtility.waitForView(withSubstring("Download in Progress"), 5000) +// InstrumentationUtility.sleep(2) + InstrumentationUtility.waitForView(withSubstring("Download complete"), 5000) + InstrumentationUtility.waitForView(withTagValue(CoreMatchers.`is`(android.R.drawable.ic_media_play))) + InstrumentationUtility.stubIntentWithAction(Intent.ACTION_VIEW) + onView(withId(R.id.video_button)).perform(click()) + InstrumentationUtility.nextPage() + InstrumentationUtility.sleep(5) + assertTrue(onView(allOf(withId(R.id.inline_video_view))).isPresent()) + InstrumentationUtility.nextPage() + InstrumentationUtility.waitForView(CustomMatchers.withDrawable( + CommCareApplication.instance(), + R.drawable.icon_info_outline_lightcool + )) + + onView( + CustomMatchers.withDrawable( + CommCareApplication.instance(), + R.drawable.icon_info_outline_lightcool + ) + ).perform(click()) +// if(onView(withTagValue(CoreMatchers.`is`(R.drawable.update_download_icon))).isPresent()){ + onView(withTagValue(CoreMatchers.`is`(R.drawable.update_download_icon))).perform(click()) +// InstrumentationUtility.sleep(1) + InstrumentationUtility.waitForView(withSubstring("Download started"),5000) +// InstrumentationUtility.sleep(2) + InstrumentationUtility.waitForView(withSubstring("Download in Progress"), 5000) +// InstrumentationUtility.sleep(2) + InstrumentationUtility.waitForView(withSubstring("Download complete"), 5000) +// } + onView(withTagValue(CoreMatchers.`is`(android.R.drawable.ic_media_play))).check(matches(isDisplayed())) + InstrumentationUtility.stubIntentWithAction(Intent.ACTION_VIEW) + onView(withId(R.id.video_button)).perform(click()) + onView(withText("OK")).perform(click()) + InstrumentationUtility.nextPage() + + onView( + CustomMatchers.withDrawable( + CommCareApplication.instance(), + R.drawable.icon_info_outline_lightcool + ) + ).perform(click()) +// if(onView(withTagValue(CoreMatchers.`is`(R.drawable.update_download_icon))).isPresent()){ + onView(withTagValue(CoreMatchers.`is`(R.drawable.update_download_icon))).perform(click()) +// InstrumentationUtility.sleep(1) + InstrumentationUtility.waitForView(withSubstring("Download started"),5000) +// InstrumentationUtility.sleep(2) + InstrumentationUtility.waitForView(withSubstring("Download in Progress"), 5000) +// InstrumentationUtility.sleep(2) + InstrumentationUtility.waitForView(withSubstring("Download complete"), 5000) +// } + onView(withTagValue(CoreMatchers.`is`(android.R.drawable.ic_media_play))).check(matches(isDisplayed())) + InstrumentationUtility.stubIntentWithAction(Intent.ACTION_VIEW) + onView(withId(R.id.video_button)).perform(click()) + onView(withText("OK")).perform(click()) + InstrumentationUtility.submitForm() + assertTrue(onView(withText("1 form sent to server!")).isPresent()) + InstrumentationUtility.logout() + } + + private fun testVideosWithNoReferences() { + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + InstrumentationUtility.login("test1", "123") + InstrumentationUtility.openForm(1, 1) + InstrumentationUtility.waitForView(withText(R.string.video_download_prompt)) + onView(withTagValue(CoreMatchers.`is`(R.drawable.update_download_icon))).check(matches(isDisplayed())) + onView(withId(R.id.video_button)).perform(click()) + InstrumentationUtility.waitForView(withText(R.string.download_complete)) + InstrumentationUtility.waitForView(withText("Media not found in the application")) + InstrumentationUtility.nextPage() + assertTrue(onView(withId(R.id.missing_media_view)).isPresent()) + InstrumentationUtility.submitForm() + assertTrue(onView(withText("1 form sent to server!")).isPresent()) + } +} diff --git a/app/instrumentation-tests/src/org/commcare/utils/CustomMatchers.kt b/app/instrumentation-tests/src/org/commcare/utils/CustomMatchers.kt index 1fc9d0b27..f6f6975e9 100644 --- a/app/instrumentation-tests/src/org/commcare/utils/CustomMatchers.kt +++ b/app/instrumentation-tests/src/org/commcare/utils/CustomMatchers.kt @@ -1,10 +1,16 @@ package org.commcare.utils +import android.content.Context import android.content.Intent +import android.content.res.Resources +import android.graphics.drawable.Drawable import android.view.View import android.view.ViewGroup +import android.widget.ImageButton +import android.widget.ImageView import android.widget.ListView import android.widget.TextView +import androidx.appcompat.view.menu.ActionMenuItemView import androidx.test.espresso.matcher.BoundedMatcher import androidx.test.espresso.util.TreeIterables import org.commcare.android.database.global.models.AppAvailableToInstall @@ -145,4 +151,26 @@ object CustomMatchers { } } + fun withDrawable(targetContext: Context, expectedId: Int): Matcher { + return object : TypeSafeMatcher(View::class.java) { + + override fun describeTo(description: Description?) { + description!!.appendText("with drawable from resource id: $expectedId") + targetContext.resources.getResourceEntryName(expectedId)?.let { description.appendText("[$it]") } + } + + override fun matchesSafely(view: View?): Boolean { + val drawable: Drawable = when (view) { + is ActionMenuItemView -> view.itemData.icon + is ImageView -> view.drawable + is ImageButton -> view.drawable + else -> null + } ?: return false + + val resources: Resources = view!!.context.resources + val expectedDrawable: Drawable? = resources.getDrawable(expectedId, targetContext.theme) + return expectedDrawable?.constantState?.let { it == drawable.constantState } ?: false + } + } + } } diff --git a/app/src/org/commcare/views/media/MediaLayout.java b/app/src/org/commcare/views/media/MediaLayout.java index 2ef29d44b..215e5a852 100644 --- a/app/src/org/commcare/views/media/MediaLayout.java +++ b/app/src/org/commcare/views/media/MediaLayout.java @@ -192,7 +192,9 @@ private void setupStandardAudio(String audioURI, int questionIndex) { private void setupVideoButton(String videoURI) { if (videoURI != null) { boolean mediaPresent = FileUtil.referenceFileExists(videoURI); - videoButton.setImageResource(mediaPresent ? android.R.drawable.ic_media_play : R.drawable.update_download_icon); + int imageResource = mediaPresent ? android.R.drawable.ic_media_play : R.drawable.update_download_icon; + videoButton.setImageResource(imageResource); + videoButton.setTag(imageResource); // this is to easily test drawables with Espresso if (!mediaPresent) { AndroidUtil.showToast(getContext(), R.string.video_download_prompt); }