diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 36c57f9e9..6760a312e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -10,18 +10,15 @@ jobs: build: name: Run tests and generate APK runs-on: ubuntu-latest - strategy: - matrix: - api-level: [23] - steps: - - uses: actions/checkout@v2.4.0 + - name: Checkout code + uses: actions/checkout@v2.4.0 - name: Set up JDK uses: actions/setup-java@v2.5.0 with: distribution: "temurin" - java-version: 8 + java-version: 11 - name: Cache packages id: cache-packages @@ -33,43 +30,60 @@ jobs: key: gradle-packages-${{ runner.os }}-${{ hashFiles('**/*.gradle', '**/*.gradle.kts', 'gradle.properties') }} restore-keys: gradle-packages-${{ runner.os }} + - name: Access test login credentials + run: | + echo "TEST_USER_NAME=${{ secrets.TEST_USER_NAME }}" >> local.properties + echo "TEST_USER_PASSWORD=${{ secrets.TEST_USER_PASSWORD }}" >> local.properties + - name: AVD cache + if: github.event_name != 'pull_request' uses: actions/cache@v2 id: avd-cache with: path: | ~/.android/avd/* ~/.android/adb* - key: avd-${{ matrix.api-level }} + key: avd-tablet-api-24 - name: Create AVD and generate snapshot for caching - if: steps.avd-cache.outputs.cache-hit != 'true' + if: steps.avd-cache.outputs.cache-hit != 'true' && github.event_name != 'pull_request' uses: reactivecircus/android-emulator-runner@v2 with: - api-level: ${{ matrix.api-level }} + api-level: 24 force-avd-creation: false emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - disable-animations: false + disable-animations: true script: echo "Generated AVD snapshot for caching." - name: Run Instrumentation tests + if: github.event_name != 'pull_request' uses: reactivecircus/android-emulator-runner@v2 with: - api-level: ${{ matrix.api-level }} + api-level: 24 force-avd-creation: false emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true - profile: Nexus 6 - script: ./gradlew connectedBetaDebugAndroidTest --stacktrace + profile: Nexus 10 + script: | + adb shell content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0 + adb shell content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:0 + adb emu geo fix 37.422131 -122.084801 + ./gradlew connectedBetaDebugAndroidTest --stacktrace - - name: Run Unit tests + - name: Run Unit tests with unified coverage + if: github.event_name != 'pull_request' + run: ./gradlew -Pcoverage testBetaDebugUnitTestUnifiedCoverage --stacktrace + + - name: Run Unit tests without unified coverage + if: github.event_name == 'pull_request' run: ./gradlew -Pcoverage testBetaDebugUnitTestCoverage --stacktrace - name: Upload Test Report to Codecov + if: github.event_name != 'pull_request' run: | curl -Os https://uploader.codecov.io/latest/linux/codecov chmod +x codecov - ./codecov -f "app/build/reports/jacoco/testBetaDebugUnitTestCoverage/testBetaDebugUnitTestCoverage.xml" -Z + ./codecov -f "app/build/reports/jacoco/testBetaDebugUnitTestUnifiedCoverage/testBetaDebugUnitTestUnifiedCoverage.xml" -Z - name: Generate betaDebug APK run: bash ./gradlew assembleBetaDebug --stacktrace diff --git a/app/build.gradle b/app/build.gradle index 864ab2743..daff00e52 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,14 +97,17 @@ dependencies { // Android testing androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$KOTLIN_VERSION" - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test:rules:1.2.0' - androidTestImplementation 'androidx.annotation:annotation:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0-alpha04' + androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' + androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.0-alpha04' + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'androidx.test:rules:1.4.1-alpha04' + androidTestImplementation 'androidx.test:core:1.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.annotation:annotation:1.3.0' androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.8.0' - androidTestUtil 'androidx.test:orchestrator:1.2.0' + androidTestImplementation "androidx.test.uiautomator:uiautomator:2.2.0" + androidTestUtil 'androidx.test:orchestrator:1.4.1' // Debugging debugImplementation "com.squareup.leakcanary:leakcanary-android:$LEAK_CANARY_VERSION" @@ -152,6 +155,18 @@ dependencies { implementation("io.github.coordinates2country:coordinates2country-android:1.2") { exclude group: 'com.google.android', module: 'android' } } +task disableAnimations(type: Exec) { + def adb = "$System.env.ANDROID_HOME/platform-tools/adb" + commandLine "$adb", 'shell', 'settings', 'put', 'global', 'window_animation_scale', '0' + commandLine "$adb", 'shell', 'settings', 'put', 'global', 'transition_animation_scale', '0' + commandLine "$adb", 'shell', 'settings', 'put', 'global', 'animator_duration_scale', '0' +} + +project.gradle.taskGraph.whenReady { + connectedBetaDebugAndroidTest.dependsOn disableAnimations + connectedProdDebugAndroidTest.dependsOn disableAnimations +} + android { compileSdkVersion 30 @@ -264,8 +279,8 @@ android { buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.locations.contentprovider\"" buildConfigField "String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.items.contentprovider\"" buildConfigField "String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\"" - buildConfigField "String", "TEST_USERNAME", "\"" + System.getenv("test_user_name") + "\"" - buildConfigField "String", "TEST_PASSWORD", "\"" + System.getenv("test_user_password") + "\"" + buildConfigField "String", "TEST_USERNAME", "\"" + getTestUserName() + "\"" + buildConfigField "String", "TEST_PASSWORD", "\"" + getTestPassword() + "\"" buildConfigField "String", "DEPICTS_PROPERTY", "\"P180\"" dimension 'tier' @@ -300,8 +315,8 @@ android { buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.locations.contentprovider\"" buildConfigField "String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.items.contentprovider\"" buildConfigField "String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\"" - buildConfigField "String", "TEST_USERNAME", "\"" + System.getenv("test_user_name") + "\"" - buildConfigField "String", "TEST_PASSWORD", "\"" + System.getenv("test_user_password") + "\"" + buildConfigField "String", "TEST_USERNAME", "\"" + getTestUserName() + "\"" + buildConfigField "String", "TEST_PASSWORD", "\"" + getTestPassword() + "\"" buildConfigField "String", "DEPICTS_PROPERTY", "\"P245962\"" dimension 'tier' @@ -327,6 +342,20 @@ android { } +String getTestUserName() { + def propFile = rootProject.file("./local.properties") + def properties = new Properties() + properties.load(new FileInputStream(propFile)) + return properties['TEST_USER_NAME'] +} + +String getTestPassword() { + def propFile = rootProject.file("./local.properties") + def properties = new Properties() + properties.load(new FileInputStream(propFile)) + return properties['TEST_USER_PASSWORD'] +} + if (isRunningOnTravisAndIsNotPRBuild) { play { track = "alpha" diff --git a/app/src/androidTest/java/fr/free/nrw/commons/AboutActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/AboutActivityTest.kt index 0e71235d0..9425a1d47 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/AboutActivityTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/AboutActivityTest.kt @@ -3,7 +3,6 @@ package fr.free.nrw.commons import android.app.Activity import android.app.Instrumentation import android.content.Intent -import androidx.test.InstrumentationRegistry import androidx.test.core.app.ApplicationProvider.getApplicationContext import androidx.test.espresso.Espresso import androidx.test.espresso.action.ViewActions @@ -12,100 +11,120 @@ import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 +import androidx.test.uiautomator.UiDevice import fr.free.nrw.commons.utils.ConfigUtils.getVersionNameWithSha import org.hamcrest.CoreMatchers +import org.junit.After import org.junit.Before -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class AboutActivityTest { + @get:Rule var activityRule: ActivityTestRule<*> = ActivityTestRule(AboutActivity::class.java) + private val device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + @Before fun setup() { + device.setOrientationNatural() + device.freezeRotation() Intents.init() Intents.intending(CoreMatchers.not(IntentMatchers.isInternal())) - .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, null)) + .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, null)) + } + + @After + fun cleanUp() { + Intents.release() } @Test - @Ignore("Fix Failing Test") fun testBuildNumber() { Espresso.onView(ViewMatchers.withId(R.id.about_version)) - .check(ViewAssertions.matches( + .check( + ViewAssertions.matches( withText(getApplicationContext().getVersionNameWithSha()) - )) + ) + ) } @Test - @Ignore("Fix Failing Test") fun testLaunchWebsite() { Espresso.onView(ViewMatchers.withId(R.id.website_launch_icon)).perform(ViewActions.click()) - Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), - IntentMatchers.hasData(Urls.WEBSITE_URL))) + Intents.intended( + CoreMatchers.allOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData(Urls.WEBSITE_URL) + ) + ) } @Test - @Ignore("Fix Failing Test") fun testLaunchFacebook() { Espresso.onView(ViewMatchers.withId(R.id.facebook_launch_icon)).perform(ViewActions.click()) - Intents.intended(IntentMatchers.hasAction(Intent.ACTION_VIEW)) - Intents.intended(CoreMatchers.anyOf(IntentMatchers.hasData(Urls.FACEBOOK_WEB_URL), - IntentMatchers.hasPackage(Urls.FACEBOOK_PACKAGE_NAME))) + Intents.intended( + CoreMatchers.anyOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData(Urls.FACEBOOK_WEB_URL), + IntentMatchers.hasPackage(Urls.FACEBOOK_PACKAGE_NAME) + ) + ) } @Test - @Ignore("Fix Failing Test") fun testLaunchGithub() { Espresso.onView(ViewMatchers.withId(R.id.github_launch_icon)).perform(ViewActions.click()) - Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), - IntentMatchers.hasData(Urls.GITHUB_REPO_URL))) + Intents.intended( + CoreMatchers.allOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData(Urls.GITHUB_REPO_URL) + ) + ) } @Test - @Ignore("Fix Failing Test") - fun testLaunchRateUs() { - val appPackageName = InstrumentationRegistry.getInstrumentation().targetContext.packageName - Espresso.onView(ViewMatchers.withId(R.id.about_rate_us)).perform(ViewActions.click()) - Intents.intended(IntentMatchers.hasAction(Intent.ACTION_VIEW)) - Intents.intended(CoreMatchers.anyOf(IntentMatchers.hasData("${Urls.PLAY_STORE_URL_PREFIX}$appPackageName"), - IntentMatchers.hasData("${Urls.PLAY_STORE_URL_PREFIX}$appPackageName"))) - } - - @Test - @Ignore("Fix Failing Test") fun testLaunchAboutPrivacyPolicy() { Espresso.onView(ViewMatchers.withId(R.id.about_privacy_policy)).perform(ViewActions.click()) - Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), - IntentMatchers.hasData(BuildConfig.PRIVACY_POLICY_URL))) + Intents.intended( + CoreMatchers.allOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData(BuildConfig.PRIVACY_POLICY_URL) + ) + ) } @Test - @Ignore("Fix Failing Test") fun testLaunchTranslate() { Espresso.onView(ViewMatchers.withId(R.id.about_translate)).perform(ViewActions.click()) Espresso.onView(ViewMatchers.withId(android.R.id.button1)).perform(ViewActions.click()) val langCode = CommonsApplication.getInstance().languageLookUpTable.codes[0] - Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), - IntentMatchers.hasData("${Urls.TRANSLATE_WIKI_URL}$langCode"))) + Intents.intended( + CoreMatchers.allOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData("${Urls.TRANSLATE_WIKI_URL}$langCode") + ) + ) } @Test - @Ignore("Fix Failing Test") fun testLaunchAboutCredits() { Espresso.onView(ViewMatchers.withId(R.id.about_credits)).perform(ViewActions.click()) - Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), - IntentMatchers.hasData(Urls.CREDITS_URL))) + Intents.intended( + CoreMatchers.allOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData(Urls.CREDITS_URL) + ) + ) } @Test - @Ignore("Fix Failing Test") fun testLaunchUserGuide() { Espresso.onView(ViewMatchers.withId(R.id.about_user_guide)).perform(ViewActions.click()) Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), @@ -114,15 +133,13 @@ class AboutActivityTest { @Test - @Ignore("Fix Failing Test") fun testLaunchAboutFaq() { Espresso.onView(ViewMatchers.withId(R.id.about_faq)).perform(ViewActions.click()) - Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), - IntentMatchers.hasData(Urls.FAQ_URL))) + Intents.intended( + CoreMatchers.allOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData(Urls.FAQ_URL) + ) + ) } - - @Test - fun orientationChange() { - UITestHelper.changeOrientation(activityRule) - } -} \ No newline at end of file +} diff --git a/app/src/androidTest/java/fr/free/nrw/commons/AchievementsActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/AchievementsActivityTest.kt deleted file mode 100644 index c8dacff49..000000000 --- a/app/src/androidTest/java/fr/free/nrw/commons/AchievementsActivityTest.kt +++ /dev/null @@ -1,37 +0,0 @@ -package fr.free.nrw.commons - -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.contrib.DrawerActions -import androidx.test.espresso.intent.Intents -import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent -import androidx.test.espresso.intent.rule.IntentsTestRule -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.runner.AndroidJUnit4 -import fr.free.nrw.commons.auth.LoginActivity -import fr.free.nrw.commons.profile.ProfileActivity -import org.junit.Before -import org.junit.Ignore -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class AchievementsActivityTest { - @get:Rule - var activityRule = IntentsTestRule(LoginActivity::class.java) - - @Before - fun setup() { - UITestHelper.skipWelcome() - UITestHelper.loginUser() - } - - @Test - @Ignore("Fix Failing Test") - fun testAchievements() { - onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()) - - Intents.intended(hasComponent(ProfileActivity::class.java.name)) - } -} diff --git a/app/src/androidTest/java/fr/free/nrw/commons/DepictionSearchTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/DepictionSearchTest.kt deleted file mode 100644 index 9ed76f42c..000000000 --- a/app/src/androidTest/java/fr/free/nrw/commons/DepictionSearchTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -package fr.free.nrw.commons - -import androidx.test.runner.AndroidJUnit4 -import org.junit.Rule -import org.junit.runner.RunWith -import android.net.Uri -import androidx.test.espresso.Espresso -import androidx.test.espresso.action.ViewActions -import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.rule.ActivityTestRule -import fr.free.nrw.commons.upload.UploadActivity -import org.hamcrest.Matchers -import org.hamcrest.core.AllOf -import org.junit.Ignore -import org.junit.Test - -@RunWith(AndroidJUnit4::class) -class DepictionSearchTest { - @get:Rule - var activityRule = ActivityTestRule(UploadActivity::class.java) - - @Test - @Ignore("Fix Failing Test") - fun TestForCaptionsAndDepictions() { - val imageUri = Uri.parse("file://mnt/sdcard/image.jpg") - - // Build a result to return from the Camera app - - - // Stub out the File picker. When an intent is sent to the File picker, this tells - // Espresso to respond with the ActivityResult we just created - - Espresso.onView(ViewMatchers.withId(R.id.caption_item_edit_text)) - .perform(ViewActions.typeText("caption in english")) - Espresso.onView(ViewMatchers.withId(R.id.description_item_edit_text)) - .perform(ViewActions.typeText("description in english")) - Espresso.onData(AllOf.allOf(Matchers.anything("spinner text"))).atPosition(1).perform(ViewActions.click()); - Espresso.onView(ViewMatchers.withId(R.id.caption_item_edit_text)) - .perform(ViewActions.typeText("caption in some other language")) - Espresso.onView(ViewMatchers.withId(R.id.description_item_edit_text)) - .perform(ViewActions.typeText("description in some other language")) - Espresso.onView(ViewMatchers.withId(R.id.btn_next)) - .perform(ViewActions.click()) - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/LeaderboardActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/LeaderboardActivityTest.kt deleted file mode 100644 index 20e387927..000000000 --- a/app/src/androidTest/java/fr/free/nrw/commons/LeaderboardActivityTest.kt +++ /dev/null @@ -1,92 +0,0 @@ -package fr.free.nrw.commons - -import android.app.Activity -import android.app.Instrumentation.ActivityResult -import android.view.View -import androidx.test.espresso.Espresso -import androidx.test.espresso.PerformException -import androidx.test.espresso.UiController -import androidx.test.espresso.ViewAction -import androidx.test.espresso.action.ViewActions -import androidx.test.espresso.contrib.DrawerActions -import androidx.test.espresso.intent.Intents -import androidx.test.espresso.intent.Intents.intending -import androidx.test.espresso.intent.matcher.IntentMatchers.isInternal -import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 -import fr.free.nrw.commons.auth.LoginActivity -import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom -import androidx.test.espresso.matcher.ViewMatchers.isDisplayed -import com.google.android.material.tabs.TabLayout -import org.hamcrest.CoreMatchers.allOf -import org.hamcrest.CoreMatchers.not -import org.junit.Before -import org.junit.Ignore -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class LeaderboardActivityTest { - @get:Rule - var activityRule = ActivityTestRule(LoginActivity::class.java) - - @Before - fun setup() { - try { - Intents.init() - } catch (ex: IllegalStateException) { - - } - UITestHelper.skipWelcome() - intending(not(isInternal())).respondWith(ActivityResult(Activity.RESULT_OK, null)) - } - - @Test - @Ignore("Fix Failing Test") - fun testScrollToRankFromAbove() { - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open()) - - Espresso.onView(ViewMatchers.withId(R.id.tab_layout)).perform(ViewActions.click()) - Espresso.onView(ViewMatchers.withId(R.id.tab_layout)).perform(selectTabAtPosition(1)) - - UITestHelper.sleep(10000) - - Espresso.onView(ViewMatchers.withId(R.id.scroll)).perform(ViewActions.click()) - } - - @Test - @Ignore("Fix Failing Test") - fun testScrollToRankFromBelow() { - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open()) - - Espresso.onView(ViewMatchers.withId(R.id.tab_layout)).perform(ViewActions.click()) - Espresso.onView(ViewMatchers.withId(R.id.tab_layout)).perform(selectTabAtPosition(1)) - - UITestHelper.sleep(10000) - - Espresso.onView(ViewMatchers.withId(R.id.leaderboard_list)).perform(ViewActions.swipeUp()) - Espresso.onView(ViewMatchers.withId(R.id.leaderboard_list)).perform(ViewActions.swipeUp()) - - Espresso.onView(ViewMatchers.withId(R.id.scroll)).perform(ViewActions.click()) - } - - private fun selectTabAtPosition(tabIndex: Int): ViewAction { - return object : ViewAction { - override fun getDescription() = "with tab at index $tabIndex" - - override fun getConstraints() = allOf(isDisplayed(), isAssignableFrom(TabLayout::class.java)) - - override fun perform(uiController: UiController, view: View) { - val tabLayout = view as TabLayout - val tabAtIndex: TabLayout.Tab = tabLayout.getTabAt(tabIndex) - ?: throw PerformException.Builder() - .withCause(Throwable("No tab at index $tabIndex")) - .build() - - tabAtIndex.select() - } - } - } -} diff --git a/app/src/androidTest/java/fr/free/nrw/commons/LoginActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/LoginActivityTest.kt index 43adfcdf9..5039a2495 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/LoginActivityTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/LoginActivityTest.kt @@ -8,55 +8,59 @@ import androidx.test.espresso.action.ViewActions import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.Intents.intending import androidx.test.espresso.intent.matcher.IntentMatchers -import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.espresso.intent.matcher.IntentMatchers.isInternal import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 +import androidx.test.uiautomator.UiDevice import fr.free.nrw.commons.auth.LoginActivity -import fr.free.nrw.commons.contributions.MainActivity +import fr.free.nrw.commons.auth.SignupActivity import org.hamcrest.CoreMatchers import org.hamcrest.CoreMatchers.not -import org.junit.Before -import org.junit.Ignore -import org.junit.Rule -import org.junit.Test +import org.junit.* import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class LoginActivityTest { + @get:Rule var activityRule = ActivityTestRule(LoginActivity::class.java) + private val device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + @Before fun setup() { - try { - Intents.init() - } catch (ex: IllegalStateException) { - - } + device.setOrientationNatural() + device.freezeRotation() + Intents.init() UITestHelper.skipWelcome() intending(not(isInternal())).respondWith(ActivityResult(Activity.RESULT_OK, null)) } - @Test - @Ignore("Fix Failing Test") - fun testLogin() { - UITestHelper.loginUser() - Intents.intended(hasComponent(MainActivity::class.java.name)) + @After + fun cleanUp() { + Intents.release() } @Test - @Ignore("Fix Failing Test") fun testForgotPassword() { - UITestHelper.sleep(3000) - Espresso.onView(ViewMatchers.withId(R.id.forgot_password)) - .perform(ViewActions.click()) - Intents.intended(CoreMatchers.allOf(IntentMatchers.hasAction(Intent.ACTION_VIEW), IntentMatchers.hasData(BuildConfig.FORGOT_PASSWORD_URL))); + Espresso.onView(ViewMatchers.withId(R.id.forgot_password)).perform(ViewActions.click()) + Intents.intended( + CoreMatchers.allOf( + IntentMatchers.hasAction(Intent.ACTION_VIEW), + IntentMatchers.hasData(BuildConfig.FORGOT_PASSWORD_URL) + ) + ) + } + + @Test + fun testSignupButton() { + Espresso.onView(ViewMatchers.withId(R.id.sign_up_button)).perform(ViewActions.click()) + Intents.intended(IntentMatchers.hasComponent(SignupActivity::class.java.name)) } @Test - @Ignore("Fix Failing Test") fun orientationChange() { UITestHelper.changeOrientation(activityRule) } diff --git a/app/src/androidTest/java/fr/free/nrw/commons/MainActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/MainActivityTest.kt index 3beb73948..c898ca029 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/MainActivityTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/MainActivityTest.kt @@ -1,21 +1,230 @@ package fr.free.nrw.commons +import android.app.Activity +import android.app.Instrumentation +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.LargeTest +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 -import fr.free.nrw.commons.contributions.MainActivity -import org.junit.Ignore -import org.junit.Rule -import org.junit.Test +import androidx.test.rule.GrantPermissionRule +import androidx.test.uiautomator.UiDevice +import com.google.gson.Gson +import fr.free.nrw.commons.UITestHelper.Companion.childAtPosition +import fr.free.nrw.commons.auth.LoginActivity +import fr.free.nrw.commons.kvstore.JsonKvStore +import fr.free.nrw.commons.notification.NotificationActivity +import org.hamcrest.CoreMatchers +import org.hamcrest.Matchers +import org.junit.* import org.junit.runner.RunWith +@LargeTest @RunWith(AndroidJUnit4::class) class MainActivityTest { + @get:Rule - var activityRule = ActivityTestRule(MainActivity::class.java) + var activityRule: ActivityTestRule<*> = ActivityTestRule(LoginActivity::class.java) + + @get:Rule + var mGrantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant( + "android.permission.ACCESS_FINE_LOCATION" + ) + + private val device: UiDevice = + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + private lateinit var defaultKvStore: JsonKvStore + + @Before + fun setup() { + device.setOrientationNatural() + device.freezeRotation() + UITestHelper.loginUser() + UITestHelper.skipWelcome() + Intents.init() + Intents.intending(CoreMatchers.not(IntentMatchers.isInternal())) + .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, null)) + val context = InstrumentationRegistry.getInstrumentation().targetContext + val storeName = context.packageName + "_preferences" + defaultKvStore = JsonKvStore(context, storeName, Gson()) + } + + @After + fun cleanUp() { + Intents.release() + } @Test - @Ignore("Fix Failing Test") - fun orientationChange() { - UITestHelper.changeOrientation(activityRule) + fun testNearby() { + Espresso.onView( + Matchers.allOf( + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 1 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + Espresso.onView(ViewMatchers.withId(R.id.fragmentContainer)) + .check(matches(ViewMatchers.isDisplayed())) + UITestHelper.sleep(10000) + val actionMenuItemView2 = Espresso.onView( + Matchers.allOf( + ViewMatchers.withId(R.id.list_sheet), ViewMatchers.withContentDescription("List"), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.toolbar), + 1 + ), + 0 + ), + ViewMatchers.isDisplayed() + ) + ) + actionMenuItemView2.perform(ViewActions.click()) + UITestHelper.sleep(1000) } + + @Test + fun testExplore() { + Espresso.onView( + Matchers.allOf( + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 2 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + Espresso.onView(ViewMatchers.withId(R.id.fragmentContainer)) + .check(matches(ViewMatchers.isDisplayed())) + UITestHelper.sleep(1000) + } + + @Test + fun testContributions() { + Espresso.onView( + Matchers.allOf( + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 0 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + Espresso.onView(ViewMatchers.withId(R.id.fragmentContainer)) + .check(matches(ViewMatchers.isDisplayed())) + Espresso.onView( + Matchers.allOf( + ViewMatchers.withId(R.id.contributionImage), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.contributionsList), + 0 + ), + 1 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + val actionMenuItemView = Espresso.onView( + Matchers.allOf( + ViewMatchers.withId(R.id.menu_bookmark_current_image), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.toolbar), + 1 + ), + 0 + ), + ViewMatchers.isDisplayed() + ) + ) + actionMenuItemView.perform(ViewActions.click()) + UITestHelper.sleep(3000) + } + + @Test + fun testBookmarks() { + Espresso.onView( + Matchers.allOf( + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 3 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + UITestHelper.sleep(1000) + } + + @Test + fun testNotifications() { + Espresso.onView( + Matchers.allOf( + ViewMatchers.withId(R.id.notifications), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.toolbar), + 1 + ), + 1 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + Intents.intended(IntentMatchers.hasComponent(NotificationActivity::class.java.name)) + Espresso.pressBack() + UITestHelper.sleep(1000) + } + + @Test + fun testLimitedConnectionModeToggle() { + val isEnabled = defaultKvStore + .getBoolean(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED, false) + Espresso.onView( + Matchers.allOf( + ViewMatchers.withId(R.id.toggle_limited_connection_mode), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.toolbar), + 1 + ), + 0 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + UITestHelper.sleep(1000) + if (isEnabled) { + Assert.assertFalse( + defaultKvStore + .getBoolean(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED, false) + ) + } else { + Assert.assertTrue( + defaultKvStore + .getBoolean(CommonsApplication.IS_LIMITED_CONNECTION_MODE_ENABLED, false) + ) + } + } + } \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/ProfileActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/ProfileActivityTest.kt new file mode 100644 index 000000000..524274d54 --- /dev/null +++ b/app/src/androidTest/java/fr/free/nrw/commons/ProfileActivityTest.kt @@ -0,0 +1,69 @@ +package fr.free.nrw.commons + +import android.app.Activity +import android.app.Instrumentation +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.swipeRight +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers +import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent +import androidx.test.espresso.intent.rule.IntentsTestRule +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation +import androidx.test.uiautomator.UiDevice +import fr.free.nrw.commons.UITestHelper.Companion.childAtPosition +import fr.free.nrw.commons.auth.LoginActivity +import fr.free.nrw.commons.profile.ProfileActivity +import org.hamcrest.CoreMatchers +import org.hamcrest.Matchers +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ProfileActivityTest { + + @get:Rule + var activityRule = IntentsTestRule(LoginActivity::class.java) + + private val device: UiDevice = UiDevice.getInstance(getInstrumentation()) + + @Before + fun setup() { + device.setOrientationNatural() + device.freezeRotation() + UITestHelper.loginUser() + UITestHelper.skipWelcome() + Intents.intending(CoreMatchers.not(IntentMatchers.isInternal())) + .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, null)) + } + + @Test + fun testProfile() { + onView( + Matchers.allOf( + ViewMatchers.withContentDescription("More"), + childAtPosition( + childAtPosition( + withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 4 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + onView(Matchers.allOf(withId(R.id.more_profile))).perform( + ViewActions.scrollTo(), + ViewActions.click() + ) + device.swipe(1033,1346,531,1346,20) + UITestHelper.sleep(5000) + Intents.intended(hasComponent(ProfileActivity::class.java.name)) + } + +} diff --git a/app/src/androidTest/java/fr/free/nrw/commons/ReviewActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/ReviewActivityTest.kt new file mode 100644 index 000000000..dd52dbc3b --- /dev/null +++ b/app/src/androidTest/java/fr/free/nrw/commons/ReviewActivityTest.kt @@ -0,0 +1,21 @@ +package fr.free.nrw.commons + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.rule.ActivityTestRule +import fr.free.nrw.commons.review.ReviewActivity +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ReviewActivityTest { + + @get:Rule + var activityRule: ActivityTestRule<*> = ActivityTestRule(ReviewActivity::class.java) + + @Test + fun orientationChange() { + UITestHelper.changeOrientation(activityRule) + } + +} \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/SearchActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/SearchActivityTest.kt index 5e58fca9b..c42b49e92 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/SearchActivityTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/SearchActivityTest.kt @@ -1,19 +1,59 @@ package fr.free.nrw.commons +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 +import androidx.test.uiautomator.UiDevice +import fr.free.nrw.commons.explore.SearchActivity +import org.hamcrest.Matchers +import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import fr.free.nrw.commons.explore.SearchActivity @RunWith(AndroidJUnit4::class) class SearchActivityTest { + @get:Rule var activityRule = ActivityTestRule(SearchActivity::class.java) + private val device: UiDevice = + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Before + fun setup() { + device.setOrientationNatural() + device.freezeRotation() + } + @Test - fun orientationChange() { - UITestHelper.changeOrientation(activityRule) + fun exploreActivityTest() { + val searchAutoComplete = Espresso.onView( + Matchers.allOf( + UITestHelper.childAtPosition( + Matchers.allOf( + ViewMatchers.withClassName(Matchers.`is`("android.widget.LinearLayout")), + UITestHelper.childAtPosition( + ViewMatchers.withClassName(Matchers.`is`("android.widget.LinearLayout")), + 1 + ) + ), + 0 + ), + ViewMatchers.isDisplayed() + ) + ) + searchAutoComplete.perform(ViewActions.replaceText("cat"), ViewActions.closeSoftKeyboard()) + UITestHelper.sleep(5000) + device.swipe(1000, 1400, 500, 1400, 20) + device.swipe(800, 1400, 600, 1400, 20) + device.swipe(800, 1400, 600, 1400, 20) + device.swipe(800, 1400, 600, 1400, 20) + device.swipe(800, 1400, 600, 1400, 20) + device.swipe(800, 1400, 600, 1400, 20) + UITestHelper.sleep(1000) } } \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityLoggedInTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityLoggedInTest.kt new file mode 100644 index 000000000..3d464fb5a --- /dev/null +++ b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityLoggedInTest.kt @@ -0,0 +1,65 @@ +package fr.free.nrw.commons + +import android.app.Activity +import android.app.Instrumentation +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.ActivityTestRule +import androidx.test.uiautomator.UiDevice +import fr.free.nrw.commons.auth.LoginActivity +import fr.free.nrw.commons.settings.SettingsActivity +import org.hamcrest.CoreMatchers +import org.hamcrest.Matchers +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SettingsActivityLoggedInTest { + + @get:Rule + var activityRule: ActivityTestRule<*> = ActivityTestRule(LoginActivity::class.java) + + private val device: UiDevice = + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Before + fun setup() { + device.setOrientationNatural() + device.freezeRotation() + UITestHelper.loginUser() + UITestHelper.skipWelcome() + Intents.intending(CoreMatchers.not(IntentMatchers.isInternal())) + .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, null)) + } + + @Test + fun testSettings() { + Espresso.onView( + Matchers.allOf( + ViewMatchers.withContentDescription("More"), + UITestHelper.childAtPosition( + UITestHelper.childAtPosition( + ViewMatchers.withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 4 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + Espresso.onView(Matchers.allOf(ViewMatchers.withId(R.id.more_settings))).perform( + ViewActions.scrollTo(), + ViewActions.click() + ) + Intents.intended(IntentMatchers.hasComponent(SettingsActivity::class.java.name)) + UITestHelper.sleep(1000) + } + +} \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.kt index 9db5a1ee4..211483a83 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.kt @@ -1,160 +1,65 @@ package fr.free.nrw.commons +import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso 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.matcher.PreferenceMatchers -import androidx.test.espresso.matcher.ViewMatchers.* -import androidx.test.filters.LargeTest +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers.isEnabled +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 +import androidx.test.uiautomator.UiDevice import com.google.gson.Gson +import fr.free.nrw.commons.UITestHelper.Companion.childAtPosition import fr.free.nrw.commons.kvstore.JsonKvStore -import fr.free.nrw.commons.settings.Prefs import fr.free.nrw.commons.settings.SettingsActivity -import org.hamcrest.Matchers.allOf -import org.hamcrest.core.IsNot.not -import org.junit.Assert.assertEquals +import org.hamcrest.CoreMatchers.allOf import org.junit.Before -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -@LargeTest @RunWith(AndroidJUnit4::class) class SettingsActivityTest { + private lateinit var defaultKvStore: JsonKvStore @get:Rule var activityRule: ActivityTestRule<*> = ActivityTestRule(SettingsActivity::class.java) + private val device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + @Before fun setup() { + device.setOrientationNatural() + device.freezeRotation() val context = InstrumentationRegistry.getInstrumentation().targetContext val storeName = context.packageName + "_preferences" defaultKvStore = JsonKvStore(context, storeName, Gson()) } @Test - @Ignore("Fix Failing Test") - fun setRecentUploadLimitTo123() { - // Open "Use external storage" preference - Espresso.onData(PreferenceMatchers.withKey("uploads")) - .inAdapterView(withId(android.R.id.list)) - .perform(click()) - - // Try setting it to 123 - Espresso.onView(withId(android.R.id.edit)) - .perform(replaceText("123")) - - // Click "OK" - Espresso.onView(allOf(withId(android.R.id.button1), withText("OK"))) - .perform(click()) - - // Check setting set to 123 in SharedPreferences - assertEquals( - 123, - defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0).toLong() - ) - - // Check displaying 123 in summary text - Espresso.onData(PreferenceMatchers.withKey("uploads")) - .inAdapterView(withId(android.R.id.list)) - .onChildView(withId(android.R.id.summary)) - .check(matches(withText("123"))) - } - - @Test - @Ignore("Fix Failing Test") - fun setRecentUploadLimitTo0() { - // Open "Use external storage" preference - Espresso.onData(PreferenceMatchers.withKey("uploads")) - .inAdapterView(withId(android.R.id.list)) - .perform(click()) - - // Try setting it to 0 - Espresso.onView(withId(android.R.id.edit)) - .perform(replaceText("0")) - - // Click "OK" - Espresso.onView(allOf(withId(android.R.id.button1), withText("OK"))) - .perform(click()) - - // Check setting set to 100 in SharedPreferences - assertEquals( - 100, - defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0).toLong() - ) - - // Check displaying 100 in summary text - Espresso.onData(PreferenceMatchers.withKey("uploads")) - .inAdapterView(withId(android.R.id.list)) - .onChildView(withId(android.R.id.summary)) - .check(matches(withText("100"))) - } - - @Test - @Ignore("Fix Failing Test") - fun setRecentUploadLimitTo700() { - // Open "Use external storage" preference - Espresso.onData(PreferenceMatchers.withKey("uploads")) - .inAdapterView(withId(android.R.id.list)) - .perform(click()) - - // Try setting it to 700 - Espresso.onView(withId(android.R.id.edit)) - .perform(replaceText("700")) - - // Click "OK" - Espresso.onView(allOf(withId(android.R.id.button1), withText("OK"))) - .perform(click()) - - // Check setting set to 500 in SharedPreferences - assertEquals( - 500, - defaultKvStore.getInt(Prefs.UPLOADS_SHOWING, 0).toLong() - ) - - // Check displaying 100 in summary text - Espresso.onData(PreferenceMatchers.withKey("uploads")) - .inAdapterView(withId(android.R.id.list)) - .onChildView(withId(android.R.id.summary)) - .check(matches(withText("500"))) - } - - @Test - @Ignore("Fix Failing Test") fun useAuthorNameTogglesOn() { // Turn on "Use author name" preference if currently off if (!defaultKvStore.getBoolean("useAuthorName", false)) { - Espresso.onData(PreferenceMatchers.withKey("useAuthorName")) - .inAdapterView(withId(android.R.id.list)) - .perform(click()) + Espresso.onView( + allOf( + withId(R.id.recycler_view), + childAtPosition(withId(android.R.id.list_container), 0) + ) + ).perform( + RecyclerViewActions.actionOnItemAtPosition(6, click()) + ) } - // Check authorName preference is enabled - Espresso.onData(PreferenceMatchers.withKey("authorName")) - .inAdapterView(withId(android.R.id.list)) - .check(matches(isEnabled())) - } - - @Test - @Ignore("Fix Failing Test") - fun useAuthorNameTogglesOff() { - // Turn off "Use external storage" preference if currently on - if (defaultKvStore.getBoolean("useAuthorName", false)) { - Espresso.onData(PreferenceMatchers.withKey("useAuthorName")) - .inAdapterView(withId(android.R.id.list)) - .perform(click()) - } - - // Check authorName preference is enabled - Espresso.onData(PreferenceMatchers.withKey("authorName")) - .inAdapterView(withId(android.R.id.list)) - .check(matches(not(isEnabled()))) + Espresso.onView( + allOf( + withId(R.id.recycler_view), + childAtPosition(withId(android.R.id.list_container), 0) + ) + ).check(matches(isEnabled())) } @Test diff --git a/app/src/androidTest/java/fr/free/nrw/commons/SignupTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/SignupTest.kt deleted file mode 100644 index d36ec8f20..000000000 --- a/app/src/androidTest/java/fr/free/nrw/commons/SignupTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package fr.free.nrw.commons - -import androidx.test.espresso.Espresso -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.assertion.ViewAssertions -import androidx.test.espresso.intent.Intents -import androidx.test.espresso.intent.Intents.intended -import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent -import androidx.test.espresso.matcher.ViewMatchers -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 -import fr.free.nrw.commons.auth.LoginActivity -import fr.free.nrw.commons.auth.SignupActivity -import org.junit.Before -import org.junit.Ignore -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class SignupTest { - @get:Rule - var activityRule: ActivityTestRule<*> = ActivityTestRule(LoginActivity::class.java) - - @Before - fun setup() { - UITestHelper.skipWelcome() - } - - @Test - @Ignore("Fix Failing Test") - fun testSignupButton() { - try { - Intents.init() - } catch (ex: IllegalStateException) { - - } - - UITestHelper.sleep(3000) - Espresso.onView(withId(R.id.sign_up_button)) - .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) - .perform(click()) - intended(hasComponent(SignupActivity::class.java.name)) - Intents.release() - } - - @Test - @Ignore("Fix Failing Test") - fun orientationChange() { - UITestHelper.changeOrientation(activityRule) - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UITestHelper.kt b/app/src/androidTest/java/fr/free/nrw/commons/UITestHelper.kt index f5716fea4..26d6f9246 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/UITestHelper.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/UITestHelper.kt @@ -2,16 +2,15 @@ package fr.free.nrw.commons import android.app.Activity import android.content.pm.ActivityInfo -import androidx.test.espresso.Espresso.closeSoftKeyboard +import android.view.View +import android.view.ViewGroup import androidx.test.espresso.Espresso.onView import androidx.test.espresso.NoMatchingViewException import androidx.test.espresso.action.ViewActions import androidx.test.espresso.matcher.ViewMatchers import androidx.test.rule.ActivityTestRule import org.apache.commons.lang3.StringUtils -import org.hamcrest.BaseMatcher -import org.hamcrest.Description -import org.hamcrest.Matcher +import org.hamcrest.* import timber.log.Timber @@ -19,9 +18,39 @@ class UITestHelper { companion object { fun skipWelcome() { try { + onView(ViewMatchers.withId(R.id.button_ok)) + .perform(ViewActions.click()) //Skip tutorial onView(ViewMatchers.withId(R.id.finishTutorialButton)) - .perform(ViewActions.click()) + .perform(ViewActions.click()) + } catch (ignored: NoMatchingViewException) { + } + } + + fun skipLogin() { + try { + //Skip Login + val htmlTextView = onView( + Matchers.allOf( + ViewMatchers.withId(R.id.skip_login), ViewMatchers.withText("Skip"), + ViewMatchers.isDisplayed() + ) + ) + htmlTextView.perform(ViewActions.click()) + + val appCompatButton = onView( + Matchers.allOf( + ViewMatchers.withId(android.R.id.button1), ViewMatchers.withText("Yes"), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.buttonPanel), + 0 + ), + 3 + ) + ) + ) + appCompatButton.perform(ViewActions.scrollTo(), ViewActions.click()) } catch (ignored: NoMatchingViewException) { } } @@ -31,19 +60,87 @@ class UITestHelper { //Perform Login sleep(3000) onView(ViewMatchers.withId(R.id.login_username)) - .perform(ViewActions.clearText(), ViewActions.typeText(getTestUsername())) - closeSoftKeyboard() + .perform( + ViewActions.replaceText(getTestUsername()), + ViewActions.closeSoftKeyboard() + ) + sleep(2000) onView(ViewMatchers.withId(R.id.login_password)) - .perform(ViewActions.clearText(), ViewActions.typeText(getTestUserPassword())) - closeSoftKeyboard() + .perform( + ViewActions.replaceText(getTestUserPassword()), + ViewActions.closeSoftKeyboard() + ) + sleep(2000) onView(ViewMatchers.withId(R.id.login_button)) - .perform(ViewActions.click()) + .perform(ViewActions.click()) sleep(10000) } catch (ignored: NoMatchingViewException) { } } + fun logoutUser() { + try { + onView( + Matchers.allOf( + ViewMatchers.withContentDescription("More"), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 4 + ), + ViewMatchers.isDisplayed() + ) + ).perform(ViewActions.click()) + onView( + Matchers.allOf( + ViewMatchers.withId(R.id.more_logout), ViewMatchers.withText("Logout"), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.scroll_view_more_bottom_sheet), + 0 + ), + 6 + ) + ) + ).perform(ViewActions.scrollTo(), ViewActions.click()) + onView( + Matchers.allOf( + ViewMatchers.withId(android.R.id.button1), ViewMatchers.withText("Yes"), + childAtPosition( + childAtPosition( + ViewMatchers.withId(R.id.buttonPanel), + 0 + ), + 3 + ) + ) + ).perform(ViewActions.scrollTo(), ViewActions.click()) + sleep(5000) + } catch (ignored: NoMatchingViewException) { + } + } + + fun childAtPosition( + parentMatcher: Matcher, position: Int + ): Matcher { + + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Child at position $position in parent ") + parentMatcher.describeTo(description) + } + + public override fun matchesSafely(view: View): Boolean { + val parent = view.parent + return parent is ViewGroup && parentMatcher.matches(parent) + && view == parent.getChildAt(position) + } + } + } + fun sleep(timeInMillis: Long) { try { Timber.d("Sleeping for %d", timeInMillis) @@ -66,7 +163,8 @@ class UITestHelper { throw NotImplementedError("Configure your beta account's password") } else return password } - fun changeOrientation(activityRule: ActivityTestRule){ + + fun changeOrientation(activityRule: ActivityTestRule) { activityRule.activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT assert(activityRule.activity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) activityRule.activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UploadActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/UploadActivityTest.kt index d33f958c1..d3a814f2d 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/UploadActivityTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/UploadActivityTest.kt @@ -1,18 +1,8 @@ package fr.free.nrw.commons -import android.net.Uri -import androidx.test.espresso.Espresso -import androidx.test.espresso.action.ViewActions -import androidx.test.espresso.intent.Intents -import androidx.test.espresso.intent.matcher.IntentMatchers -import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.rule.ActivityTestRule -import androidx.test.runner.AndroidJUnit4 import fr.free.nrw.commons.upload.UploadActivity -import fr.free.nrw.commons.upload.depicts.DepictsFragment -import org.hamcrest.Matchers -import org.hamcrest.core.AllOf -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -26,23 +16,4 @@ class UploadActivityTest { fun orientationChange() { UITestHelper.changeOrientation(activityRule) } - - @Test - @Ignore("Fix Failing Test") - fun TestForCaptionsAndDepictions() { - val imageUri = Uri.parse("file://mnt/sdcard/image.jpg") - - Espresso.onView(ViewMatchers.withId(R.id.caption_item_edit_text)) - .perform(ViewActions.typeText("caption in english")) - Espresso.onView(ViewMatchers.withId(R.id.description_item_edit_text)) - .perform(ViewActions.typeText("description in english")) - Espresso.onData(AllOf.allOf(Matchers.anything("spinner text"))).atPosition(1).perform(ViewActions.click()); - Espresso.onView(ViewMatchers.withId(R.id.caption_item_edit_text)) - .perform(ViewActions.typeText("caption in some other language")) - Espresso.onView(ViewMatchers.withId(R.id.description_item_edit_text)) - .perform(ViewActions.typeText("description in some other language")) - Espresso.onView(ViewMatchers.withId(R.id.btn_next)) - .perform(ViewActions.click()) - Intents.intended(IntentMatchers.hasComponent(DepictsFragment::class.java.name)) - } } diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UploadCancelledTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/UploadCancelledTest.kt new file mode 100644 index 000000000..4041b92e5 --- /dev/null +++ b/app/src/androidTest/java/fr/free/nrw/commons/UploadCancelledTest.kt @@ -0,0 +1,194 @@ +package fr.free.nrw.commons + +import android.app.Activity +import android.app.Instrumentation +import androidx.recyclerview.widget.RecyclerView +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.* +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.ActivityTestRule +import androidx.test.rule.GrantPermissionRule +import androidx.test.uiautomator.UiDevice +import fr.free.nrw.commons.LocationPicker.LocationPickerActivity +import fr.free.nrw.commons.UITestHelper.Companion.childAtPosition +import fr.free.nrw.commons.auth.LoginActivity +import org.hamcrest.CoreMatchers +import org.hamcrest.Matchers.allOf +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class UploadCancelledTest { + + @Rule + @JvmField + var mActivityTestRule = ActivityTestRule(LoginActivity::class.java) + + @Rule + @JvmField + var mGrantPermissionRule: GrantPermissionRule = + GrantPermissionRule.grant( + "android.permission.WRITE_EXTERNAL_STORAGE" + ) + + private val device: UiDevice = + UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Before + fun setup() { + try { + Intents.init() + } catch (ex: IllegalStateException) { + + } + device.unfreezeRotation() + device.setOrientationNatural() + device.freezeRotation() + UITestHelper.loginUser() + UITestHelper.skipWelcome() + Intents.intending(CoreMatchers.not(IntentMatchers.isInternal())) + .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, null)) + } + + @After + fun teardown() { + try { + Intents.release() + } catch (ex: IllegalStateException) { + + } + } + + @Test + fun uploadCancelledAfterLocationPickedTest() { + + val bottomNavigationItemView = onView( + allOf( + childAtPosition( + childAtPosition( + withId(R.id.fragment_main_nav_tab_layout), + 0 + ), + 1 + ), + isDisplayed() + ) + ) + bottomNavigationItemView.perform(click()) + + UITestHelper.sleep(12000) + + val actionMenuItemView = onView( + allOf( + withId(R.id.list_sheet), + childAtPosition( + childAtPosition( + withId(R.id.toolbar), + 1 + ), + 0 + ), + isDisplayed() + ) + ) + actionMenuItemView.perform(click()) + + val recyclerView = onView( + allOf( + withId(R.id.rv_nearby_list), + ) + ) + recyclerView.perform( + RecyclerViewActions.actionOnItemAtPosition( + 0, + click() + ) + ) + + val linearLayout3 = onView( + allOf( + withId(R.id.cameraButton), + childAtPosition( + allOf( + withId(R.id.nearby_button_layout), + ), + 0 + ), + isDisplayed() + ) + ) + linearLayout3.perform(click()) + + val pasteSensitiveTextInputEditText = onView( + allOf( + withId(R.id.caption_item_edit_text), + childAtPosition( + childAtPosition( + withId(R.id.caption_item_edit_text_input_layout), + 0 + ), + 0 + ), + isDisplayed() + ) + ) + pasteSensitiveTextInputEditText.perform(replaceText("test"), closeSoftKeyboard()) + + val pasteSensitiveTextInputEditText2 = onView( + allOf( + withId(R.id.description_item_edit_text), + childAtPosition( + childAtPosition( + withId(R.id.description_item_edit_text_input_layout), + 0 + ), + 0 + ), + isDisplayed() + ) + ) + pasteSensitiveTextInputEditText2.perform(replaceText("test"), closeSoftKeyboard()) + + val appCompatButton2 = onView( + allOf( + withId(R.id.btn_next), + childAtPosition( + childAtPosition( + withId(R.id.ll_container_media_detail), + 2 + ), + 1 + ), + isDisplayed() + ) + ) + appCompatButton2.perform(click()) + + val appCompatButton3 = onView( + allOf( + withId(android.R.id.button1), + ) + ) + appCompatButton3.perform(scrollTo(), click()) + + Intents.intended(IntentMatchers.hasComponent(LocationPickerActivity::class.java.name)) + + val floatingActionButton3 = onView( + allOf( + withId(R.id.location_chosen_button), + isDisplayed() + ) + ) + UITestHelper.sleep(2000) + floatingActionButton3.perform(click()) + } +} diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt index 931259801..c5e0bd14a 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt @@ -8,7 +8,6 @@ import android.graphics.Bitmap import android.net.Uri import android.os.Environment import android.view.View -import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso.onView import androidx.test.espresso.NoMatchingViewException import androidx.test.espresso.action.ViewActions.click @@ -21,10 +20,10 @@ import androidx.test.espresso.intent.Intents.intending import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction import androidx.test.espresso.intent.matcher.IntentMatchers.hasType import androidx.test.espresso.matcher.ViewMatchers.* +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.rule.ActivityTestRule import androidx.test.rule.GrantPermissionRule -import androidx.test.runner.AndroidJUnit4 import fr.free.nrw.commons.auth.LoginActivity import fr.free.nrw.commons.upload.UploadMediaDetailAdapter import fr.free.nrw.commons.util.MyViewAction @@ -64,8 +63,8 @@ class UploadTest { } catch (ex: IllegalStateException) { } - UITestHelper.skipWelcome() UITestHelper.loginUser() + UITestHelper.skipWelcome() } @After diff --git a/app/src/androidTest/java/fr/free/nrw/commons/WelcomeActivityTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/WelcomeActivityTest.kt index 764b892d2..777a1859a 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/WelcomeActivityTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/WelcomeActivityTest.kt @@ -3,105 +3,127 @@ package fr.free.nrw.commons import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule +import androidx.test.uiautomator.UiDevice import androidx.viewpager.widget.ViewPager import fr.free.nrw.commons.utils.ConfigUtils import org.hamcrest.core.IsNot.not -import org.junit.Ignore +import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @LargeTest -@RunWith(AndroidJUnit4ClassRunner::class) +@RunWith(AndroidJUnit4::class) class WelcomeActivityTest { + @get:Rule var activityRule: ActivityTestRule<*> = ActivityTestRule(WelcomeActivity::class.java) + private val device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + @Before + fun setup() { + device.setOrientationNatural() + device.freezeRotation() + } + @Test - @Ignore("Fix Failing Test") fun ifBetaShowsSkipButton() { if (ConfigUtils.isBetaFlavour) { + onView(withId(R.id.button_ok)) + .perform(ViewActions.click()) onView(withId(R.id.finishTutorialButton)) - .check(matches(isDisplayed())) + .check(matches(isDisplayed())) } } @Test fun ifProdHidesSkipButton() { if (!ConfigUtils.isBetaFlavour) { + onView(withId(R.id.button_ok)) + .perform(ViewActions.click()) onView(withId(R.id.finishTutorialButton)) - .check(matches(not(isDisplayed()))) + .check(matches(not(isDisplayed()))) } } @Test - @Ignore("Fix Failing Test") fun testBetaSkipButton() { if (ConfigUtils.isBetaFlavour) { + onView(withId(R.id.button_ok)) + .perform(ViewActions.click()) onView(withId(R.id.finishTutorialButton)) - .perform(ViewActions.click()) + .perform(ViewActions.click()) assert(activityRule.activity.isDestroyed) } } @Test - @Ignore("Fix Failing Test") fun testSwipingOnce() { + onView(withId(R.id.button_ok)) + .perform(ViewActions.click()) onView(withId(R.id.welcomePager)) - .perform(ViewActions.swipeLeft()) + .perform(ViewActions.swipeLeft()) assert(true) onView(withId(R.id.welcomePager)) - .perform(ViewActions.swipeRight()) + .perform(ViewActions.swipeRight()) assert(true) } @Test - @Ignore("Fix Failing Test") fun testSwipingWholeTutorial() { + onView(withId(R.id.button_ok)) + .perform(ViewActions.click()) onView(withId(R.id.welcomePager)) - .perform(ViewActions.swipeLeft()) - .perform(ViewActions.swipeLeft()) - .perform(ViewActions.swipeLeft()) - .perform(ViewActions.swipeLeft()) + .perform(ViewActions.swipeLeft()) + .perform(ViewActions.swipeLeft()) + .perform(ViewActions.swipeLeft()) + .perform(ViewActions.swipeLeft()) assert(true) onView(withId(R.id.welcomePager)) - .perform(ViewActions.swipeRight()) - .perform(ViewActions.swipeRight()) - .perform(ViewActions.swipeRight()) - .perform(ViewActions.swipeRight()) + .perform(ViewActions.swipeRight()) + .perform(ViewActions.swipeRight()) + .perform(ViewActions.swipeRight()) + .perform(ViewActions.swipeRight()) assert(true) } @Test - fun swipeBeyondBounds(){ - var view_pager=activityRule.activity.findViewById(R.id.welcomePager) + fun swipeBeyondBounds() { + val viewPager = activityRule.activity.findViewById(R.id.welcomePager) - view_pager.adapter?.let { view_pager.currentItem == view_pager.adapter?.count?.minus(1) - if (view_pager.currentItem==3){ - onView(withId(R.id.welcomePager)) - .perform(ViewActions.swipeLeft()) - assert(true) - onView(withId(R.id.welcomePager)) - .perform(ViewActions.swipeRight()) - assert(false) - }} + viewPager.adapter?.let { + if (viewPager.currentItem == 3) { + onView(withId(R.id.welcomePager)) + .perform(ViewActions.swipeLeft()) + assert(true) + onView(withId(R.id.welcomePager)) + .perform(ViewActions.swipeRight()) + assert(false) + } + } } @Test - fun swipeTillLastAndFinish(){ - var view_pager=activityRule.activity.findViewById(R.id.welcomePager) + fun swipeTillLastAndFinish() { + val viewPager = activityRule.activity.findViewById(R.id.welcomePager) - view_pager.adapter?.let { view_pager.currentItem == view_pager.adapter?.count?.minus(1) - if (view_pager.currentItem==3){ - onView(withId(R.id.finishTutorialButton)) - .perform(ViewActions.click()) - assert(activityRule.activity.isDestroyed) - }} + viewPager.adapter?.let { + if (viewPager.currentItem == 3) { + onView(withId(R.id.button_ok)) + .perform(ViewActions.click()) + onView(withId(R.id.finishTutorialButton)) + .perform(ViewActions.click()) + assert(activityRule.activity.isDestroyed) + } + } } @Test diff --git a/app/src/androidTest/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditTextTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditTextTest.kt index ebfa8b0c7..37ea557d1 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditTextTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/ui/PasteSensitiveTextInputEditTextTest.kt @@ -1,19 +1,13 @@ package fr.free.nrw.commons.ui -import android.R import android.content.Context -import android.os.Build import android.util.AttributeSet import androidx.test.core.app.ApplicationProvider -import androidx.test.runner.AndroidJUnit4 -import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText +import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Assert import org.junit.Before -import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith -import java.lang.Exception -import kotlin.Throws @RunWith(AndroidJUnit4::class) class PasteSensitiveTextInputEditTextTest { @@ -27,41 +21,6 @@ class PasteSensitiveTextInputEditTextTest { textView = PasteSensitiveTextInputEditText(context) } - @Test - @Ignore("Fix Failing Test") - fun onTextContextMenuItemPasteFormattingDisabled() { - textView!!.setFormattingAllowed(false); - textView!!.setText("Text") - textView!!.onTextContextMenuItem(R.id.paste) - Assert.assertEquals("Text", textView!!.text.toString()) - } - - @Test - @Ignore("Fix Failing Test") - fun onTextContextMenuItemPasteFormattingAllowed() { - textView!!.setFormattingAllowed(true); - textView!!.setText("Text") - textView!!.onTextContextMenuItem(R.id.paste) - Assert.assertEquals("Text", textView!!.text.toString()) - } - - @Test - @Ignore("Fix Failing Test") - fun onTextContextMenuItemPaste() { - textView!!.setText("Text") - textView!!.onTextContextMenuItem(R.id.paste) - Assert.assertEquals("Text", textView!!.text.toString()) - } - - - @Test - @Ignore("Fix Failing Test") - fun onTextContextMenuItemNotPaste() { - textView!!.setText("Text") - textView!!.onTextContextMenuItem(R.id.copy) - Assert.assertEquals("Text", textView!!.text.toString()) - } - // this test has no real value, just % for test code coverage @Test fun extractFormattingAttributeSet(){ diff --git a/app/src/main/res/layout/fragment_more_bottom_sheet.xml b/app/src/main/res/layout/fragment_more_bottom_sheet.xml index 4042e2ead..58f796c87 100644 --- a/app/src/main/res/layout/fragment_more_bottom_sheet.xml +++ b/app/src/main/res/layout/fragment_more_bottom_sheet.xml @@ -6,11 +6,13 @@ android:orientation="vertical"> diff --git a/jacoco.gradle b/jacoco.gradle index 892c83f33..74adf0578 100644 --- a/jacoco.gradle +++ b/jacoco.gradle @@ -18,81 +18,85 @@ project.afterEvaluate { .all { variant -> def variantName = variant.name def unitTestTask = "test${variantName.capitalize()}UnitTest" - def androidTestCoverageTask = "create${variantName.capitalize()}CoverageReport" + def androidTestCoverageTask = "create${variantName.capitalize()}CoverageReport" - tasks.create(name: "${unitTestTask}Coverage", type: JacocoReport, dependsOn: [ + def excludes = [ + // data binding + 'android/databinding/**/*.class', + '**/android/databinding/*Binding.class', + '**/android/databinding/*', + '**/androidx/databinding/*', + '**/BR.*', + // android + '**/R.class', + '**/R$*.class', + '**/BuildConfig.*', + '**/Manifest*.*', + '**/*Test*.*', + 'android/**/*.*', + // butterKnife + '**/*$ViewInjector*.*', + '**/*$ViewBinder*.*', + '**/*ViewBinding*.*', + // dagger + '**/*_MembersInjector.class', + '**/Dagger*Component.class', + '**/Dagger*Component$Builder.class', + '**/*Module_*Factory.class', + '**/di/*', + '**/*_Factory*.*', + '**/*Module*.*', + '**/*Dagger*.*', + '**/*Hilt*.*', + // kotlin + '**/*MapperImpl*.*', + '**/*$ViewInjector*.*', + '**/*$ViewBinder*.*', + '**/BuildConfig.*', + '**/*Component*.*', + '**/*BR*.*', + '**/Manifest*.*', + '**/*$Lambda$*.*', + '**/*Companion*.*', + '**/*Module*.*', + '**/*Dagger*.*', + '**/*Hilt*.*', + '**/*MembersInjector*.*', + '**/*_MembersInjector.class', + '**/*_Factory*.*', + '**/*_Provide*Factory*.*', + '**/*Extensions*.*', + // sealed and data classes + '**/*$Result.*', + '**/*$Result$*.*', + // model + '**/**/model/*', + '**/**/models/*', + '**/model/*', + // concurrency + '**/concurrency/*', + // kvstore + '**/kvstore/*', + // db + '**/db/*', + // data + '**/data/*', + // zoom controllers are part of external library + '**/**/zoomControllers/*', + ] + + tasks.create(name: "${unitTestTask}UnifiedCoverage", type: JacocoReport, dependsOn: [ "$unitTestTask", "$androidTestCoverageTask", ]) { group = "Reporting" - description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build" + description = "Generate Jacoco unified coverage reports for the ${variantName.capitalize()} build" reports { html.enabled = true xml.enabled = true } - def excludes = [ - // data binding - 'android/databinding/**/*.class', - '**/android/databinding/*Binding.class', - '**/android/databinding/*', - '**/androidx/databinding/*', - '**/BR.*', - // android - '**/R.class', - '**/R$*.class', - '**/BuildConfig.*', - '**/Manifest*.*', - '**/*Test*.*', - 'android/**/*.*', - // butterKnife - '**/*$ViewInjector*.*', - '**/*$ViewBinder*.*', - '**/*ViewBinding*.*', - // dagger - '**/*_MembersInjector.class', - '**/Dagger*Component.class', - '**/Dagger*Component$Builder.class', - '**/*Module_*Factory.class', - '**/di/*', - '**/*_Factory*.*', - '**/*Module*.*', - '**/*Dagger*.*', - '**/*Hilt*.*', - // kotlin - '**/*MapperImpl*.*', - '**/*$ViewInjector*.*', - '**/*$ViewBinder*.*', - '**/BuildConfig.*', - '**/*Component*.*', - '**/*BR*.*', - '**/Manifest*.*', - '**/*$Lambda$*.*', - '**/*Companion*.*', - '**/*Module*.*', - '**/*Dagger*.*', - '**/*Hilt*.*', - '**/*MembersInjector*.*', - '**/*_MembersInjector.class', - '**/*_Factory*.*', - '**/*_Provide*Factory*.*', - '**/*Extensions*.*', - // sealed and data classes - '**/*$Result.*', - '**/*$Result$*.*', - // model - '**/**/model/*', - // concurrency - '**/concurrency/*', - // kvstore - '**/kvstore/*', - // db - '**/db/*', - // data - '**/data/*', - ] - def javaClasses = fileTree(dir: variant.javaCompileProvider.get().destinationDir, excludes: excludes) def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", @@ -116,7 +120,34 @@ project.afterEvaluate { ])) } + tasks.create(name: "${unitTestTask}Coverage", type: JacocoReport, dependsOn: [ + "$unitTestTask" + ]) { + group = "Reporting" + description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build" + + reports { + html.enabled = true + xml.enabled = true + } + + def javaClasses = fileTree(dir: variant.javaCompileProvider.get().destinationDir, + excludes: excludes) + def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", + excludes: excludes) + + classDirectories.setFrom(files([ + javaClasses, + kotlinClasses + ])) + + def variantSourceSets = variant.sourceSets.java.srcDirs.collect { it.path }.flatten() + sourceDirectories.setFrom(project.files(variantSourceSets)) + + executionData(files([ + "$project.buildDir/jacoco/${unitTestTask}.exec" + ])) + } + } - - }