Compare commits
	
		
			1 Commits
		
	
	
		
			release
			...
			7af7df3e2f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7af7df3e2f | 
							
								
								
									
										62
									
								
								.gitea/workflows/common_coverage.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								.gitea/workflows/common_coverage.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| name: Coverage | ||||
| on: | ||||
|   workflow_call: | ||||
|  | ||||
| jobs: | ||||
|   BuildAndTestAndCoverage: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Check out repository code | ||||
|         uses: actions/checkout@v4 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|       - name: Fetch tags | ||||
|         run: git fetch --tags -p | ||||
|       - name: Check KVM | ||||
|         run: | | ||||
|           sudo apt update | ||||
|           sudo apt install -y kmod kvm qemu qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils | ||||
|           echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules | ||||
|           sudo udevadm control --reload-rules | ||||
|           sudo udevadm trigger --name-match=kvm | ||||
|  | ||||
|       - uses: actions/setup-java@v4 | ||||
|         with: | ||||
|           distribution: 'temurin' | ||||
|           java-version: '17' | ||||
|           cache: gradle | ||||
|       - uses: gradle/actions/setup-gradle@v3 | ||||
|       #- uses: android-actions/setup-android@v3 | ||||
|       - name: Configure gradle... | ||||
|         run: mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true" >> ~/.gradle/gradle.properties | ||||
|       - uses: KengoTODA/actions-setup-docker-compose@v1 | ||||
|         with: | ||||
|           version: "2.23.3" | ||||
|       - name: run selfoss | ||||
|         run: | | ||||
|           docker compose -f .gitea/workflows/assets/docker-compose.yml up -d | ||||
|       - name: Tests | ||||
|         uses: reactivecircus/android-emulator-runner@v2 | ||||
|         with: | ||||
|           api-level: 29 | ||||
|           arch: x86_64 | ||||
|           script: ./gradlew androidApp:connectedAndroidTest | ||||
|       - uses: actions/upload-artifact@v3 | ||||
|         if: failure() | ||||
|         with: | ||||
|           name: failure-espresso | ||||
|           path: build/reports/androidTests/connected/screenshots | ||||
|           retention-days: 2 | ||||
|           overwrite: true | ||||
|           include-hidden-files: true | ||||
|       - uses: actions/upload-artifact@v3 | ||||
|         with: | ||||
|           name: coverage-espresso | ||||
|           path: build/reports/coverage/androidTest/githubConfig/debug/connected | ||||
|           retention-days: 1 | ||||
|           overwrite: true | ||||
|           include-hidden-files: true | ||||
|       - name: Clean | ||||
|         if: always() | ||||
|         run: | | ||||
|           docker compose -f .gitea/workflows/assets/docker-compose.yml stop | ||||
| @@ -3,89 +3,91 @@ on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - master | ||||
|       - chore-crowdin-ci | ||||
|  | ||||
| jobs: | ||||
|   Lint: | ||||
|   EspressoReports: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Check out repository code | ||||
|         uses: actions/checkout@v4 | ||||
|       - uses: actions/setup-java@v4 | ||||
|         with: | ||||
|           distribution: 'temurin' | ||||
|           java-version: '17' | ||||
|           cache: gradle | ||||
|       - name: Install klint | ||||
|         run: curl -sSLO https://github.com/pinterest/ktlint/releases/download/1.5.0/ktlint && chmod a+x ktlint && mv ktlint /usr/local/bin/ | ||||
|       - name: Install detekt | ||||
|         run: curl -sSLO https://github.com/detekt/detekt/releases/download/v1.23.7/detekt-cli-1.23.7.zip && unzip detekt-cli-1.23.7.zip | ||||
|       - name: Linting... | ||||
|         run: ktlint 'shared/**/*.kt' 'androidApp/**/*.kt' '!shared/build' | ||||
|       - name: Detecting... | ||||
|         run: ./detekt-cli-1.23.7/bin/detekt-cli -c detekt.yml --excludes '**/shared/build/**/*.kt' | ||||
|   translations: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Check out repository code | ||||
|         uses: actions/checkout@v4 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|       - name: "Check translations changes" | ||||
|         id: check-translations-changes | ||||
|         uses: tj-actions/changed-files@v45 | ||||
|         with: | ||||
|           files: | | ||||
|             androidApp/src/main/res/values/strings.xml | ||||
|       - name: upload translation sources | ||||
|         if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
|         uses: crowdin/github-action@v2 | ||||
|         with: | ||||
|           config: './.gitea/workflows/assets/crowdin.yml' | ||||
|           upload_sources: true | ||||
|           upload_translations: false | ||||
|           download_translations: false | ||||
|           create_pull_request: false | ||||
|           push_translations: false | ||||
|         env: | ||||
|           CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} | ||||
|           CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} | ||||
|       - name: wait | ||||
|         if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
|         run: sleep 10s | ||||
|       - name: download translations | ||||
|         if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
|         uses: crowdin/github-action@v2 | ||||
|         with: | ||||
|           config: './.gitea/workflows/assets/crowdin.yml' | ||||
|           upload_sources: false | ||||
|           upload_translations: false | ||||
|           download_translations: true | ||||
|           create_pull_request: false | ||||
|           push_translations: false | ||||
|         env: | ||||
|           CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} | ||||
|           CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} | ||||
|       - name: Check for uncommitted changes | ||||
|         if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
|         id: check-changes | ||||
|         uses: mskri/check-uncommitted-changes-action@v1.0.1 | ||||
|       - name: Commit Changes | ||||
|         if: steps.check-api-changes.outputs.any_modified == 'true' && steps.check-changes.outputs.changes != '' | ||||
|         run: | | ||||
|           git config --global user.email aminecmi+giteadrone@pm.me | ||||
|           git config --global user.name giteadrone | ||||
|           git add ./androidApp/src/main/res/* | ||||
|           git commit -m "translation: translation files" | ||||
|       - name: Push changes | ||||
|         if: steps.check-api-changes.outputs.any_modified == 'true' && steps.check-changes.outputs.changes != '' | ||||
|         uses: appleboy/git-push-action@v1.0.0 | ||||
|         with: | ||||
|           author_name: giteadrone | ||||
|           author_email: aminecmi+giteadrone@pm.me | ||||
|           remote: ${{ secrets.REMOTE_URL }} | ||||
|           ssh_key: ${{ secrets.PRIVATE_KEY }} | ||||
|           branch: ${{ github.head_ref || github.ref_name }} | ||||
|   build: | ||||
|     needs: Lint | ||||
|     uses: ./.gitea/workflows/common_build.yml | ||||
|     uses: ./.gitea/workflows/common_coverage.yml | ||||
| #  Lint: | ||||
| #    runs-on: ubuntu-latest | ||||
| #    steps: | ||||
| #      - name: Check out repository code | ||||
| #        uses: actions/checkout@v4 | ||||
| #      - uses: actions/setup-java@v4 | ||||
| #        with: | ||||
| #          distribution: 'temurin' | ||||
| #          java-version: '17' | ||||
| #          cache: gradle | ||||
| #      - name: Install klint | ||||
| #        run: curl -sSLO https://github.com/pinterest/ktlint/releases/download/1.5.0/ktlint && chmod a+x ktlint && mv ktlint /usr/local/bin/ | ||||
| #      - name: Install detekt | ||||
| #        run: curl -sSLO https://github.com/detekt/detekt/releases/download/v1.23.7/detekt-cli-1.23.7.zip && unzip detekt-cli-1.23.7.zip | ||||
| #      - name: Linting... | ||||
| #        run: ktlint 'shared/**/*.kt' 'androidApp/**/*.kt' '!shared/build' | ||||
| #      - name: Detecting... | ||||
| #        run: ./detekt-cli-1.23.7/bin/detekt-cli -c detekt.yml --excludes '**/shared/build/**/*.kt' | ||||
| #  translations: | ||||
| #    runs-on: ubuntu-latest | ||||
| #    steps: | ||||
| #      - name: Check out repository code | ||||
| #        uses: actions/checkout@v4 | ||||
| #        with: | ||||
| #          fetch-depth: 0 | ||||
| #      - name: "Check translations changes" | ||||
| #        id: check-translations-changes | ||||
| #        uses: tj-actions/changed-files@v45 | ||||
| #        with: | ||||
| #          files: | | ||||
| #            androidApp/src/main/res/values/strings.xml | ||||
| #      - name: upload translation sources | ||||
| #        if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
| #        uses: crowdin/github-action@v2 | ||||
| #        with: | ||||
| #          config: './.gitea/workflows/assets/crowdin.yml' | ||||
| #          upload_sources: true | ||||
| #          upload_translations: false | ||||
| #          download_translations: false | ||||
| #          create_pull_request: false | ||||
| #          push_translations: false | ||||
| #        env: | ||||
| #          CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} | ||||
| #          CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} | ||||
| #      - name: wait | ||||
| #        if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
| #        run: sleep 10s | ||||
| #      - name: download translations | ||||
| #        if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
| #        uses: crowdin/github-action@v2 | ||||
| #        with: | ||||
| #          config: './.gitea/workflows/assets/crowdin.yml' | ||||
| #          upload_sources: false | ||||
| #          upload_translations: false | ||||
| #          download_translations: true | ||||
| #          create_pull_request: false | ||||
| #          push_translations: false | ||||
| #        env: | ||||
| #          CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} | ||||
| #          CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} | ||||
| #      - name: Check for uncommitted changes | ||||
| #        if: steps.check-api-changes.outputs.any_modified == 'true' | ||||
| #        id: check-changes | ||||
| #        uses: mskri/check-uncommitted-changes-action@v1.0.1 | ||||
| #      - name: Commit Changes | ||||
| #        if: steps.check-api-changes.outputs.any_modified == 'true' && steps.check-changes.outputs.changes != '' | ||||
| #        run: | | ||||
| #          git config --global user.email aminecmi+giteadrone@pm.me | ||||
| #          git config --global user.name giteadrone | ||||
| #          git add ./androidApp/src/main/res/* | ||||
| #          git commit -m "translation: translation files" | ||||
| #      - name: Push changes | ||||
| #        if: steps.check-api-changes.outputs.any_modified == 'true' && steps.check-changes.outputs.changes != '' | ||||
| #        uses: appleboy/git-push-action@v1.0.0 | ||||
| #        with: | ||||
| #          author_name: giteadrone | ||||
| #          author_email: aminecmi+giteadrone@pm.me | ||||
| #          remote: ${{ secrets.REMOTE_URL }} | ||||
| #          ssh_key: ${{ secrets.PRIVATE_KEY }} | ||||
| #          branch: ${{ github.head_ref || github.ref_name }} | ||||
| #  build: | ||||
| #    needs: Lint | ||||
| #    uses: ./.gitea/workflows/common_build.yml | ||||
|   | ||||
| @@ -96,6 +96,7 @@ android { | ||||
|         // tests | ||||
|         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||||
|         testInstrumentationRunnerArguments["clearPackageData"] = "true" | ||||
|         testInstrumentationRunnerArguments["useTestStorageService"] = "true" | ||||
|     } | ||||
|     packaging { | ||||
|         resources { | ||||
| @@ -109,6 +110,11 @@ android { | ||||
|             proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") | ||||
|         } | ||||
|         getByName("debug") { | ||||
|             isTestCoverageEnabled = true | ||||
|             enableAndroidTestCoverage = true | ||||
|             installation { | ||||
|                 installOptions("-g", "-r") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     flavorDimensions.add("build") | ||||
| @@ -197,14 +203,16 @@ dependencies { | ||||
|     testImplementation("io.mockk:mockk:1.13.14") | ||||
|     testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1") | ||||
|     implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1") | ||||
|     androidTestImplementation("androidx.test:runner:1.6.2") | ||||
|     androidTestImplementation("androidx.test:rules:1.6.1") | ||||
|     androidTestImplementation("androidx.test:runner:1.7.0-alpha01") | ||||
|     androidTestImplementation("androidx.test:rules:1.7.0-alpha01") | ||||
|     androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") | ||||
|     implementation("androidx.test.espresso:espresso-idling-resource:3.6.1") | ||||
|     androidTestImplementation("androidx.test.ext:junit-ktx:1.2.1") | ||||
|     androidTestUtil("androidx.test:orchestrator:1.5.1") | ||||
|     androidTestUtil("androidx.test:orchestrator:1.6.0-alpha02") | ||||
|     androidTestUtil("androidx.test.services:test-services:1.6.0-alpha02") | ||||
|     testImplementation("org.robolectric:robolectric:4.14.1") | ||||
|     testImplementation("androidx.test:core-ktx:1.6.1") | ||||
|     testImplementation("androidx.test:core-ktx:1.7.0-alpha01") | ||||
|     androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0") | ||||
|  | ||||
|     implementation("ch.acra:acra-http:$acraVersion") | ||||
|     implementation("ch.acra:acra-toast:$acraVersion") | ||||
| @@ -235,3 +243,40 @@ aboutLibraries { | ||||
|     duplicationMode = com.mikepenz.aboutlibraries.plugin.DuplicateMode.MERGE | ||||
|     duplicationRule = com.mikepenz.aboutlibraries.plugin.DuplicateRule.GROUP | ||||
| } | ||||
|  | ||||
| // Screenshot failure handling | ||||
| val reportsDirectory = file("$buildDir/reports/androidTests/connected") | ||||
|  | ||||
| val clearScreenshotsTask = | ||||
|     tasks.register<Exec>("clearScreenshots") { | ||||
|         println("AMINE : clear") | ||||
|         commandLine = listOf("adb", "shell", "rm", "-r", "/sdcard/Pictures/selfoss_tests") | ||||
|     } | ||||
|  | ||||
| val createScreenshotDirectoryTask = | ||||
|     tasks.register<Exec>("createScreenshotDirectory") { | ||||
|         println("AMINE : create directory") | ||||
|         group = "reporting" | ||||
|         commandLine = listOf("adb", "shell", "mkdir", "-p", "/sdcard/Pictures/selfoss_tests") | ||||
|     } | ||||
|  | ||||
| val fetchScreenshotsTask = | ||||
|     tasks.register<Exec>("fetchScreenshots") { | ||||
|         println("AMINE : fetch") | ||||
|         group = "reporting" | ||||
|         executable(android.adbExecutable.toString()) | ||||
|         commandLine = listOf("adb", "pull", "/sdcard/Pictures/selfoss_tests/.", reportsDirectory.toString()) | ||||
|  | ||||
|         finalizedBy(clearScreenshotsTask) | ||||
|         dependsOn(createScreenshotDirectoryTask) | ||||
|  | ||||
|         doFirst { | ||||
|             reportsDirectory.mkdirs() | ||||
|         } | ||||
|     } | ||||
|  | ||||
| tasks.whenTaskAdded { | ||||
|     if (this.name == "connectedGithubConfigDebugAndroidTest") { | ||||
|         this.finalizedBy(fetchScreenshotsTask) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| package bou.amine.apps.readerforselfossv2.android | ||||
|  | ||||
| import android.content.Context | ||||
| import android.os.Environment.DIRECTORY_PICTURES | ||||
| import android.os.Environment.getExternalStoragePublicDirectory | ||||
| import android.util.Log | ||||
| import androidx.annotation.ArrayRes | ||||
| import androidx.test.espresso.Espresso | ||||
| import androidx.test.espresso.Espresso.onData | ||||
| import androidx.test.espresso.Espresso.onView | ||||
| import androidx.test.espresso.action.ViewActions.click | ||||
| @@ -9,13 +13,25 @@ import androidx.test.espresso.action.ViewActions.replaceText | ||||
| import androidx.test.espresso.action.ViewActions.typeTextIntoFocusedView | ||||
| import androidx.test.espresso.assertion.ViewAssertions.doesNotExist | ||||
| import androidx.test.espresso.assertion.ViewAssertions.matches | ||||
| import androidx.test.espresso.base.DefaultFailureHandler | ||||
| import androidx.test.espresso.matcher.ViewMatchers.isChecked | ||||
| import androidx.test.espresso.matcher.ViewMatchers.isDisplayed | ||||
| import androidx.test.espresso.matcher.ViewMatchers.isNotChecked | ||||
| import androidx.test.espresso.matcher.ViewMatchers.withId | ||||
| import androidx.test.espresso.matcher.ViewMatchers.withText | ||||
| import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation | ||||
| import androidx.test.runner.screenshot.BasicScreenCaptureProcessor | ||||
| import androidx.test.runner.screenshot.Screenshot | ||||
| import androidx.test.uiautomator.UiDevice | ||||
| import androidx.test.uiautomator.UiSelector | ||||
| import org.hamcrest.CoreMatchers.allOf | ||||
| import org.hamcrest.Matchers.hasToString | ||||
| import org.junit.BeforeClass | ||||
| import org.junit.rules.TestWatcher | ||||
| import org.junit.runner.Description | ||||
| import java.io.File | ||||
| import java.io.IOException | ||||
| import java.util.Locale | ||||
|  | ||||
| fun performLogin(someUrl: String? = null) { | ||||
|     onView(withId(R.id.urlView)).perform(click()).perform( | ||||
| @@ -119,3 +135,86 @@ fun testAddSourceWithUrl( | ||||
|         .perform(click()) | ||||
|     onView(withText(sourceName)).check(matches(isDisplayed())) | ||||
| } | ||||
|  | ||||
| open class WithANRException { | ||||
|     companion object { | ||||
|         // Running count of the number of Android Not Responding dialogues to prevent endless dismissal. | ||||
|         private var anrCount = 0 | ||||
|  | ||||
|         // `RootViewWithoutFocusException` class is private, need to match the message (instead of using type matching). | ||||
|         private val rootViewWithoutFocusExceptionMsg = | ||||
|             java.lang.String.format( | ||||
|                 Locale.ROOT, | ||||
|                 "Waited for the root of the view hierarchy to have " + | ||||
|                     "window focus and not request layout for 10 seconds. If you specified a non " + | ||||
|                     "default root matcher, it may be picking a root that never takes focus. " + | ||||
|                     "Root:", | ||||
|             ) | ||||
|  | ||||
|         private fun handleAnrDialogue() { | ||||
|             val device = UiDevice.getInstance(getInstrumentation()) | ||||
|             // If running the device in English Locale | ||||
|             val waitButton = device.findObject(UiSelector().textContains("wait")) | ||||
|             if (waitButton.exists()) waitButton.click() | ||||
|         } | ||||
|  | ||||
|         @JvmStatic | ||||
|         @BeforeClass | ||||
|         fun setUpHandler() { | ||||
|             Espresso.setFailureHandler { error, viewMatcher -> | ||||
|  | ||||
|                 if (error.message!!.contains(rootViewWithoutFocusExceptionMsg) && anrCount < 3) { | ||||
|                     anrCount++ | ||||
|                     handleAnrDialogue() | ||||
|                 } else { // chain all failures down to the default espresso handler | ||||
|                     DefaultFailureHandler(getInstrumentation().targetContext).handle(error, viewMatcher) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| class MyScreenCaptureProcessor( | ||||
|     parentFolderPath: String, | ||||
| ) : BasicScreenCaptureProcessor() { | ||||
|     init { | ||||
|         this.mDefaultScreenshotPath = | ||||
|             File( | ||||
|                 File( | ||||
|                     getExternalStoragePublicDirectory(DIRECTORY_PICTURES), | ||||
|                     "selfoss_tests", | ||||
|                 ).absolutePath, | ||||
|                 "screenshots/$parentFolderPath", | ||||
|             ) | ||||
|     } | ||||
|  | ||||
|     override fun getFilename(prefix: String): String = prefix | ||||
| } | ||||
|  | ||||
| fun takeScreenshot( | ||||
|     parentFolderPath: String = "", | ||||
|     screenShotName: String, | ||||
| ) { | ||||
|     Log.d("Screenshots", "Taking screenshot of '$screenShotName'") | ||||
|     val screenCapture = Screenshot.capture() | ||||
|     val processors = setOf(MyScreenCaptureProcessor(parentFolderPath)) | ||||
|     try { | ||||
|         screenCapture.apply { | ||||
|             name = screenShotName | ||||
|             process(processors) | ||||
|         } | ||||
|         Log.d("Screenshots", "Screenshot taken") | ||||
|     } catch (ex: IOException) { | ||||
|         Log.e("Screenshots", "Could not take the screenshot", ex) | ||||
|     } | ||||
| } | ||||
|  | ||||
| class ScreenshotTakingRule : TestWatcher() { | ||||
|     override fun failed( | ||||
|         e: Throwable?, | ||||
|         description: Description, | ||||
|     ) { | ||||
|         val parentFolderPath = "failures/${description.className}" | ||||
|         takeScreenshot(parentFolderPath = parentFolderPath, screenShotName = description.methodName) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -18,14 +18,22 @@ import org.hamcrest.CoreMatchers.not | ||||
| import org.junit.Before | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| import org.junit.rules.RuleChain | ||||
| import org.junit.runner.RunWith | ||||
|  | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| @LargeTest | ||||
| class HomeActivityTest { | ||||
| class HomeActivityTest : WithANRException() { | ||||
|     @get:Rule | ||||
|     val activityRule = ActivityScenarioRule(LoginActivity::class.java) | ||||
|  | ||||
|     @JvmField | ||||
|     @Rule | ||||
|     val ruleChain: RuleChain = | ||||
|         RuleChain | ||||
|             .outerRule(activityRule) | ||||
|             .around(ScreenshotTakingRule()) | ||||
|  | ||||
|     @Before | ||||
|     fun init() { | ||||
|         loginAndInitHome() | ||||
| @@ -33,7 +41,7 @@ class HomeActivityTest { | ||||
|  | ||||
|     @Test | ||||
|     fun testMenu() { | ||||
|         onView(withId(R.id.action_search)).check(matches(isDisplayed())).check( | ||||
|         onView(withId(R.id.action_search)).check(matches(not(isDisplayed()))).check( | ||||
|             matches( | ||||
|                 isClickable(), | ||||
|             ), | ||||
|   | ||||
| @@ -17,14 +17,22 @@ import org.junit.After | ||||
| import org.junit.Before | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| import org.junit.rules.RuleChain | ||||
| import org.junit.runner.RunWith | ||||
|  | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| @LargeTest | ||||
| class LoginActivityTest { | ||||
| class LoginActivityTest : WithANRException() { | ||||
|     @get:Rule | ||||
|     val activityRule = ActivityScenarioRule(LoginActivity::class.java) | ||||
|  | ||||
|     @JvmField | ||||
|     @Rule | ||||
|     val ruleChain: RuleChain = | ||||
|         RuleChain | ||||
|             .outerRule(activityRule) | ||||
|             .around(ScreenshotTakingRule()) | ||||
|  | ||||
|     @Before | ||||
|     fun registerIdlingResource() { | ||||
|         IdlingRegistry | ||||
|   | ||||
| @@ -24,14 +24,22 @@ import org.hamcrest.CoreMatchers.not | ||||
| import org.junit.Before | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| import org.junit.rules.RuleChain | ||||
| import org.junit.runner.RunWith | ||||
|  | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| @LargeTest | ||||
| class SettingsActivityGeneralTest { | ||||
| class SettingsActivityGeneralTest : WithANRException() { | ||||
|     @get:Rule | ||||
|     val activityRule = ActivityScenarioRule(LoginActivity::class.java) | ||||
|  | ||||
|     @JvmField | ||||
|     @Rule | ||||
|     val ruleChain: RuleChain = | ||||
|         RuleChain | ||||
|             .outerRule(activityRule) | ||||
|             .around(ScreenshotTakingRule()) | ||||
|  | ||||
|     @Before | ||||
|     fun init() { | ||||
|         loginAndInitHome() | ||||
|   | ||||
| @@ -19,14 +19,22 @@ import org.hamcrest.CoreMatchers.not | ||||
| import org.junit.Before | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| import org.junit.rules.RuleChain | ||||
| import org.junit.runner.RunWith | ||||
|  | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| @LargeTest | ||||
| class SettingsActivityOfflineTest { | ||||
| class SettingsActivityOfflineTest : WithANRException() { | ||||
|     @get:Rule | ||||
|     val activityRule = ActivityScenarioRule(LoginActivity::class.java) | ||||
|  | ||||
|     @JvmField | ||||
|     @Rule | ||||
|     val ruleChain: RuleChain = | ||||
|         RuleChain | ||||
|             .outerRule(activityRule) | ||||
|             .around(ScreenshotTakingRule()) | ||||
|  | ||||
|     lateinit var context: Context | ||||
|  | ||||
|     @Before | ||||
|   | ||||
| @@ -17,14 +17,22 @@ import org.hamcrest.CoreMatchers.not | ||||
| import org.junit.Before | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| import org.junit.rules.RuleChain | ||||
| import org.junit.runner.RunWith | ||||
|  | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| @LargeTest | ||||
| class SettingsActivityReaderTest { | ||||
| class SettingsActivityReaderTest : WithANRException() { | ||||
|     @get:Rule | ||||
|     val activityRule = ActivityScenarioRule(LoginActivity::class.java) | ||||
|  | ||||
|     @JvmField | ||||
|     @Rule | ||||
|     val ruleChain: RuleChain = | ||||
|         RuleChain | ||||
|             .outerRule(activityRule) | ||||
|             .around(ScreenshotTakingRule()) | ||||
|  | ||||
|     lateinit var context: Context | ||||
|  | ||||
|     @Before | ||||
|   | ||||
| @@ -15,13 +15,22 @@ import org.hamcrest.CoreMatchers.not | ||||
| import org.junit.Before | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| import org.junit.rules.RuleChain | ||||
| import org.junit.runner.RunWith | ||||
|  | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| @LargeTest | ||||
| class SettingsActivityTest { | ||||
| class SettingsActivityTest : WithANRException() { | ||||
|     @get:Rule | ||||
|     val activityRule = ActivityScenarioRule(LoginActivity::class.java) | ||||
|  | ||||
|     @JvmField | ||||
|     @Rule | ||||
|     val ruleChain: RuleChain = | ||||
|         RuleChain | ||||
|             .outerRule(activityRule) | ||||
|             .around(ScreenshotTakingRule()) | ||||
|  | ||||
|     lateinit var context: Context | ||||
|  | ||||
|     @Before | ||||
|   | ||||
| @@ -18,15 +18,23 @@ import org.junit.After | ||||
| import org.junit.Before | ||||
| import org.junit.Rule | ||||
| import org.junit.Test | ||||
| import org.junit.rules.RuleChain | ||||
| import org.junit.runner.RunWith | ||||
| import java.util.UUID | ||||
|  | ||||
| @RunWith(AndroidJUnit4::class) | ||||
| @LargeTest | ||||
| class SourcesActivityTest { | ||||
| class SourcesActivityTest : WithANRException() { | ||||
|     @get:Rule | ||||
|     val activityRule = ActivityScenarioRule(LoginActivity::class.java) | ||||
|  | ||||
|     @JvmField | ||||
|     @Rule | ||||
|     val ruleChain: RuleChain = | ||||
|         RuleChain | ||||
|             .outerRule(activityRule) | ||||
|             .around(ScreenshotTakingRule()) | ||||
|  | ||||
|     lateinit var sourceName: String | ||||
|  | ||||
|     @Before | ||||
|   | ||||
		Reference in New Issue
	
	Block a user