From 9972f2bfa63b32f66d8eb813aac7e0b6c60836aa Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 29 Oct 2021 20:56:25 +0200 Subject: [PATCH 01/61] Test e2e Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 49 +++++++++++++++++++++++++++++++ app/build.gradle | 5 ++++ ci/runE2E.sh | 3 ++ ci/sleepUntilReady.sh | 16 ++++++++++ 4 files changed, 73 insertions(+) create mode 100644 .github/workflows/android-e2e.yml create mode 100755 ci/runE2E.sh create mode 100755 ci/sleepUntilReady.sh diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml new file mode 100644 index 000000000..955f99c26 --- /dev/null +++ b/.github/workflows/android-e2e.yml @@ -0,0 +1,49 @@ +on: [push] + +jobs: + setup_nextcloud: + runs-on: ubuntu-latest + name: Run e2e test + services: + nextcloud: + image: nextcloud:latest + env: + SQLITE_DATABASE: db.sqlite + NEXTCLOUD_ADMIN_USER: Test + NEXTCLOUD_ADMIN_PASSWORD: Test + ports: + - 8080:80 + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Wait for Nextcloud instance + run: sh ci/sleepUntilReady.sh 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' 30 + + - name: List running Docker containers + run: | + docker ps + echo "Current docker container ID: `docker ps -f 'name=_nextcloudlatest_' -l -q`" + + - name: Print Container information + run: | + docker exec `docker ps -f 'name=_nextcloudlatest_' -l -q` bash -c 'whoami' + docker exec `docker ps -f 'name=_nextcloudlatest_' -l -q` bash -c 'uname -a' + + - name: Enable Deck via Docker Exec + run: | + docker exec `docker ps -f 'name=_nextcloudlatest_' -l -q` bash -c 'runuser -u www-data -- php occ app:install deck' + + - name: Fetch capabilities + run: | + curl -v -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/cloud/capabilities?format=json' -H 'OCS-APIRequest: true' | jq + + - name: Fetch server info + run: | + curl -v -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' -H 'OCS-APIRequest: true' | jq + + - name: Run emulator + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 29 + script: sh ci/runE2E.sh \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index c94aa8aa6..43a053efd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -126,4 +126,9 @@ dependencies { testImplementation 'org.mockito:mockito-core:4.0.0' testImplementation 'androidx.test:core:1.4.0' testImplementation 'androidx.arch.core:core-testing:2.1.0' + + androidTestImplementation 'androidx.test:runner:1.4.0' + androidTestImplementation 'androidx.test:rules:1.4.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' } diff --git a/ci/runE2E.sh b/ci/runE2E.sh new file mode 100755 index 000000000..cefdb2acb --- /dev/null +++ b/ci/runE2E.sh @@ -0,0 +1,3 @@ +wget https://download.nextcloud.com/android/dev/latest.apk +adb install latest.apk +exit 0; \ No newline at end of file diff --git a/ci/sleepUntilReady.sh b/ci/sleepUntilReady.sh new file mode 100755 index 000000000..69d0bf06c --- /dev/null +++ b/ci/sleepUntilReady.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +url=$1 +maxTries=$2 +delay=1s # also valid: 1m 1.5s etc. +for i in $(seq 1 $maxTries); do + response=$(curl -LI $url -H 'OCS-APIRequest: true' -o /dev/null -w '%{http_code}\n' -s) + echo "Check instance being ready: Attempt $i of $maxTries…" + if [ $response -eq '200' ] || [ $response -eq '204' ] + then + exit 0 + fi + sleep $delay +done + +exit 1 \ No newline at end of file From 5f90ab3216be2611b25e6e26e6afeeba0a65ccb8 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 29 Oct 2021 21:07:05 +0200 Subject: [PATCH 02/61] Add sample test Signed-off-by: Stefan Niedermann --- app/src/androidTest/java/E2ETest.java | 18 ++++++++++++++++++ ci/runE2E.sh | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 app/src/androidTest/java/E2ETest.java diff --git a/app/src/androidTest/java/E2ETest.java b/app/src/androidTest/java/E2ETest.java new file mode 100644 index 000000000..4edb4bfd7 --- /dev/null +++ b/app/src/androidTest/java/E2ETest.java @@ -0,0 +1,18 @@ +import static org.hamcrest.MatcherAssert.assertThat; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +// @RunWith is required only if you use a mix of JUnit3 and JUnit4. +@RunWith(AndroidJUnit4.class) +@SmallTest +public class E2ETest { + + @Test + public void sampleTest() { + assertThat("Test fail on purpose", false); + } +} diff --git a/ci/runE2E.sh b/ci/runE2E.sh index cefdb2acb..266f604fa 100755 --- a/ci/runE2E.sh +++ b/ci/runE2E.sh @@ -1,3 +1,3 @@ wget https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk -exit 0; \ No newline at end of file +./gradlew connectedAndroidTest \ No newline at end of file From 964ea2fce126d7c10a3aa023f83e5f32d61fb32d Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 29 Oct 2021 21:21:57 +0200 Subject: [PATCH 03/61] Move e2e script into workflow Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 5 ++++- ci/runE2E.sh | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) delete mode 100755 ci/runE2E.sh diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 955f99c26..86819e818 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -46,4 +46,7 @@ jobs: uses: reactivecircus/android-emulator-runner@v2 with: api-level: 29 - script: sh ci/runE2E.sh \ No newline at end of file + script: | + wget -q https://download.nextcloud.com/android/dev/latest.apk + adb install latest.apk + ./gradlew connectedAndroidTest \ No newline at end of file diff --git a/ci/runE2E.sh b/ci/runE2E.sh deleted file mode 100755 index 266f604fa..000000000 --- a/ci/runE2E.sh +++ /dev/null @@ -1,3 +0,0 @@ -wget https://download.nextcloud.com/android/dev/latest.apk -adb install latest.apk -./gradlew connectedAndroidTest \ No newline at end of file From 1f521bfcca724ccc8338bedebf01e5113dd5e97e Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 29 Oct 2021 21:51:46 +0200 Subject: [PATCH 04/61] Login flow Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 18 +++++++++++++ app/build.gradle | 1 + app/src/androidTest/java/E2ETest.java | 18 ------------- .../niedermann/nextcloud/deck/ui/E2ETest.java | 26 +++++++++++++++++++ .../deck/ui/ImportAccountActivity.java | 2 +- 5 files changed, 46 insertions(+), 19 deletions(-) delete mode 100644 app/src/androidTest/java/E2ETest.java create mode 100644 app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 86819e818..dd2f25322 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -49,4 +49,22 @@ jobs: script: | wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk + adb shell monkey -p com.nextcloud.client -c android.intent.category.LAUNCHER 1 + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_ENTER" + adb shell input text "http://localhost:8080" + adb shell input keyevent "KEYCODE_ENTER" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_ENTER" + adb shell input text "Test" + adb shell input keyevent "KEYCODE_TAB" + adb shell input text "Test" + adb shell input keyevent "KEYCODE_ENTER" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_ENTER" ./gradlew connectedAndroidTest \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 43a053efd..d47922663 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,6 +66,7 @@ dependencies { implementation project(path: ':cross-tab-drag-and-drop') // TabLayoutHelper implementation project(path: ':tab-layout-helper') + implementation 'androidx.test.ext:junit:1.1.3' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' diff --git a/app/src/androidTest/java/E2ETest.java b/app/src/androidTest/java/E2ETest.java deleted file mode 100644 index 4edb4bfd7..000000000 --- a/app/src/androidTest/java/E2ETest.java +++ /dev/null @@ -1,18 +0,0 @@ -import static org.hamcrest.MatcherAssert.assertThat; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -// @RunWith is required only if you use a mix of JUnit3 and JUnit4. -@RunWith(AndroidJUnit4.class) -@SmallTest -public class E2ETest { - - @Test - public void sampleTest() { - assertThat("Test fail on purpose", false); - } -} diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java new file mode 100644 index 000000000..1d88ce55e --- /dev/null +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -0,0 +1,26 @@ +package it.niedermann.nextcloud.deck.ui; + +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +// @RunWith is required only if you use a mix of JUnit3 and JUnit4. +@RunWith(AndroidJUnit4.class) +@SmallTest +public class E2ETest { + + @Rule + public ActivityScenarioRule rule = new ActivityScenarioRule<>(ImportAccountActivity.class); + + @Test + public void sampleTest() { + final var scenario = rule.getScenario(); + scenario.onActivity(activity -> { + activity.binding.addButton.performClick(); + }); + } +} diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java index 7910c55de..6107f9f09 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java @@ -48,7 +48,7 @@ public class ImportAccountActivity extends AppCompatActivity { private String sharedPreferenceLastAccount; private String urlFragmentUpdateDeck; - private ActivityImportAccountBinding binding; + protected ActivityImportAccountBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { From 03337f1362a7c73385d486adff7c366aaf4558d8 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 29 Oct 2021 22:12:55 +0200 Subject: [PATCH 05/61] Add sleep Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 1 + .../niedermann/nextcloud/deck/ui/E2ETest.java | 33 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index dd2f25322..84c92ce51 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -49,6 +49,7 @@ jobs: script: | wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk + sleep 5s adb shell monkey -p com.nextcloud.client -c android.intent.category.LAUNCHER 1 adb shell input keyevent "KEYCODE_TAB" adb shell input keyevent "KEYCODE_TAB" diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 1d88ce55e..40e36a6ff 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -1,5 +1,8 @@ package it.niedermann.nextcloud.deck.ui; +import android.app.Instrumentation; +import android.view.KeyEvent; + import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -8,19 +11,47 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.CountDownLatch; + // @RunWith is required only if you use a mix of JUnit3 and JUnit4. @RunWith(AndroidJUnit4.class) @SmallTest public class E2ETest { @Rule - public ActivityScenarioRule rule = new ActivityScenarioRule<>(ImportAccountActivity.class); + public ActivityScenarioRule rule = new ActivityScenarioRule<>(ImportAccountActivity.class); @Test public void sampleTest() { final var scenario = rule.getScenario(); scenario.onActivity(activity -> { + final var latch = new CountDownLatch(1); activity.binding.addButton.performClick(); + new Thread(() -> { + try { + final var inst = new Instrumentation(); + Thread.sleep(1_000); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); + Thread.sleep(1_000); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_SPACE); + Thread.sleep(1_000); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); + Thread.sleep(1_000); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); + Thread.sleep(1_000); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); + Thread.sleep(1_000); + inst.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER); + latch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + try { + latch.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } }); } } From 8c40b696b489cc276d23e6e725815274054e94cd Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 29 Oct 2021 22:34:48 +0200 Subject: [PATCH 06/61] Fix package name of downloaded NC apk Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 3 +- .../niedermann/nextcloud/deck/ui/E2ETest.java | 40 +++++-------------- 2 files changed, 11 insertions(+), 32 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 84c92ce51..e1b39ac58 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -50,7 +50,7 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s - adb shell monkey -p com.nextcloud.client -c android.intent.category.LAUNCHER 1 + adb shell monkey -p com.nextcloud.android.beta -c android.intent.category.LAUNCHER 1 adb shell input keyevent "KEYCODE_TAB" adb shell input keyevent "KEYCODE_TAB" adb shell input keyevent "KEYCODE_TAB" @@ -68,4 +68,5 @@ jobs: adb shell input keyevent "KEYCODE_ENTER" adb shell input keyevent "KEYCODE_TAB" adb shell input keyevent "KEYCODE_ENTER" + ./gradlew connectedAndroidTest \ No newline at end of file diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 40e36a6ff..83971c7ea 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -1,18 +1,14 @@ package it.niedermann.nextcloud.deck.ui; -import android.app.Instrumentation; -import android.view.KeyEvent; - import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.concurrent.CountDownLatch; - // @RunWith is required only if you use a mix of JUnit3 and JUnit4. @RunWith(AndroidJUnit4.class) @SmallTest @@ -25,33 +21,15 @@ public class E2ETest { public void sampleTest() { final var scenario = rule.getScenario(); scenario.onActivity(activity -> { - final var latch = new CountDownLatch(1); activity.binding.addButton.performClick(); - new Thread(() -> { - try { - final var inst = new Instrumentation(); - Thread.sleep(1_000); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); - Thread.sleep(1_000); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_SPACE); - Thread.sleep(1_000); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); - Thread.sleep(1_000); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); - Thread.sleep(1_000); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_TAB); - Thread.sleep(1_000); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER); - latch.countDown(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }).start(); - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + + final var inst = InstrumentationRegistry.getInstrumentation(); + inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); + inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_SPACE\""); + inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); + inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); + inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); + inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_ENTER\""); }); } } From e7715e5d3a7f92a24048d8521f37191236402189 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Fri, 29 Oct 2021 22:40:39 +0200 Subject: [PATCH 07/61] Configure NC account via adb Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 13 +++++++++++++ .../it/niedermann/nextcloud/deck/ui/E2ETest.java | 14 ++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index e1b39ac58..f2f0bf02d 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -69,4 +69,17 @@ jobs: adb shell input keyevent "KEYCODE_TAB" adb shell input keyevent "KEYCODE_ENTER" + ./gradlew assembleDev + adb install app/build/outputs/apk/dev/debug/app-dev-debug.apk + adb shell monkey -p it.niedermann.nextcloud.deck.dev -c android.intent.category.LAUNCHER 1 + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_ENTER" + + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_SPACE" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_TAB" + adb shell input keyevent "KEYCODE_ENTER" + ./gradlew connectedAndroidTest \ No newline at end of file diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 83971c7ea..5138aaebe 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -1,8 +1,10 @@ package it.niedermann.nextcloud.deck.ui; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.filters.SmallTest; -import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; @@ -21,15 +23,7 @@ public class E2ETest { public void sampleTest() { final var scenario = rule.getScenario(); scenario.onActivity(activity -> { - activity.binding.addButton.performClick(); - - final var inst = InstrumentationRegistry.getInstrumentation(); - inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); - inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_SPACE\""); - inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); - inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); - inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_TAB\""); - inst.getUiAutomation().executeShellCommand("input keyevent \"KEYCODE_ENTER\""); + onView(withText("Task")); }); } } From 5def0a0b87def898a5a4f99568b476679bd974d3 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sat, 30 Oct 2021 00:02:13 +0200 Subject: [PATCH 08/61] another try - should fail Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 5138aaebe..7e0411048 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -16,6 +16,8 @@ @SmallTest public class E2ETest { +// @Rule +// public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(Manifest.permission.ACCOUNT_MANAGER); @Rule public ActivityScenarioRule rule = new ActivityScenarioRule<>(ImportAccountActivity.class); @@ -24,6 +26,7 @@ public void sampleTest() { final var scenario = rule.getScenario(); scenario.onActivity(activity -> { onView(withText("Task")); + onView(withText("Halloween")); }); } } From ad1751eed1e8611f93593b56395e5b9e5e08b5ea Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sat, 30 Oct 2021 15:04:57 +0200 Subject: [PATCH 09/61] Be more explicit Signed-off-by: Stefan Niedermann --- .../niedermann/nextcloud/deck/ui/E2ETest.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 7e0411048..86db04c6f 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -1,32 +1,40 @@ package it.niedermann.nextcloud.deck.ui; import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import androidx.test.core.app.ActivityScenario; import androidx.test.ext.junit.rules.ActivityScenarioRule; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; +import org.junit.After; import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; -// @RunWith is required only if you use a mix of JUnit3 and JUnit4. -@RunWith(AndroidJUnit4.class) -@SmallTest +import it.niedermann.nextcloud.deck.R; + public class E2ETest { -// @Rule -// public GrantPermissionRule mRuntimePermissionRule = GrantPermissionRule.grant(Manifest.permission.ACCOUNT_MANAGER); + public ActivityScenario scenario; @Rule - public ActivityScenarioRule rule = new ActivityScenarioRule<>(ImportAccountActivity.class); + public ActivityScenarioRule rule = new ActivityScenarioRule<>(MainActivity.class); @Test public void sampleTest() { - final var scenario = rule.getScenario(); + scenario = rule.getScenario(); scenario.onActivity(activity -> { - onView(withText("Task")); - onView(withText("Halloween")); + final var fieldMatcher = withId(R.id.filter); + final var interaction = onView(fieldMatcher); + final var matcher = isDisplayed(); + final var assertion = matches(matcher); + interaction.check(assertion); +// onView(withText("Halloween")).check(matches(isDisplayed())); }); } + + @After + public void cleanup() { + scenario.close(); + } } From 8c9852c7d36148dfc307a774331cf5c52f33e539 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sat, 30 Oct 2021 15:26:57 +0200 Subject: [PATCH 10/61] Only run connectedDevDebugAndroidTest Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index f2f0bf02d..b4ff21d57 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -69,7 +69,7 @@ jobs: adb shell input keyevent "KEYCODE_TAB" adb shell input keyevent "KEYCODE_ENTER" - ./gradlew assembleDev + ./gradlew assembleDevDebug adb install app/build/outputs/apk/dev/debug/app-dev-debug.apk adb shell monkey -p it.niedermann.nextcloud.deck.dev -c android.intent.category.LAUNCHER 1 adb shell input keyevent "KEYCODE_TAB" @@ -82,4 +82,4 @@ jobs: adb shell input keyevent "KEYCODE_TAB" adb shell input keyevent "KEYCODE_ENTER" - ./gradlew connectedAndroidTest \ No newline at end of file + ./gradlew connectedDevDebugAndroidTest \ No newline at end of file From 9ff88ed88d4c5079bb448fdeeabe4a58f69aa053 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sat, 30 Oct 2021 17:12:37 +0200 Subject: [PATCH 11/61] Use --health-cmd instead of sleepUntilReady.sh Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 9 ++++++--- .../it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- ci/sleepUntilReady.sh | 16 ---------------- 3 files changed, 7 insertions(+), 20 deletions(-) delete mode 100755 ci/sleepUntilReady.sh diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index b4ff21d57..9df291980 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -13,13 +13,16 @@ jobs: NEXTCLOUD_ADMIN_PASSWORD: Test ports: - 8080:80 + options: >- + --health-cmd "curl GET 'http://Test:Test@localhost:80/ocs/v2.php/apps/serverinfo/api/v1/info' -f -H 'OCS-APIRequest: true' || exit 1" + --health-interval 1s + --health-timeout 2s + --health-retries 10 + --health-start-period 3s steps: - name: Checkout uses: actions/checkout@v2 - - name: Wait for Nextcloud instance - run: sh ci/sleepUntilReady.sh 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' 30 - - name: List running Docker containers run: | docker ps diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 86db04c6f..38a8dc3f5 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -28,7 +28,7 @@ public void sampleTest() { final var interaction = onView(fieldMatcher); final var matcher = isDisplayed(); final var assertion = matches(matcher); - interaction.check(assertion); +// interaction.check(assertion); // onView(withText("Halloween")).check(matches(isDisplayed())); }); } diff --git a/ci/sleepUntilReady.sh b/ci/sleepUntilReady.sh deleted file mode 100755 index 69d0bf06c..000000000 --- a/ci/sleepUntilReady.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -url=$1 -maxTries=$2 -delay=1s # also valid: 1m 1.5s etc. -for i in $(seq 1 $maxTries); do - response=$(curl -LI $url -H 'OCS-APIRequest: true' -o /dev/null -w '%{http_code}\n' -s) - echo "Check instance being ready: Attempt $i of $maxTries…" - if [ $response -eq '200' ] || [ $response -eq '204' ] - then - exit 0 - fi - sleep $delay -done - -exit 1 \ No newline at end of file From abe5dd239d6460ffe9e98339a50bd049ab4e57a7 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 09:43:17 +0100 Subject: [PATCH 12/61] Try new e2e test using UI Automator Signed-off-by: Stefan Niedermann --- .../niedermann/nextcloud/deck/ui/E2ETest.java | 147 ++++++++++++++---- 1 file changed, 121 insertions(+), 26 deletions(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 38a8dc3f5..9e1916a10 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -1,40 +1,135 @@ package it.niedermann.nextcloud.deck.ui; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import androidx.test.core.app.ActivityScenario; -import androidx.test.ext.junit.rules.ActivityScenarioRule; +import android.content.Context; +import android.content.Intent; +import android.webkit.WebView; +import android.widget.Button; +import android.widget.EditText; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; +import androidx.test.uiautomator.Until; + +import com.google.android.material.card.MaterialCardView; -import it.niedermann.nextcloud.deck.R; +import org.junit.Test; public class E2ETest { - public ActivityScenario scenario; - @Rule - public ActivityScenarioRule rule = new ActivityScenarioRule<>(MainActivity.class); + private UiDevice mDevice; @Test - public void sampleTest() { - scenario = rule.getScenario(); - scenario.onActivity(activity -> { - final var fieldMatcher = withId(R.id.filter); - final var interaction = onView(fieldMatcher); - final var matcher = isDisplayed(); - final var assertion = matches(matcher); -// interaction.check(assertion); -// onView(withText("Halloween")).check(matches(isDisplayed())); - }); + public void setUp() throws UiObjectNotFoundException { + setupNextcloudAccount("http://localhost:8080", "Test", "Test"); + importAccountIntoDeck(); + verfiyCardsPresent(); } - @After - public void cleanup() { - scenario.close(); + private void setupNextcloudAccount(String url, String username, String password) throws UiObjectNotFoundException { + final var CALC_PACKAGE = "com.nextcloud.android.beta"; + // Initialize UiDevice instance + mDevice = UiDevice.getInstance(getInstrumentation()); + + // Launch a simple calculator app + final var context = getInstrumentation().getContext(); + final var intent = context.getPackageManager() + .getLaunchIntentForPackage(CALC_PACKAGE) + .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + // Clear out any previous instances + context.startActivity(intent); + mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); + + mDevice.findObject(new UiSelector().text("Log in")).click(); + mDevice.findObject(new UiSelector().focused(true)).setText(url); + mDevice.pressEnter(); + mDevice.findObject(new UiSelector().text("Log in")).click(); + + mDevice.wait(Until.findObject(By.clazz(WebView.class)), 30); + + final var usernameInput = mDevice.findObject(new UiSelector() + .instance(0) + .className(EditText.class)); + + usernameInput.waitForExists(30); + usernameInput.setText(username); + + final var passwordInput = mDevice.findObject(new UiSelector() + .instance(1) + .className(EditText.class)); + + passwordInput.waitForExists(30); + passwordInput.setText(password); + + mDevice.findObject(new UiSelector().text("Log in")).click(); + + mDevice.findObject(new UiSelector().text("Grant access")).click(); + } + + private void importAccountIntoDeck() throws UiObjectNotFoundException { + final var CALC_PACKAGE = "it.niedermann.nextcloud.deck.dev"; + // Initialize UiDevice instance + mDevice = UiDevice.getInstance(getInstrumentation()); + + // Launch a simple calculator app + Context context = getInstrumentation().getContext(); + Intent intent = context.getPackageManager() + .getLaunchIntentForPackage(CALC_PACKAGE); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + // Clear out any previous instances + context.startActivity(intent); + mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); + + final var accountButton = mDevice.findObject(new UiSelector() + .instance(0) + .className(Button.class)); + + accountButton.waitForExists(30); + accountButton.click(); + + final var radioAccount = mDevice.findObject(new UiSelector() + .clickable(true) + .instance(0)); + + radioAccount.waitForExists(30); + radioAccount.click(); + + final var okButton = mDevice.findObject(new UiSelector().text("OK")); + + okButton.waitForExists(30); + okButton.click(); + + final var allowButton = mDevice.findObject(new UiSelector().text("Allow")); + + allowButton.waitForExists(30); + allowButton.click(); + + final var welcomeText = mDevice.findObject(new UiSelector().description("Filter")); + welcomeText.waitForExists(30); +// mDevice.wait + } + + private void verfiyCardsPresent() { + final var CALC_PACKAGE = "it.niedermann.nextcloud.deck.dev"; + // Initialize UiDevice instance + mDevice = UiDevice.getInstance(getInstrumentation()); + + // Launch a simple calculator app + Context context = getInstrumentation().getContext(); + Intent intent = context.getPackageManager() + .getLaunchIntentForPackage(CALC_PACKAGE); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + // Clear out any previous instances + context.startActivity(intent); + mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); + + final var accountButton = mDevice.findObject(new UiSelector() + .instance(0) + .className(MaterialCardView.class)); + + accountButton.waitForExists(30); } } From d56b8904e91e1374d9bd5bfb0c0376ebc75a843b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 09:44:58 +0100 Subject: [PATCH 13/61] Remove Files app setup from workflow Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 32 ------------------------------- 1 file changed, 32 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 9df291980..467c2eac7 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -53,36 +53,4 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s - adb shell monkey -p com.nextcloud.android.beta -c android.intent.category.LAUNCHER 1 - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_ENTER" - adb shell input text "http://localhost:8080" - adb shell input keyevent "KEYCODE_ENTER" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_ENTER" - adb shell input text "Test" - adb shell input keyevent "KEYCODE_TAB" - adb shell input text "Test" - adb shell input keyevent "KEYCODE_ENTER" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_ENTER" - - ./gradlew assembleDevDebug - adb install app/build/outputs/apk/dev/debug/app-dev-debug.apk - adb shell monkey -p it.niedermann.nextcloud.deck.dev -c android.intent.category.LAUNCHER 1 - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_ENTER" - - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_SPACE" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_TAB" - adb shell input keyevent "KEYCODE_ENTER" - ./gradlew connectedDevDebugAndroidTest \ No newline at end of file From 074b42b2f0d2858563728c50576f362942ff4092 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 09:52:27 +0100 Subject: [PATCH 14/61] Make and store screenshots Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 8 +++++++- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 467c2eac7..bc5d09fd2 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -53,4 +53,10 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s - ./gradlew connectedDevDebugAndroidTest \ No newline at end of file + ./gradlew connectedDevDebugAndroidTest + adb pull "/sdcard/screenshots" "screenshots" + - name: Store screenshots + uses: actions/upload-artifact@v2 + with: + name: screenshots + path: screenshots \ No newline at end of file diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 9e1916a10..99072e151 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -18,6 +18,8 @@ import org.junit.Test; +import java.io.File; + public class E2ETest { private UiDevice mDevice; @@ -83,11 +85,14 @@ private void importAccountIntoDeck() throws UiObjectNotFoundException { context.startActivity(intent); mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); + + final var accountButton = mDevice.findObject(new UiSelector() .instance(0) .className(Button.class)); accountButton.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/1.png")); accountButton.click(); final var radioAccount = mDevice.findObject(new UiSelector() @@ -95,20 +100,24 @@ private void importAccountIntoDeck() throws UiObjectNotFoundException { .instance(0)); radioAccount.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/2.png")); radioAccount.click(); final var okButton = mDevice.findObject(new UiSelector().text("OK")); okButton.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/3.png")); okButton.click(); final var allowButton = mDevice.findObject(new UiSelector().text("Allow")); allowButton.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/4.png")); allowButton.click(); final var welcomeText = mDevice.findObject(new UiSelector().description("Filter")); welcomeText.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/5.png")); // mDevice.wait } From 4886e8750710f14aa8f333e73621c55801f65c6e Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 10:07:21 +0100 Subject: [PATCH 15/61] Add more screenshots Signed-off-by: Stefan Niedermann --- .../it/niedermann/nextcloud/deck/ui/E2ETest.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 99072e151..ea4c929ca 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -45,18 +45,29 @@ private void setupNextcloudAccount(String url, String username, String password) context.startActivity(intent); mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); - mDevice.findObject(new UiSelector().text("Log in")).click(); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-1.png")); + + final var loginButton1 = mDevice.findObject(new UiSelector().text("Log in")); + + loginButton1.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-2.png")); + loginButton1.click(); + mDevice.findObject(new UiSelector().focused(true)).setText(url); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-3.png")); mDevice.pressEnter(); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-4.png")); mDevice.findObject(new UiSelector().text("Log in")).click(); mDevice.wait(Until.findObject(By.clazz(WebView.class)), 30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-5.png")); final var usernameInput = mDevice.findObject(new UiSelector() .instance(0) .className(EditText.class)); usernameInput.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-6.png")); usernameInput.setText(username); final var passwordInput = mDevice.findObject(new UiSelector() @@ -64,11 +75,14 @@ private void setupNextcloudAccount(String url, String username, String password) .className(EditText.class)); passwordInput.waitForExists(30); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-7.png")); passwordInput.setText(password); mDevice.findObject(new UiSelector().text("Log in")).click(); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-8.png")); mDevice.findObject(new UiSelector().text("Grant access")).click(); + mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-9.png")); } private void importAccountIntoDeck() throws UiObjectNotFoundException { From 1cb08af13526cbe5b9013da1435a1b2df2c699a7 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 10:13:36 +0100 Subject: [PATCH 16/61] Rename screenshots Signed-off-by: Stefan Niedermann --- .../niedermann/nextcloud/deck/ui/E2ETest.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index ea4c929ca..d8e416905 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -8,6 +8,7 @@ import android.widget.Button; import android.widget.EditText; +import androidx.annotation.NonNull; import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObjectNotFoundException; @@ -45,29 +46,28 @@ private void setupNextcloudAccount(String url, String username, String password) context.startActivity(intent); mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-1.png")); + screenshot("setup-1"); final var loginButton1 = mDevice.findObject(new UiSelector().text("Log in")); - loginButton1.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-2.png")); + screenshot("setup-2"); loginButton1.click(); mDevice.findObject(new UiSelector().focused(true)).setText(url); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-3.png")); + screenshot("setup-3"); mDevice.pressEnter(); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-4.png")); + screenshot("setup-4"); mDevice.findObject(new UiSelector().text("Log in")).click(); mDevice.wait(Until.findObject(By.clazz(WebView.class)), 30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-5.png")); + screenshot("setup-5"); final var usernameInput = mDevice.findObject(new UiSelector() .instance(0) .className(EditText.class)); usernameInput.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-6.png")); + screenshot("setup-6"); usernameInput.setText(username); final var passwordInput = mDevice.findObject(new UiSelector() @@ -75,14 +75,14 @@ private void setupNextcloudAccount(String url, String username, String password) .className(EditText.class)); passwordInput.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-7.png")); + screenshot("setup-7"); passwordInput.setText(password); mDevice.findObject(new UiSelector().text("Log in")).click(); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-8.png")); + screenshot("setup-8"); mDevice.findObject(new UiSelector().text("Grant access")).click(); - mDevice.takeScreenshot(new File("/sdcard/screenshots/setup-9.png")); + screenshot("setup-9"); } private void importAccountIntoDeck() throws UiObjectNotFoundException { @@ -99,14 +99,12 @@ private void importAccountIntoDeck() throws UiObjectNotFoundException { context.startActivity(intent); mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); - - final var accountButton = mDevice.findObject(new UiSelector() .instance(0) .className(Button.class)); accountButton.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/1.png")); + screenshot("deck-1"); accountButton.click(); final var radioAccount = mDevice.findObject(new UiSelector() @@ -114,25 +112,24 @@ private void importAccountIntoDeck() throws UiObjectNotFoundException { .instance(0)); radioAccount.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/2.png")); + screenshot("deck-2"); radioAccount.click(); final var okButton = mDevice.findObject(new UiSelector().text("OK")); okButton.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/3.png")); + screenshot("deck-3"); okButton.click(); final var allowButton = mDevice.findObject(new UiSelector().text("Allow")); allowButton.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/4.png")); + screenshot("deck-4"); allowButton.click(); final var welcomeText = mDevice.findObject(new UiSelector().description("Filter")); welcomeText.waitForExists(30); - mDevice.takeScreenshot(new File("/sdcard/screenshots/5.png")); -// mDevice.wait + screenshot("deck-5"); } private void verfiyCardsPresent() { @@ -154,5 +151,10 @@ private void verfiyCardsPresent() { .className(MaterialCardView.class)); accountButton.waitForExists(30); + screenshot("deck-validate-1"); + } + + private void screenshot(@NonNull String name) { + mDevice.takeScreenshot(new File("/sdcard/screenshots/" + name + ".png")); } } From 9c5ade7f7b29b4e2a84f9f76efe45a2eb90e0758 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 10:19:14 +0100 Subject: [PATCH 17/61] Refactoring Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 1 + .../niedermann/nextcloud/deck/ui/E2ETest.java | 66 ++++++------------- 2 files changed, 21 insertions(+), 46 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index bc5d09fd2..5060f3c02 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -46,6 +46,7 @@ jobs: curl -v -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' -H 'OCS-APIRequest: true' | jq - name: Run emulator + continue-on-error: true uses: reactivecircus/android-emulator-runner@v2 with: api-level: 29 diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index d8e416905..4a237069b 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -2,7 +2,6 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import android.content.Context; import android.content.Intent; import android.webkit.WebView; import android.widget.Button; @@ -26,28 +25,19 @@ public class E2ETest { private UiDevice mDevice; @Test - public void setUp() throws UiObjectNotFoundException { - setupNextcloudAccount("http://localhost:8080", "Test", "Test"); - importAccountIntoDeck(); - verfiyCardsPresent(); - } - - private void setupNextcloudAccount(String url, String username, String password) throws UiObjectNotFoundException { - final var CALC_PACKAGE = "com.nextcloud.android.beta"; - // Initialize UiDevice instance + public void e2e() throws UiObjectNotFoundException { mDevice = UiDevice.getInstance(getInstrumentation()); + launch("com.nextcloud.android.beta"); + configureNextcloudAccount("http://localhost:8080", "Test", "Test"); - // Launch a simple calculator app - final var context = getInstrumentation().getContext(); - final var intent = context.getPackageManager() - .getLaunchIntentForPackage(CALC_PACKAGE) - .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - // Clear out any previous instances - context.startActivity(intent); - mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); + launch("it.niedermann.nextcloud.deck.dev"); + importAccountIntoDeck(); + + verifyCardsPresent(); + } - screenshot("setup-1"); + private void configureNextcloudAccount(String url, String username, String password) throws UiObjectNotFoundException { final var loginButton1 = mDevice.findObject(new UiSelector().text("Log in")); loginButton1.waitForExists(30); screenshot("setup-2"); @@ -86,19 +76,6 @@ private void setupNextcloudAccount(String url, String username, String password) } private void importAccountIntoDeck() throws UiObjectNotFoundException { - final var CALC_PACKAGE = "it.niedermann.nextcloud.deck.dev"; - // Initialize UiDevice instance - mDevice = UiDevice.getInstance(getInstrumentation()); - - // Launch a simple calculator app - Context context = getInstrumentation().getContext(); - Intent intent = context.getPackageManager() - .getLaunchIntentForPackage(CALC_PACKAGE); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - // Clear out any previous instances - context.startActivity(intent); - mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); - final var accountButton = mDevice.findObject(new UiSelector() .instance(0) .className(Button.class)); @@ -132,20 +109,7 @@ private void importAccountIntoDeck() throws UiObjectNotFoundException { screenshot("deck-5"); } - private void verfiyCardsPresent() { - final var CALC_PACKAGE = "it.niedermann.nextcloud.deck.dev"; - // Initialize UiDevice instance - mDevice = UiDevice.getInstance(getInstrumentation()); - - // Launch a simple calculator app - Context context = getInstrumentation().getContext(); - Intent intent = context.getPackageManager() - .getLaunchIntentForPackage(CALC_PACKAGE); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - // Clear out any previous instances - context.startActivity(intent); - mDevice.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), 30); - + private void verifyCardsPresent() { final var accountButton = mDevice.findObject(new UiSelector() .instance(0) .className(MaterialCardView.class)); @@ -154,6 +118,16 @@ private void verfiyCardsPresent() { screenshot("deck-validate-1"); } + private void launch(@NonNull String packageName) { + final var context = getInstrumentation().getContext(); + context.startActivity(context + .getPackageManager() + .getLaunchIntentForPackage(packageName) + .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)); + mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), 30); + screenshot("launch-" + packageName + ".png"); + } + private void screenshot(@NonNull String name) { mDevice.takeScreenshot(new File("/sdcard/screenshots/" + name + ".png")); } From e2a9753ed0995ac137f8b2df72e4b5001091ffe8 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 10:42:54 +0100 Subject: [PATCH 18/61] List files Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 5060f3c02..84922fcff 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -56,6 +56,8 @@ jobs: sleep 5s ./gradlew connectedDevDebugAndroidTest adb pull "/sdcard/screenshots" "screenshots" + - name: List files + run: ls -all - name: Store screenshots uses: actions/upload-artifact@v2 with: From a862e7a010080b0ea8136aa9be4960cfd1a7f97b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 10:43:20 +0100 Subject: [PATCH 19/61] upload everything Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 84922fcff..d9258f055 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -61,5 +61,5 @@ jobs: - name: Store screenshots uses: actions/upload-artifact@v2 with: - name: screenshots - path: screenshots \ No newline at end of file + name: stuff + path: . \ No newline at end of file From 0628510b43005edc957e4df5d528f08ed0357b6c Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 10:54:35 +0100 Subject: [PATCH 20/61] Upload reports as described in ... ... https://medium.com/upday-devs/how-to-setup-github-actions-for-android-projects-a94e8e3b0539 Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index d9258f055..32815ea0a 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -46,7 +46,6 @@ jobs: curl -v -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' -H 'OCS-APIRequest: true' | jq - name: Run emulator - continue-on-error: true uses: reactivecircus/android-emulator-runner@v2 with: api-level: 29 @@ -58,7 +57,14 @@ jobs: adb pull "/sdcard/screenshots" "screenshots" - name: List files run: ls -all + - name: Upload Reports + if: always() + uses: actions/upload-artifact@v2 + with: + name: Test-Reports + path: app/build/reports - name: Store screenshots + if: always() uses: actions/upload-artifact@v2 with: name: stuff From 9b8f7991b7ed66607b4ae8ffda1009e0e636943b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 11:13:58 +0100 Subject: [PATCH 21/61] Try pulling screenshots from runner machine Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 ++ .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 32815ea0a..6a7b03b57 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -57,6 +57,8 @@ jobs: adb pull "/sdcard/screenshots" "screenshots" - name: List files run: ls -all + - name: Pull screenshots + run: adb pull "/sdcard/screenshots" "screenshots" - name: Upload Reports if: always() uses: actions/upload-artifact@v2 diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 4a237069b..2cb85ccd5 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -28,7 +28,7 @@ public class E2ETest { public void e2e() throws UiObjectNotFoundException { mDevice = UiDevice.getInstance(getInstrumentation()); launch("com.nextcloud.android.beta"); - configureNextcloudAccount("http://localhost:8080", "Test", "Test"); + configureNextcloudAccount("nextcloud.knecht.rocks", "stefan", "stefaniststinkt"); launch("it.niedermann.nextcloud.deck.dev"); importAccountIntoDeck(); From d13b8a7bd4288e80518ed12963e10f28954e485c Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 11:28:54 +0100 Subject: [PATCH 22/61] Try pulling screenshots from runner machine Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 6a7b03b57..ed54d1192 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -53,8 +53,10 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s - ./gradlew connectedDevDebugAndroidTest + ls -all + bash -c 'if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 else adb exec-out screenshots -p >/sdcard/screenshots.png; exit 1 fi' adb pull "/sdcard/screenshots" "screenshots" + ls -all - name: List files run: ls -all - name: Pull screenshots From 628e783853a220b91a8a10aab3a2b144d13ea58b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 11:32:35 +0100 Subject: [PATCH 23/61] Fix test creds Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 2cb85ccd5..4a237069b 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -28,7 +28,7 @@ public class E2ETest { public void e2e() throws UiObjectNotFoundException { mDevice = UiDevice.getInstance(getInstrumentation()); launch("com.nextcloud.android.beta"); - configureNextcloudAccount("nextcloud.knecht.rocks", "stefan", "stefaniststinkt"); + configureNextcloudAccount("http://localhost:8080", "Test", "Test"); launch("it.niedermann.nextcloud.deck.dev"); importAccountIntoDeck(); From 741853c5f38a2ac96062873876c5a9fd8899b0c6 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 12:04:39 +0100 Subject: [PATCH 24/61] Use shell script as own file Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 4 ++-- copy_screenshots.sh | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100755 copy_screenshots.sh diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index ed54d1192..c56f1d5d9 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -54,8 +54,8 @@ jobs: adb install latest.apk sleep 5s ls -all - bash -c 'if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 else adb exec-out screenshots -p >/sdcard/screenshots.png; exit 1 fi' - adb pull "/sdcard/screenshots" "screenshots" + sh copy_screenshots.sh + adb pull /sdcard/screenshots screenshots ls -all - name: List files run: ls -all diff --git a/copy_screenshots.sh b/copy_screenshots.sh new file mode 100755 index 000000000..1db77e3a6 --- /dev/null +++ b/copy_screenshots.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +adb logcat -c +adb logcat *:E -v color & +if ./gradlew connectedDebugAndroidTest; then + echo "connectedDebugAndroidTest succeeded" >&2 +else + adb exec-out screenshots -p >screenshots + exit 1 +fi \ No newline at end of file From 419577224abf5d0a7b59d0dcb488c9b4857c8c0b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 12:11:19 +0100 Subject: [PATCH 25/61] Try another syntax Signed-off-by: Stefan Niedermann --- copy_screenshots.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/copy_screenshots.sh b/copy_screenshots.sh index 1db77e3a6..3ca4ffa66 100755 --- a/copy_screenshots.sh +++ b/copy_screenshots.sh @@ -5,6 +5,7 @@ adb logcat *:E -v color & if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 else - adb exec-out screenshots -p >screenshots + adb pull /sdcard/screenshots screenshots + adb exec-out /sdcard/screenshots -p >screenshots exit 1 fi \ No newline at end of file From f3d6553c41b6eec6ba05589cf2ff57fee690c549 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 12:49:01 +0100 Subject: [PATCH 26/61] More verbose Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 3 +++ copy_screenshots.sh | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index c56f1d5d9..291bb062f 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -53,11 +53,14 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s + echo "ls -all (0)" ls -all sh copy_screenshots.sh adb pull /sdcard/screenshots screenshots + echo "ls -all (3)" ls -all - name: List files + echo "ls -all (4)" run: ls -all - name: Pull screenshots run: adb pull "/sdcard/screenshots" "screenshots" diff --git a/copy_screenshots.sh b/copy_screenshots.sh index 3ca4ffa66..baf49f819 100755 --- a/copy_screenshots.sh +++ b/copy_screenshots.sh @@ -4,8 +4,23 @@ adb logcat -c adb logcat *:E -v color & if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 + echo "ls -all (1)" + ls -all + adb pull /sdcard/screenshots screenshots + echo "ls -all (1.1)" + ls -all + adb exec-out /sdcard/screenshots -p >screenshots + echo "ls -all (1.2)" + ls -all + exit 0 else + echo "ls -all (2)" + ls -all adb pull /sdcard/screenshots screenshots + echo "ls -all (2.1)" + ls -all adb exec-out /sdcard/screenshots -p >screenshots + echo "ls -all (2.2)" + ls -all exit 1 fi \ No newline at end of file From 7bad0ca60b07555e4518381639c29e85ed327a80 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 12:49:36 +0100 Subject: [PATCH 27/61] Fix yml syntax Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 291bb062f..b4ba376ad 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -60,8 +60,9 @@ jobs: echo "ls -all (3)" ls -all - name: List files - echo "ls -all (4)" - run: ls -all + run: | + echo "ls -all (4)" + ls -all - name: Pull screenshots run: adb pull "/sdcard/screenshots" "screenshots" - name: Upload Reports From dbbaa52945031dbae06cca8d0cc25ee9e90218c4 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 13:16:43 +0100 Subject: [PATCH 28/61] Upload screenshots folder Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index b4ba376ad..b1392ecd5 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -71,9 +71,9 @@ jobs: with: name: Test-Reports path: app/build/reports - - name: Store screenshots + - name: Upload screenshots if: always() uses: actions/upload-artifact@v2 with: - name: stuff - path: . \ No newline at end of file + name: Screenshots + path: screenshots \ No newline at end of file From 30dd49f6b90e6c73a06ddbc48b92d5d3ae0d5165 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 13:17:56 +0100 Subject: [PATCH 29/61] Upload screenshots folder Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index b1392ecd5..8d6826bb1 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -53,17 +53,9 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s - echo "ls -all (0)" - ls -all sh copy_screenshots.sh - adb pull /sdcard/screenshots screenshots - echo "ls -all (3)" - ls -all - - name: List files - run: | - echo "ls -all (4)" - ls -all - name: Pull screenshots + if: always() run: adb pull "/sdcard/screenshots" "screenshots" - name: Upload Reports if: always() From f715c107dc6203a78ffa3257365fb55f50841fca Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 13:42:40 +0100 Subject: [PATCH 30/61] adb ls Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 3 --- copy_screenshots.sh | 6 ++++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 8d6826bb1..4c0dbed01 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -54,9 +54,6 @@ jobs: adb install latest.apk sleep 5s sh copy_screenshots.sh - - name: Pull screenshots - if: always() - run: adb pull "/sdcard/screenshots" "screenshots" - name: Upload Reports if: always() uses: actions/upload-artifact@v2 diff --git a/copy_screenshots.sh b/copy_screenshots.sh index baf49f819..dd7b476c8 100755 --- a/copy_screenshots.sh +++ b/copy_screenshots.sh @@ -4,12 +4,18 @@ adb logcat -c adb logcat *:E -v color & if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 + echo "adb ls -all (1)" + adb shell ls -R / echo "ls -all (1)" ls -all adb pull /sdcard/screenshots screenshots + echo "adb ls -all (1.1)" + adb shell ls -R / echo "ls -all (1.1)" ls -all adb exec-out /sdcard/screenshots -p >screenshots + echo "adb ls -all (1.2)" + adb shell ls -R / echo "ls -all (1.2)" ls -all exit 0 From ea189efadcdba7b3d47ccf57ae4ee5910719d6f1 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 13:43:14 +0100 Subject: [PATCH 31/61] More output Signed-off-by: Stefan Niedermann --- copy_screenshots.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/copy_screenshots.sh b/copy_screenshots.sh index dd7b476c8..87a84019f 100755 --- a/copy_screenshots.sh +++ b/copy_screenshots.sh @@ -6,16 +6,22 @@ if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 echo "adb ls -all (1)" adb shell ls -R / + adb shell ls -R /sdcard/ + adb shell ls -R /sdcard/screenshots echo "ls -all (1)" ls -all adb pull /sdcard/screenshots screenshots echo "adb ls -all (1.1)" adb shell ls -R / + adb shell ls -R /sdcard/ + adb shell ls -R /sdcard/screenshots echo "ls -all (1.1)" ls -all adb exec-out /sdcard/screenshots -p >screenshots echo "adb ls -all (1.2)" adb shell ls -R / + adb shell ls -R /sdcard/ + adb shell ls -R /sdcard/screenshots echo "ls -all (1.2)" ls -all exit 0 From 0f1923b0311df20553c60bfd50e63ce22333727b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Sun, 31 Oct 2021 14:05:51 +0100 Subject: [PATCH 32/61] Do not adb shell ls recursively Signed-off-by: Stefan Niedermann --- copy_screenshots.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/copy_screenshots.sh b/copy_screenshots.sh index 87a84019f..909daa247 100755 --- a/copy_screenshots.sh +++ b/copy_screenshots.sh @@ -5,22 +5,25 @@ adb logcat *:E -v color & if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 echo "adb ls -all (1)" - adb shell ls -R / - adb shell ls -R /sdcard/ - adb shell ls -R /sdcard/screenshots + adb shell ls / + adb shell ls /mnt/ + adb shell ls /mnt/sdcard + adb shell ls -R /mnt/sdcard/screenshots echo "ls -all (1)" ls -all adb pull /sdcard/screenshots screenshots echo "adb ls -all (1.1)" - adb shell ls -R / - adb shell ls -R /sdcard/ + adb shell ls / + adb shell ls /mnt/ + adb shell ls /mnt/sdcard adb shell ls -R /sdcard/screenshots echo "ls -all (1.1)" ls -all adb exec-out /sdcard/screenshots -p >screenshots echo "adb ls -all (1.2)" - adb shell ls -R / - adb shell ls -R /sdcard/ + adb shell ls / + adb shell ls /mnt/ + adb shell ls /mnt/sdcard adb shell ls -R /sdcard/screenshots echo "ls -all (1.2)" ls -all From 3ba3ee54a6f18c00a2bfe05a128a09b1e4fc19b3 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:17:59 +0100 Subject: [PATCH 33/61] Refactor e2e test Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 20 ++++-- .../niedermann/nextcloud/deck/ui/E2ETest.java | 69 ++++++++++++++----- copy_screenshots.sh | 2 - 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 4c0dbed01..b45ecd7b7 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -53,16 +53,22 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s - sh copy_screenshots.sh + adb logcat -c + adb logcat *:V -v color & + adb logcat *:D -v color & + adb logcat *:I -v color & + adb logcat *:W -v color & + adb logcat *:E -v color & + ./gradlew connectedDebugAndroidTest || true - name: Upload Reports if: always() uses: actions/upload-artifact@v2 with: name: Test-Reports path: app/build/reports - - name: Upload screenshots - if: always() - uses: actions/upload-artifact@v2 - with: - name: Screenshots - path: screenshots \ No newline at end of file + #- name: Upload screenshots + # if: always() + # uses: actions/upload-artifact@v2 + # with: + # name: Screenshots + # path: screenshots \ No newline at end of file diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 4a237069b..1d93b5cce 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -3,6 +3,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import android.content.Intent; +import android.util.Log; import android.webkit.WebView; import android.widget.Button; import android.widget.EditText; @@ -16,34 +17,49 @@ import com.google.android.material.card.MaterialCardView; +import org.junit.After; +import org.junit.Before; +import org.junit.FixMethodOrder; import org.junit.Test; +import org.junit.runners.MethodSorters; import java.io.File; +import java.io.IOException; +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class E2ETest { private UiDevice mDevice; - @Test - public void e2e() throws UiObjectNotFoundException { - mDevice = UiDevice.getInstance(getInstrumentation()); - launch("com.nextcloud.android.beta"); - configureNextcloudAccount("http://localhost:8080", "Test", "Test"); + private static final String TAG = E2ETest.class.getSimpleName(); + private static final String APP_NEXTCLOUD = "com.nextcloud.android.beta"; + private static final String APP_DECK = "it.niedermann.nextcloud.deck.dev"; + private static final String SERVER_URL = "http://localhost:8080"; + private static final String SERVER_USERNAME = "Test"; + private static final String SERVER_PASSWORD = "Test"; - launch("it.niedermann.nextcloud.deck.dev"); - importAccountIntoDeck(); + @Before + public void before() { + mDevice = UiDevice.getInstance(getInstrumentation()); + } - verifyCardsPresent(); + @After + public void after() { + mDevice.pressHome(); } + @Test + public void test_00_configureNextcloudAccount() throws UiObjectNotFoundException, IOException, InterruptedException { + Log.i(TAG, "START test_00_configureNextcloudAccount"); + + launch(APP_NEXTCLOUD); - private void configureNextcloudAccount(String url, String username, String password) throws UiObjectNotFoundException { final var loginButton1 = mDevice.findObject(new UiSelector().text("Log in")); loginButton1.waitForExists(30); screenshot("setup-2"); loginButton1.click(); - mDevice.findObject(new UiSelector().focused(true)).setText(url); + mDevice.findObject(new UiSelector().focused(true)).setText(SERVER_URL); screenshot("setup-3"); mDevice.pressEnter(); screenshot("setup-4"); @@ -58,7 +74,7 @@ private void configureNextcloudAccount(String url, String username, String passw usernameInput.waitForExists(30); screenshot("setup-6"); - usernameInput.setText(username); + usernameInput.setText(SERVER_USERNAME); final var passwordInput = mDevice.findObject(new UiSelector() .instance(1) @@ -66,16 +82,22 @@ private void configureNextcloudAccount(String url, String username, String passw passwordInput.waitForExists(30); screenshot("setup-7"); - passwordInput.setText(password); + passwordInput.setText(SERVER_PASSWORD); mDevice.findObject(new UiSelector().text("Log in")).click(); screenshot("setup-8"); mDevice.findObject(new UiSelector().text("Grant access")).click(); screenshot("setup-9"); + + Log.i(TAG, "END test_00_configureNextcloudAccount"); } - private void importAccountIntoDeck() throws UiObjectNotFoundException { + @Test + public void test_01_importAccountIntoDeck() throws UiObjectNotFoundException, IOException, InterruptedException { + Log.i(TAG, "START test_01_importAccountIntoDeck"); + launch(APP_DECK); + final var accountButton = mDevice.findObject(new UiSelector() .instance(0) .className(Button.class)); @@ -107,18 +129,26 @@ private void importAccountIntoDeck() throws UiObjectNotFoundException { final var welcomeText = mDevice.findObject(new UiSelector().description("Filter")); welcomeText.waitForExists(30); screenshot("deck-5"); + Log.i(TAG, "END test_01_importAccountIntoDeck"); } - private void verifyCardsPresent() { + @Test + public void test_02_verifyCardsPresent() throws IOException, InterruptedException, UiObjectNotFoundException { + Log.i(TAG, "START test_02_verifyCardsPresent"); + launch(APP_DECK); + final var accountButton = mDevice.findObject(new UiSelector() .instance(0) .className(MaterialCardView.class)); accountButton.waitForExists(30); + Log.i(TAG, accountButton.getText()); screenshot("deck-validate-1"); + Log.i(TAG, "END test_02_verifyCardsPresent"); } - private void launch(@NonNull String packageName) { + private void launch(@NonNull String packageName) throws IOException, InterruptedException { + Log.d(TAG, "... LAUNCH " + packageName); final var context = getInstrumentation().getContext(); context.startActivity(context .getPackageManager() @@ -128,7 +158,12 @@ private void launch(@NonNull String packageName) { screenshot("launch-" + packageName + ".png"); } - private void screenshot(@NonNull String name) { - mDevice.takeScreenshot(new File("/sdcard/screenshots/" + name + ".png")); + private void screenshot(@NonNull String name) throws IOException, InterruptedException { +// Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); + final var p = new File(getInstrumentation().getContext().getFilesDir().getAbsolutePath()); + final var f = new File(getInstrumentation().getContext().getFilesDir() + "/screenshots/" + name + ".png"); + f.createNewFile(); + + System.out.println("Screenshot: " + mDevice.takeScreenshot(f)); } } diff --git a/copy_screenshots.sh b/copy_screenshots.sh index 909daa247..1fdd43e06 100755 --- a/copy_screenshots.sh +++ b/copy_screenshots.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash -adb logcat -c -adb logcat *:E -v color & if ./gradlew connectedDebugAndroidTest; then echo "connectedDebugAndroidTest succeeded" >&2 echo "adb ls -all (1)" From b35e3787808546b092f95502887b002d1fe216c4 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:23:01 +0100 Subject: [PATCH 34/61] Limit Logcat to info and higher Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 4 ---- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index b45ecd7b7..0a18e6255 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -54,11 +54,7 @@ jobs: adb install latest.apk sleep 5s adb logcat -c - adb logcat *:V -v color & - adb logcat *:D -v color & adb logcat *:I -v color & - adb logcat *:W -v color & - adb logcat *:E -v color & ./gradlew connectedDebugAndroidTest || true - name: Upload Reports if: always() diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 1d93b5cce..3f3ce437e 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -148,7 +148,7 @@ public void test_02_verifyCardsPresent() throws IOException, InterruptedExceptio } private void launch(@NonNull String packageName) throws IOException, InterruptedException { - Log.d(TAG, "... LAUNCH " + packageName); + Log.i(TAG, "... LAUNCH " + packageName); final var context = getInstrumentation().getContext(); context.startActivity(context .getPackageManager() From bfec6ea1ea2834c5b7027ad22d96520a8b9028c5 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:33:35 +0100 Subject: [PATCH 35/61] Try to make usage of AVD caches Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 39 +++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 0a18e6255..72de8f148 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -4,6 +4,9 @@ jobs: setup_nextcloud: runs-on: ubuntu-latest name: Run e2e test + strategy: + matrix: + api-level: [ 24, 27, 29 ] services: nextcloud: image: nextcloud:latest @@ -45,17 +48,49 @@ jobs: run: | curl -v -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' -H 'OCS-APIRequest: true' | jq - - name: Run emulator + - name: Gradle cache + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }} + + - name: AVD cache + uses: actions/cache@v2 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ matrix.api-level }} + + - name: Create AVD and generate snapshot for caching + if: steps.avd-cache.outputs.cache-hit != 'true' uses: reactivecircus/android-emulator-runner@v2 with: - api-level: 29 + api-level: ${{ matrix.api-level }} + force-avd-creation: false + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true + script: echo "Generated AVD snapshot for caching." + + - name: Run e2e tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + force-avd-creation: false + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true script: | + ./gradlew connectedCheck wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 5s adb logcat -c adb logcat *:I -v color & ./gradlew connectedDebugAndroidTest || true + - name: Upload Reports if: always() uses: actions/upload-artifact@v2 From efa326d49f4b350b9f23ae473f14c321fd171e62 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:36:25 +0100 Subject: [PATCH 36/61] Increase matrix multipliers Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 72de8f148..e1ce431de 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -6,10 +6,11 @@ jobs: name: Run e2e test strategy: matrix: - api-level: [ 24, 27, 29 ] + api-level: [ 24, 25, 26, 27, 28, 29 ] + nextcloud-version: [ 'nextcloud:latest', 'nextcloud:stable', 'nextcloud.production' ] services: nextcloud: - image: nextcloud:latest + image: ${{ matrix.nextcloud-version }} env: SQLITE_DATABASE: db.sqlite NEXTCLOUD_ADMIN_USER: Test From 435f3ee3337767cc75fcbdb13cc58d596d90d86e Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:37:26 +0100 Subject: [PATCH 37/61] Fix typo in nextcloud:production image Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index e1ce431de..71e8e701a 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: api-level: [ 24, 25, 26, 27, 28, 29 ] - nextcloud-version: [ 'nextcloud:latest', 'nextcloud:stable', 'nextcloud.production' ] + nextcloud-version: [ 'nextcloud:latest', 'nextcloud:stable', 'nextcloud:production' ] services: nextcloud: image: ${{ matrix.nextcloud-version }} From 8041889eab3a0600281740752dba4b2e84f13247 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:39:04 +0100 Subject: [PATCH 38/61] Make docker filter more generous Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 71e8e701a..a8053576e 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -34,8 +34,8 @@ jobs: - name: Print Container information run: | - docker exec `docker ps -f 'name=_nextcloudlatest_' -l -q` bash -c 'whoami' - docker exec `docker ps -f 'name=_nextcloudlatest_' -l -q` bash -c 'uname -a' + docker exec `docker ps -f 'name=_nextcloud' -l -q` bash -c 'whoami' + docker exec `docker ps -f 'name=_nextcloud' -l -q` bash -c 'uname -a' - name: Enable Deck via Docker Exec run: | From 51ccf6fe1fd35abcce59371a2a7394cfda3d737e Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:40:47 +0100 Subject: [PATCH 39/61] Make docker filter more generous Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index a8053576e..10b933bc3 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -30,7 +30,7 @@ jobs: - name: List running Docker containers run: | docker ps - echo "Current docker container ID: `docker ps -f 'name=_nextcloudlatest_' -l -q`" + echo "Current docker container ID: `docker ps -f 'name=_nextcloud' -l -q`" - name: Print Container information run: | @@ -39,7 +39,7 @@ jobs: - name: Enable Deck via Docker Exec run: | - docker exec `docker ps -f 'name=_nextcloudlatest_' -l -q` bash -c 'runuser -u www-data -- php occ app:install deck' + docker exec `docker ps -f 'name=_nextcloud' -l -q` bash -c 'runuser -u www-data -- php occ app:install deck' - name: Fetch capabilities run: | From c4df12689c80fbe4ba3ace6fe03242375aa98b00 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 16:59:53 +0100 Subject: [PATCH 40/61] Wait longer for Nextcloud app getting installed Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 +- .../it/niedermann/nextcloud/deck/ui/E2ETest.java | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 10b933bc3..3e23f96d2 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -87,7 +87,7 @@ jobs: ./gradlew connectedCheck wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk - sleep 5s + sleep 10s adb logcat -c adb logcat *:I -v color & ./gradlew connectedDebugAndroidTest || true diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 3f3ce437e..27063b986 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -15,8 +15,6 @@ import androidx.test.uiautomator.UiSelector; import androidx.test.uiautomator.Until; -import com.google.android.material.card.MaterialCardView; - import org.junit.After; import org.junit.Before; import org.junit.FixMethodOrder; @@ -32,8 +30,10 @@ public class E2ETest { private UiDevice mDevice; private static final String TAG = E2ETest.class.getSimpleName(); + private static final String APP_NEXTCLOUD = "com.nextcloud.android.beta"; private static final String APP_DECK = "it.niedermann.nextcloud.deck.dev"; + private static final String SERVER_URL = "http://localhost:8080"; private static final String SERVER_USERNAME = "Test"; private static final String SERVER_PASSWORD = "Test"; @@ -138,8 +138,7 @@ public void test_02_verifyCardsPresent() throws IOException, InterruptedExceptio launch(APP_DECK); final var accountButton = mDevice.findObject(new UiSelector() - .instance(0) - .className(MaterialCardView.class)); + .textContains("task")); accountButton.waitForExists(30); Log.i(TAG, accountButton.getText()); @@ -159,11 +158,7 @@ private void launch(@NonNull String packageName) throws IOException, Interrupted } private void screenshot(@NonNull String name) throws IOException, InterruptedException { -// Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); - final var p = new File(getInstrumentation().getContext().getFilesDir().getAbsolutePath()); - final var f = new File(getInstrumentation().getContext().getFilesDir() + "/screenshots/" + name + ".png"); - f.createNewFile(); - - System.out.println("Screenshot: " + mDevice.takeScreenshot(f)); + Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); + mDevice.takeScreenshot(new File(getInstrumentation().getContext().getFilesDir() + "/screenshots/" + name + ".png")); } } From 4f4897280589095a57d4036df9b1925511d3e689 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 17:09:44 +0100 Subject: [PATCH 41/61] Remove copy_screenshots.sh Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 5 ++-- copy_screenshots.sh | 39 ------------------------------- 2 files changed, 2 insertions(+), 42 deletions(-) delete mode 100755 copy_screenshots.sh diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 3e23f96d2..5e3dcee7a 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -43,11 +43,11 @@ jobs: - name: Fetch capabilities run: | - curl -v -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/cloud/capabilities?format=json' -H 'OCS-APIRequest: true' | jq + curl -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/cloud/capabilities?format=json' -H 'OCS-APIRequest: true' | jq - name: Fetch server info run: | - curl -v -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' -H 'OCS-APIRequest: true' | jq + curl -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' -H 'OCS-APIRequest: true' | jq - name: Gradle cache uses: actions/cache@v2 @@ -84,7 +84,6 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true script: | - ./gradlew connectedCheck wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 10s diff --git a/copy_screenshots.sh b/copy_screenshots.sh deleted file mode 100755 index 1fdd43e06..000000000 --- a/copy_screenshots.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -if ./gradlew connectedDebugAndroidTest; then - echo "connectedDebugAndroidTest succeeded" >&2 - echo "adb ls -all (1)" - adb shell ls / - adb shell ls /mnt/ - adb shell ls /mnt/sdcard - adb shell ls -R /mnt/sdcard/screenshots - echo "ls -all (1)" - ls -all - adb pull /sdcard/screenshots screenshots - echo "adb ls -all (1.1)" - adb shell ls / - adb shell ls /mnt/ - adb shell ls /mnt/sdcard - adb shell ls -R /sdcard/screenshots - echo "ls -all (1.1)" - ls -all - adb exec-out /sdcard/screenshots -p >screenshots - echo "adb ls -all (1.2)" - adb shell ls / - adb shell ls /mnt/ - adb shell ls /mnt/sdcard - adb shell ls -R /sdcard/screenshots - echo "ls -all (1.2)" - ls -all - exit 0 -else - echo "ls -all (2)" - ls -all - adb pull /sdcard/screenshots screenshots - echo "ls -all (2.1)" - ls -all - adb exec-out /sdcard/screenshots -p >screenshots - echo "ls -all (2.2)" - ls -all - exit 1 -fi \ No newline at end of file From e84eae87c5564cf56e14f7d7d84bd02a5a2f3899 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Mon, 1 Nov 2021 17:26:35 +0100 Subject: [PATCH 42/61] Do not fail when logcat can not be retrieved Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 5e3dcee7a..5d0cf7f3c 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -87,7 +87,7 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 10s - adb logcat -c + adb logcat -c || true adb logcat *:I -v color & ./gradlew connectedDebugAndroidTest || true From b0994ddc5e4106f820f0539ad72888e71224e8e9 Mon Sep 17 00:00:00 2001 From: Niedermann IT-Dienstleistungen Date: Mon, 1 Nov 2021 22:34:04 +0100 Subject: [PATCH 43/61] Remove installed apps before e2e --- .github/workflows/android-e2e.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 5d0cf7f3c..9fb997a1c 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -84,6 +84,8 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true script: | + adb shell pm uninstall -k --user 0 com.nextcloud.android.beta + adb shell pm uninstall -k --user 0 it.niedermann.nextcloud.deck.dev wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 10s @@ -102,4 +104,4 @@ jobs: # uses: actions/upload-artifact@v2 # with: # name: Screenshots - # path: screenshots \ No newline at end of file + # path: screenshots From 4593dcb20e6bab0b76f99d73340d3d7494fa9d22 Mon Sep 17 00:00:00 2001 From: Niedermann IT-Dienstleistungen Date: Mon, 1 Nov 2021 22:45:18 +0100 Subject: [PATCH 44/61] Allow failing apk removal --- .github/workflows/android-e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 9fb997a1c..dc2c771f7 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -84,8 +84,8 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true script: | - adb shell pm uninstall -k --user 0 com.nextcloud.android.beta - adb shell pm uninstall -k --user 0 it.niedermann.nextcloud.deck.dev + adb shell pm uninstall -k --user 0 com.nextcloud.android.beta || true + adb shell pm uninstall -k --user 0 it.niedermann.nextcloud.deck.dev || true wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 10s From 4eaab54792174dbd19a09e785357df885ffab71c Mon Sep 17 00:00:00 2001 From: Niedermann IT-Dienstleistungen Date: Mon, 1 Nov 2021 23:05:34 +0100 Subject: [PATCH 45/61] Provocate test failure --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 27063b986..efd5d481e 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -138,7 +138,7 @@ public void test_02_verifyCardsPresent() throws IOException, InterruptedExceptio launch(APP_DECK); final var accountButton = mDevice.findObject(new UiSelector() - .textContains("task")); + .textContains("halloween - should fail")); accountButton.waitForExists(30); Log.i(TAG, accountButton.getText()); From 683906fd63202e0a976cc075f44879e353b8900d Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 08:16:02 +0100 Subject: [PATCH 46/61] Watch fail Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 7 +++++ .../niedermann/nextcloud/deck/ui/E2ETest.java | 30 ++++++++++--------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index dc2c771f7..9a92472a9 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -93,6 +93,13 @@ jobs: adb logcat *:I -v color & ./gradlew connectedDebugAndroidTest || true + - name: List files + run: | + ls -all + ls -all app + ls -all app/build + ls -all app/build/reports + - name: Upload Reports if: always() uses: actions/upload-artifact@v2 diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index efd5d481e..38a7dbdf6 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -21,9 +21,6 @@ import org.junit.Test; import org.junit.runners.MethodSorters; -import java.io.File; -import java.io.IOException; - @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class E2ETest { @@ -49,7 +46,7 @@ public void after() { } @Test - public void test_00_configureNextcloudAccount() throws UiObjectNotFoundException, IOException, InterruptedException { + public void test_00_configureNextcloudAccount() throws UiObjectNotFoundException { Log.i(TAG, "START test_00_configureNextcloudAccount"); launch(APP_NEXTCLOUD); @@ -94,7 +91,7 @@ public void test_00_configureNextcloudAccount() throws UiObjectNotFoundException } @Test - public void test_01_importAccountIntoDeck() throws UiObjectNotFoundException, IOException, InterruptedException { + public void test_01_importAccountIntoDeck() throws UiObjectNotFoundException { Log.i(TAG, "START test_01_importAccountIntoDeck"); launch(APP_DECK); @@ -133,20 +130,20 @@ public void test_01_importAccountIntoDeck() throws UiObjectNotFoundException, IO } @Test - public void test_02_verifyCardsPresent() throws IOException, InterruptedException, UiObjectNotFoundException { + public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { Log.i(TAG, "START test_02_verifyCardsPresent"); launch(APP_DECK); - final var accountButton = mDevice.findObject(new UiSelector() - .textContains("halloween - should fail")); + final var taskCard = mDevice.findObject(new UiSelector() + .textContains("t1243")); - accountButton.waitForExists(30); - Log.i(TAG, accountButton.getText()); + taskCard.waitForExists(30); + Log.i(TAG, taskCard.getText()); screenshot("deck-validate-1"); Log.i(TAG, "END test_02_verifyCardsPresent"); } - private void launch(@NonNull String packageName) throws IOException, InterruptedException { + private void launch(@NonNull String packageName) { Log.i(TAG, "... LAUNCH " + packageName); final var context = getInstrumentation().getContext(); context.startActivity(context @@ -157,8 +154,13 @@ private void launch(@NonNull String packageName) throws IOException, Interrupted screenshot("launch-" + packageName + ".png"); } - private void screenshot(@NonNull String name) throws IOException, InterruptedException { - Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); - mDevice.takeScreenshot(new File(getInstrumentation().getContext().getFilesDir() + "/screenshots/" + name + ".png")); + private void screenshot(@NonNull String name) { + try { + Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); + // This throws an exception because the file system is read only. +// mDevice.takeScreenshot(new File(getInstrumentation().getContext().getFilesDir() + "/screenshots/" + name + ".png")); + } catch (Throwable ignored) { + + } } } From 3f3d6ae9356ed6b72dc57a8aa1c0af4fbb0a81dd Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 08:18:02 +0100 Subject: [PATCH 47/61] Try to fix again Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 38a7dbdf6..ab558979c 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -135,7 +135,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("t1243")); + .textContains("task 3")); taskCard.waitForExists(30); Log.i(TAG, taskCard.getText()); From 878cd9e8ad01101292e70f2f0d2ade24e5637f3b Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 08:24:06 +0100 Subject: [PATCH 48/61] Use matrix for unit tests Signed-off-by: Stefan Niedermann --- .github/workflows/android.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index fa6999474..6e735bbae 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -24,11 +24,14 @@ jobs: test: name: Unit tests runs-on: ubuntu-latest + strategy: + matrix: + flavor: [ 'testDevDebugUnitTest', 'testFdroidReleaseUnitTest', 'testPlayReleaseUnitTest' ] steps: - name: Checkout uses: actions/checkout@v2 - name: Unit tests - run: bash ./gradlew test + run: bash ./gradlew ${{ matrix.flavor }} codeql: name: CodeQL security scan From c84b813bca244c591e594e7e42853a9963e5a839 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 08:25:27 +0100 Subject: [PATCH 49/61] Remove ls Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 9a92472a9..e87bf9086 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -93,19 +93,19 @@ jobs: adb logcat *:I -v color & ./gradlew connectedDebugAndroidTest || true - - name: List files - run: | - ls -all - ls -all app - ls -all app/build - ls -all app/build/reports + #- name: List files + # run: | + # ls -all + # ls -all app + # ls -all app/build + # ls -all app/build/reports - - name: Upload Reports - if: always() - uses: actions/upload-artifact@v2 - with: - name: Test-Reports - path: app/build/reports + #- name: Upload Reports + # if: always() + # uses: actions/upload-artifact@v2 + # with: + # name: Test-Reports + # path: app/build/reports #- name: Upload screenshots # if: always() # uses: actions/upload-artifact@v2 From 46a694448f8c46ee990dedc109b965df33683a8c Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 08:55:26 +0100 Subject: [PATCH 50/61] Remove || true to make instrumented tests actually fail Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 +- .../it/niedermann/nextcloud/deck/ui/E2ETest.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index e87bf9086..fbb89bda7 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -91,7 +91,7 @@ jobs: sleep 10s adb logcat -c || true adb logcat *:I -v color & - ./gradlew connectedDebugAndroidTest || true + ./gradlew connectedDebugAndroidTest #- name: List files # run: | diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index ab558979c..a8955461e 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -135,7 +135,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("task 3")); + .textContains("task1234444")); taskCard.waitForExists(30); Log.i(TAG, taskCard.getText()); @@ -155,12 +155,12 @@ private void launch(@NonNull String packageName) { } private void screenshot(@NonNull String name) { - try { - Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); +// try { +// Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); // This throws an exception because the file system is read only. // mDevice.takeScreenshot(new File(getInstrumentation().getContext().getFilesDir() + "/screenshots/" + name + ".png")); - } catch (Throwable ignored) { - - } +// } catch (Throwable ignored) { +// +// } } } From e2ee15c7b00d3e9411ea44ab3ad5dade68814963 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 08:55:39 +0100 Subject: [PATCH 51/61] Restore successful tests Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index a8955461e..eb352a16c 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -135,7 +135,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("task1234444")); + .textContains("Task 3")); taskCard.waitForExists(30); Log.i(TAG, taskCard.getText()); From e59bbc4e0fb3f9495d1480ec9df88645a25d1248 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 09:23:39 +0100 Subject: [PATCH 52/61] [Should fail] Use connectedDevDebugAndroidTest flavor Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 +- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index fbb89bda7..5cb5621f2 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -91,7 +91,7 @@ jobs: sleep 10s adb logcat -c || true adb logcat *:I -v color & - ./gradlew connectedDebugAndroidTest + ./gradlew connectedDevDebugAndroidTest #- name: List files # run: | diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index eb352a16c..859b582f7 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -135,7 +135,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Task 3")); + .textContains("Taask 3")); taskCard.waitForExists(30); Log.i(TAG, taskCard.getText()); From f52b9c21eede2a763406697e53b63645e8805ca6 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 09:23:52 +0100 Subject: [PATCH 53/61] [Should success] Use connectedDevDebugAndroidTest flavor Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 859b582f7..eb352a16c 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -135,7 +135,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Taask 3")); + .textContains("Task 3")); taskCard.waitForExists(30); Log.i(TAG, taskCard.getText()); From 2bf499339e285141d908e84f4b7e5ad0ffee883f Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 09:29:07 +0100 Subject: [PATCH 54/61] Remove screenshots Signed-off-by: Stefan Niedermann --- .../niedermann/nextcloud/deck/ui/E2ETest.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index eb352a16c..802de9c16 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -53,24 +53,19 @@ public void test_00_configureNextcloudAccount() throws UiObjectNotFoundException final var loginButton1 = mDevice.findObject(new UiSelector().text("Log in")); loginButton1.waitForExists(30); - screenshot("setup-2"); loginButton1.click(); mDevice.findObject(new UiSelector().focused(true)).setText(SERVER_URL); - screenshot("setup-3"); mDevice.pressEnter(); - screenshot("setup-4"); mDevice.findObject(new UiSelector().text("Log in")).click(); mDevice.wait(Until.findObject(By.clazz(WebView.class)), 30); - screenshot("setup-5"); final var usernameInput = mDevice.findObject(new UiSelector() .instance(0) .className(EditText.class)); usernameInput.waitForExists(30); - screenshot("setup-6"); usernameInput.setText(SERVER_USERNAME); final var passwordInput = mDevice.findObject(new UiSelector() @@ -78,14 +73,11 @@ public void test_00_configureNextcloudAccount() throws UiObjectNotFoundException .className(EditText.class)); passwordInput.waitForExists(30); - screenshot("setup-7"); passwordInput.setText(SERVER_PASSWORD); mDevice.findObject(new UiSelector().text("Log in")).click(); - screenshot("setup-8"); mDevice.findObject(new UiSelector().text("Grant access")).click(); - screenshot("setup-9"); Log.i(TAG, "END test_00_configureNextcloudAccount"); } @@ -100,7 +92,6 @@ public void test_01_importAccountIntoDeck() throws UiObjectNotFoundException { .className(Button.class)); accountButton.waitForExists(30); - screenshot("deck-1"); accountButton.click(); final var radioAccount = mDevice.findObject(new UiSelector() @@ -108,24 +99,20 @@ public void test_01_importAccountIntoDeck() throws UiObjectNotFoundException { .instance(0)); radioAccount.waitForExists(30); - screenshot("deck-2"); radioAccount.click(); final var okButton = mDevice.findObject(new UiSelector().text("OK")); okButton.waitForExists(30); - screenshot("deck-3"); okButton.click(); final var allowButton = mDevice.findObject(new UiSelector().text("Allow")); allowButton.waitForExists(30); - screenshot("deck-4"); allowButton.click(); final var welcomeText = mDevice.findObject(new UiSelector().description("Filter")); welcomeText.waitForExists(30); - screenshot("deck-5"); Log.i(TAG, "END test_01_importAccountIntoDeck"); } @@ -139,7 +126,6 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { taskCard.waitForExists(30); Log.i(TAG, taskCard.getText()); - screenshot("deck-validate-1"); Log.i(TAG, "END test_02_verifyCardsPresent"); } @@ -151,16 +137,5 @@ private void launch(@NonNull String packageName) { .getLaunchIntentForPackage(packageName) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)); mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), 30); - screenshot("launch-" + packageName + ".png"); - } - - private void screenshot(@NonNull String name) { -// try { -// Runtime.getRuntime().exec("screencap -p " + "/sdcard/screenshots" + name).waitFor(); - // This throws an exception because the file system is read only. -// mDevice.takeScreenshot(new File(getInstrumentation().getContext().getFilesDir() + "/screenshots/" + name + ".png")); -// } catch (Throwable ignored) { -// -// } } } From c2906cfa6c0b89c842239f65135616bf8de04cba Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 09:41:47 +0100 Subject: [PATCH 55/61] [Should fail] Refactoring Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 42 +++------------ .../niedermann/nextcloud/deck/ui/E2ETest.java | 51 ++++++------------- 2 files changed, 24 insertions(+), 69 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 5cb5621f2..593244f60 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -27,16 +27,6 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: List running Docker containers - run: | - docker ps - echo "Current docker container ID: `docker ps -f 'name=_nextcloud' -l -q`" - - - name: Print Container information - run: | - docker exec `docker ps -f 'name=_nextcloud' -l -q` bash -c 'whoami' - docker exec `docker ps -f 'name=_nextcloud' -l -q` bash -c 'uname -a' - - name: Enable Deck via Docker Exec run: | docker exec `docker ps -f 'name=_nextcloud' -l -q` bash -c 'runuser -u www-data -- php occ app:install deck' @@ -45,9 +35,9 @@ jobs: run: | curl -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/cloud/capabilities?format=json' -H 'OCS-APIRequest: true' | jq - - name: Fetch server info - run: | - curl -X GET 'http://Test:Test@localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info?format=json' -H 'OCS-APIRequest: true' | jq + ########################## + # AVD CACHING START # + ########################## - name: Gradle cache uses: actions/cache@v2 @@ -76,6 +66,10 @@ jobs: disable-animations: true script: echo "Generated AVD snapshot for caching." + ########################## + # AVD CACHING END # + ########################## + - name: Run e2e tests uses: reactivecircus/android-emulator-runner@v2 with: @@ -91,24 +85,4 @@ jobs: sleep 10s adb logcat -c || true adb logcat *:I -v color & - ./gradlew connectedDevDebugAndroidTest - - #- name: List files - # run: | - # ls -all - # ls -all app - # ls -all app/build - # ls -all app/build/reports - - #- name: Upload Reports - # if: always() - # uses: actions/upload-artifact@v2 - # with: - # name: Test-Reports - # path: app/build/reports - #- name: Upload screenshots - # if: always() - # uses: actions/upload-artifact@v2 - # with: - # name: Screenshots - # path: screenshots + ./gradlew connectedDevDebugAndroidTest \ No newline at end of file diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 802de9c16..ca200baa5 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -3,7 +3,6 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import android.content.Intent; -import android.util.Log; import android.webkit.WebView; import android.widget.Button; import android.widget.EditText; @@ -26,7 +25,7 @@ public class E2ETest { private UiDevice mDevice; - private static final String TAG = E2ETest.class.getSimpleName(); + private static final int TIMEOUT = 30_000; private static final String APP_NEXTCLOUD = "com.nextcloud.android.beta"; private static final String APP_DECK = "it.niedermann.nextcloud.deck.dev"; @@ -47,95 +46,77 @@ public void after() { @Test public void test_00_configureNextcloudAccount() throws UiObjectNotFoundException { - Log.i(TAG, "START test_00_configureNextcloudAccount"); - launch(APP_NEXTCLOUD); - final var loginButton1 = mDevice.findObject(new UiSelector().text("Log in")); - loginButton1.waitForExists(30); - loginButton1.click(); + final var loginButton = mDevice.findObject(new UiSelector().text("Log in")); + loginButton.waitForExists(TIMEOUT); + loginButton.click(); mDevice.findObject(new UiSelector().focused(true)).setText(SERVER_URL); mDevice.pressEnter(); mDevice.findObject(new UiSelector().text("Log in")).click(); - - mDevice.wait(Until.findObject(By.clazz(WebView.class)), 30); + mDevice.wait(Until.findObject(By.clazz(WebView.class)), TIMEOUT); final var usernameInput = mDevice.findObject(new UiSelector() .instance(0) .className(EditText.class)); - - usernameInput.waitForExists(30); + usernameInput.waitForExists(TIMEOUT); usernameInput.setText(SERVER_USERNAME); final var passwordInput = mDevice.findObject(new UiSelector() .instance(1) .className(EditText.class)); - - passwordInput.waitForExists(30); + passwordInput.waitForExists(TIMEOUT); passwordInput.setText(SERVER_PASSWORD); mDevice.findObject(new UiSelector().text("Log in")).click(); - mDevice.findObject(new UiSelector().text("Grant access")).click(); - - Log.i(TAG, "END test_00_configureNextcloudAccount"); } @Test public void test_01_importAccountIntoDeck() throws UiObjectNotFoundException { - Log.i(TAG, "START test_01_importAccountIntoDeck"); launch(APP_DECK); final var accountButton = mDevice.findObject(new UiSelector() .instance(0) .className(Button.class)); - - accountButton.waitForExists(30); + accountButton.waitForExists(TIMEOUT); accountButton.click(); final var radioAccount = mDevice.findObject(new UiSelector() .clickable(true) .instance(0)); - - radioAccount.waitForExists(30); + radioAccount.waitForExists(TIMEOUT); radioAccount.click(); final var okButton = mDevice.findObject(new UiSelector().text("OK")); - - okButton.waitForExists(30); + okButton.waitForExists(TIMEOUT); okButton.click(); final var allowButton = mDevice.findObject(new UiSelector().text("Allow")); - - allowButton.waitForExists(30); + allowButton.waitForExists(TIMEOUT); allowButton.click(); final var welcomeText = mDevice.findObject(new UiSelector().description("Filter")); - welcomeText.waitForExists(30); - Log.i(TAG, "END test_01_importAccountIntoDeck"); + welcomeText.waitForExists(TIMEOUT); } @Test public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { - Log.i(TAG, "START test_02_verifyCardsPresent"); launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Task 3")); - - taskCard.waitForExists(30); - Log.i(TAG, taskCard.getText()); - Log.i(TAG, "END test_02_verifyCardsPresent"); + .textContains("Taask 3")); + taskCard.waitForExists(TIMEOUT); + System.out.println("Found: " + taskCard.getText()); } private void launch(@NonNull String packageName) { - Log.i(TAG, "... LAUNCH " + packageName); final var context = getInstrumentation().getContext(); context.startActivity(context .getPackageManager() .getLaunchIntentForPackage(packageName) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)); - mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), 30); + mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), TIMEOUT); } } From 9dec888d76f4ad1bf14c33e7cc55d43059f203e8 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 09:42:04 +0100 Subject: [PATCH 56/61] [Should success] Refactoring Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index ca200baa5..141fb1e88 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -106,7 +106,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Taask 3")); + .textContains("Task 3")); taskCard.waitForExists(TIMEOUT); System.out.println("Found: " + taskCard.getText()); } From 2f74d85c3c48b888090428a203ccfa4bbe538b3f Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 10:02:40 +0100 Subject: [PATCH 57/61] [Should fail] Clean up Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 2 -- app/build.gradle | 4 +--- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- .../niedermann/nextcloud/deck/ui/ImportAccountActivity.java | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 593244f60..812343d8e 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -83,6 +83,4 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 10s - adb logcat -c || true - adb logcat *:I -v color & ./gradlew connectedDevDebugAndroidTest \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index d47922663..34ab56407 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,7 +66,6 @@ dependencies { implementation project(path: ':cross-tab-drag-and-drop') // TabLayoutHelper implementation project(path: ':tab-layout-helper') - implementation 'androidx.test.ext:junit:1.1.3' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' @@ -128,8 +127,7 @@ dependencies { testImplementation 'androidx.test:core:1.4.0' testImplementation 'androidx.arch.core:core-testing:2.1.0' + // Instrumented tests androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test:rules:1.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' } diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 141fb1e88..3227ae2f1 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -106,7 +106,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Task 3")); + .textContains("Tasak 3")); taskCard.waitForExists(TIMEOUT); System.out.println("Found: " + taskCard.getText()); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java index 6107f9f09..7910c55de 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java @@ -48,7 +48,7 @@ public class ImportAccountActivity extends AppCompatActivity { private String sharedPreferenceLastAccount; private String urlFragmentUpdateDeck; - protected ActivityImportAccountBinding binding; + private ActivityImportAccountBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { From 1f177c308b8bff5973e6b253f501b42ce0e08d68 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 10:02:48 +0100 Subject: [PATCH 58/61] [Should success] Clean up Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 3227ae2f1..141fb1e88 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -106,7 +106,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Tasak 3")); + .textContains("Task 3")); taskCard.waitForExists(TIMEOUT); System.out.println("Found: " + taskCard.getText()); } From 9b192c0dbf45d1bfc4957c056c82af18860e3238 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 10:25:56 +0100 Subject: [PATCH 59/61] [Should fail] Readd adb logcat -c Signed-off-by: Stefan Niedermann --- .github/workflows/android-e2e.yml | 1 + .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-e2e.yml b/.github/workflows/android-e2e.yml index 812343d8e..c99314327 100644 --- a/.github/workflows/android-e2e.yml +++ b/.github/workflows/android-e2e.yml @@ -83,4 +83,5 @@ jobs: wget -q https://download.nextcloud.com/android/dev/latest.apk adb install latest.apk sleep 10s + adb logcat -c || true ./gradlew connectedDevDebugAndroidTest \ No newline at end of file diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 141fb1e88..ca200baa5 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -106,7 +106,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Task 3")); + .textContains("Taask 3")); taskCard.waitForExists(TIMEOUT); System.out.println("Found: " + taskCard.getText()); } From 4465cfc7dd3b5d7b95da20f5699dc68281d92fe8 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 10:26:03 +0100 Subject: [PATCH 60/61] [Should success] Readd adb logcat -c Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index ca200baa5..141fb1e88 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -106,7 +106,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Taask 3")); + .textContains("Task 3")); taskCard.waitForExists(TIMEOUT); System.out.println("Found: " + taskCard.getText()); } From b7d1aab5ef52dfc4725216fe2038823e1f176e72 Mon Sep 17 00:00:00 2001 From: Stefan Niedermann Date: Tue, 2 Nov 2021 10:26:12 +0100 Subject: [PATCH 61/61] [Should fail] Readd adb logcat -c Signed-off-by: Stefan Niedermann --- .../java/it/niedermann/nextcloud/deck/ui/E2ETest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java index 141fb1e88..ca200baa5 100644 --- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java +++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/ui/E2ETest.java @@ -106,7 +106,7 @@ public void test_02_verifyCardsPresent() throws UiObjectNotFoundException { launch(APP_DECK); final var taskCard = mDevice.findObject(new UiSelector() - .textContains("Task 3")); + .textContains("Taask 3")); taskCard.waitForExists(TIMEOUT); System.out.println("Found: " + taskCard.getText()); }