diff --git a/build.gradle b/build.gradle index 708fc12de4a6..c919269c046e 100644 --- a/build.gradle +++ b/build.gradle @@ -368,6 +368,8 @@ dependencies { testImplementation 'org.json:json:20200518' testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0" testImplementation "androidx.arch.core:core-testing:2.1.0" + kaptAndroidTest "com.google.dagger:dagger-compiler:$daggerVersion" + kaptTest "com.google.dagger:dagger-compiler:$daggerVersion" // dependencies for instrumented tests // JUnit4 Rules diff --git a/screenshots/gplay/debug/com.nextcloud.client.ActivitiesActivityIT_open.png b/screenshots/gplay/debug/com.nextcloud.client.ActivitiesActivityIT_open.png new file mode 100644 index 000000000000..41fde67158f2 Binary files /dev/null and b/screenshots/gplay/debug/com.nextcloud.client.ActivitiesActivityIT_open.png differ diff --git a/screenshots/gplay/debug/com.nextcloud.client.ActivitiesActivityIT_openDrawer.png b/screenshots/gplay/debug/com.nextcloud.client.ActivitiesActivityIT_openDrawer.png index 908f1e3aa15e..18e6f14bfaff 100644 Binary files a/screenshots/gplay/debug/com.nextcloud.client.ActivitiesActivityIT_openDrawer.png and b/screenshots/gplay/debug/com.nextcloud.client.ActivitiesActivityIT_openDrawer.png differ diff --git a/scripts/updateScreenshots.sh b/scripts/updateScreenshots.sh index cb261bc626bd..001a6f9396f7 100755 --- a/scripts/updateScreenshots.sh +++ b/scripts/updateScreenshots.sh @@ -74,7 +74,7 @@ sed -i s'#false#true#'g ## update/create all screenshots #./gradlew gplayDebugExecuteScreenshotTests -Precord \ -#-Pandroid.testInstrumentationRunnerArguments.annotation=com.owncloud.android.utils.ScreenshotTest +#-Pandroid.testInstrumentationRunnerArguments.annotation=com.owncloud.android.utils.ScreenshotOnServerTest ## update screenshots in a class #./gradlew gplayDebugExecuteScreenshotTests \ @@ -94,7 +94,7 @@ until [ $resultCode -eq 0 ] || [ $retryCount -gt 2 ] do # test all screenshots ./gradlew gplayDebugExecuteScreenshotTests \ - -Pandroid.testInstrumentationRunnerArguments.annotation=com.owncloud.android.utils.ScreenshotTest + -Pandroid.testInstrumentationRunnerArguments.annotation=com.owncloud.android.utils.ScreenshotOnServerTest resultCode=$? ((retryCount++)) diff --git a/scripts/updateScreenshotsWithoutServer.sh b/scripts/updateScreenshotsWithoutServer.sh new file mode 100755 index 000000000000..2eb539b9792e --- /dev/null +++ b/scripts/updateScreenshotsWithoutServer.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +## emulator +if [[ ! $(emulator -list-avds | grep uiComparison -c) -eq 0 ]]; then + avdmanager delete avd -n uiComparison + (sleep 5; echo "no") | avdmanager create avd -n uiComparison -c 100M -k "system-images;android-27;google_apis;x86" --abi "google_apis/x86" +fi + +if [ "$1" == "debug" ]; then + emulator -writable-system -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-audio -skin 500x833 1>/dev/null & +else + emulator -writable-system -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-window -no-audio -skin 500x833 1>/dev/null & +fi +PID=$! + +scripts/wait_for_emulator.sh + +sed -i s'#false#true#'g src/main/res/values/setup.xml + +## update/create all screenshots +#./gradlew gplayDebugExecuteScreenshotTests -Precord \ +#-Pandroid.testInstrumentationRunnerArguments.annotation=com.owncloud.android.utils.ScreenshotWithoutServerTest + +## update screenshots in a class +#./gradlew gplayDebugExecuteScreenshotTests \ +#-Precord \ +#-Pandroid.testInstrumentationRunnerArguments.class=\ +#com.owncloud.android.ui.dialog.SyncFileNotEnoughSpaceDialogFragmentTest + +## update single screenshot within a class +#./gradlew gplayDebugExecuteScreenshotTests \ +#-Precord \ +#-Pandroid.testInstrumentationRunnerArguments.class=\ +#com.nextcloud.client.FileDisplayActivityIT#showShares + +resultCode=-1 +retryCount=0 +until [ $resultCode -eq 0 ] || [ $retryCount -gt 2 ] +do + # test all screenshots + ./gradlew gplayDebugRemoveScreenshots + ./gradlew gplayDebugExecuteScreenshotTests \ + -Precord \ + -Pandroid.testInstrumentationRunnerArguments.annotation=com.owncloud.android.utils.ScreenshotWithoutServerTest + +resultCode=$? +((retryCount++)) +done + +sed -i s'#true#false#'g src/main/res/values/setup.xml + +if [ "$1" == "debug" ]; then + exit +fi + +# tidy up +kill "$PID" diff --git a/src/androidTest/AndroidManifest.xml b/src/androidTest/AndroidManifest.xml index f22349d38f21..333f14844f4b 100644 --- a/src/androidTest/AndroidManifest.xml +++ b/src/androidTest/AndroidManifest.xml @@ -31,4 +31,6 @@ android:sharedUserId="${applicationId}.uid"> + + diff --git a/src/androidTest/java/com/nextcloud/client/ActivitiesActivityIT.java b/src/androidTest/java/com/nextcloud/client/ActivitiesActivityIT.java index ed2c4495e71a..d7c87058fa51 100644 --- a/src/androidTest/java/com/nextcloud/client/ActivitiesActivityIT.java +++ b/src/androidTest/java/com/nextcloud/client/ActivitiesActivityIT.java @@ -23,13 +23,13 @@ package com.nextcloud.client; import android.Manifest; -import android.view.View; import com.facebook.testing.screenshot.Screenshot; import com.owncloud.android.AbstractIT; import com.owncloud.android.R; import com.owncloud.android.ui.activities.ActivitiesActivity; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithoutServerTest; import org.junit.Rule; import org.junit.Test; @@ -52,6 +52,18 @@ public class ActivitiesActivityIT extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithoutServerTest + @ScreenshotTest + public void open() { + ActivitiesActivity sut = activityRule.launchActivity(null); + + shortSleep(); + + Screenshot.snapActivity(sut).record(); + } + + @Test + @ScreenshotWithoutServerTest @ScreenshotTest public void openDrawer() { ActivitiesActivity sut = activityRule.launchActivity(null); @@ -60,15 +72,7 @@ public void openDrawer() { onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()); - sut.runOnUiThread(new Runnable() { - @Override - public void run() { - sut.emptyContentContainer.setVisibility(View.VISIBLE); - sut.recyclerView.setVisibility(View.INVISIBLE); - } - }); - - waitForIdleSync(); + shortSleep(); Screenshot.snapActivity(sut).record(); } diff --git a/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java b/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java index 77a73262cd21..d1371cc943d4 100644 --- a/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java +++ b/src/androidTest/java/com/nextcloud/client/FileDisplayActivityIT.java @@ -39,6 +39,7 @@ import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.events.SearchEvent; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithServerTest; import org.greenrobot.eventbus.EventBus; import org.junit.Assert; @@ -66,6 +67,7 @@ public class FileDisplayActivityIT extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithServerTest @ScreenshotTest public void open() { Activity sut = activityRule.launchActivity(null); @@ -76,6 +78,7 @@ public void open() { } @Test + @ScreenshotWithServerTest @ScreenshotTest public void drawer() { FileDisplayActivity sut = activityRule.launchActivity(null); @@ -90,6 +93,7 @@ public void drawer() { } @Test + @ScreenshotWithServerTest @ScreenshotTest public void showShares() { assertTrue(new ExistenceCheckRemoteOperation("/shareToAdmin/", true).execute(client).isSuccess()); diff --git a/src/androidTest/java/com/nextcloud/client/FirstRunActivityIT.java b/src/androidTest/java/com/nextcloud/client/FirstRunActivityIT.java index c28cc56fa347..6c0821d33383 100644 --- a/src/androidTest/java/com/nextcloud/client/FirstRunActivityIT.java +++ b/src/androidTest/java/com/nextcloud/client/FirstRunActivityIT.java @@ -29,6 +29,7 @@ import com.nextcloud.client.onboarding.FirstRunActivity; import com.owncloud.android.AbstractIT; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithServerTest; import org.junit.Rule; import org.junit.Test; @@ -47,6 +48,7 @@ public class FirstRunActivityIT extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithServerTest @ScreenshotTest public void open() { Activity sut = activityRule.launchActivity(null); diff --git a/src/androidTest/java/com/nextcloud/client/NotificationsActivityIT.java b/src/androidTest/java/com/nextcloud/client/NotificationsActivityIT.java index f4ba1bc39e8d..b98cae12c26e 100644 --- a/src/androidTest/java/com/nextcloud/client/NotificationsActivityIT.java +++ b/src/androidTest/java/com/nextcloud/client/NotificationsActivityIT.java @@ -27,6 +27,7 @@ import com.owncloud.android.AbstractIT; import com.owncloud.android.ui.activity.NotificationsActivity; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithServerTest; import org.junit.Rule; import org.junit.Test; @@ -45,6 +46,7 @@ public class NotificationsActivityIT extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithServerTest @ScreenshotTest public void openDrawer() { super.openDrawer(activityRule); diff --git a/src/androidTest/java/com/nextcloud/client/ScreenshotTestRunner.java b/src/androidTest/java/com/nextcloud/client/ScreenshotTestRunner.java index 1b88f899e1e4..80ea007ec655 100644 --- a/src/androidTest/java/com/nextcloud/client/ScreenshotTestRunner.java +++ b/src/androidTest/java/com/nextcloud/client/ScreenshotTestRunner.java @@ -22,14 +22,25 @@ package com.nextcloud.client; +import android.app.Application; +import android.content.Context; import android.os.Bundle; import com.facebook.testing.screenshot.ScreenshotRunner; +import com.owncloud.android.TestApp; import androidx.test.runner.AndroidJUnitRunner; public class ScreenshotTestRunner extends AndroidJUnitRunner { + @Override + public Application newApplication(ClassLoader cl, String className, Context context) + throws ClassNotFoundException, + IllegalAccessException, + InstantiationException { + return super.newApplication(cl, TestApp.class.getName(), context); + } + @Override public void onCreate(Bundle args) { super.onCreate(args); diff --git a/src/androidTest/java/com/nextcloud/client/SettingsActivityIT.java b/src/androidTest/java/com/nextcloud/client/SettingsActivityIT.java index b850f81339b1..c73ab5d24f7f 100644 --- a/src/androidTest/java/com/nextcloud/client/SettingsActivityIT.java +++ b/src/androidTest/java/com/nextcloud/client/SettingsActivityIT.java @@ -29,6 +29,7 @@ import com.owncloud.android.AbstractIT; import com.owncloud.android.ui.activity.SettingsActivity; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithoutServerTest; import org.junit.Rule; import org.junit.Test; @@ -47,6 +48,7 @@ public class SettingsActivityIT extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithoutServerTest @ScreenshotTest public void open() { Activity test = activityRule.launchActivity(null); diff --git a/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java b/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java index 122ee1830a86..a44c074afaa3 100644 --- a/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java +++ b/src/androidTest/java/com/nextcloud/client/SyncedFoldersActivityIT.java @@ -26,7 +26,7 @@ import com.owncloud.android.AbstractIT; import com.owncloud.android.ui.activity.SyncedFoldersActivity; -import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithServerTest; import org.junit.Rule; import org.junit.Test; @@ -45,6 +45,7 @@ public class SyncedFoldersActivityIT extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithServerTest @ScreenshotTest public void openDrawer() { super.openDrawer(activityRule); diff --git a/src/androidTest/java/com/nextcloud/client/UploadListActivityActivityIT.java b/src/androidTest/java/com/nextcloud/client/UploadListActivityActivityIT.java index 7d210278f353..66975bee10e1 100644 --- a/src/androidTest/java/com/nextcloud/client/UploadListActivityActivityIT.java +++ b/src/androidTest/java/com/nextcloud/client/UploadListActivityActivityIT.java @@ -27,6 +27,7 @@ import com.owncloud.android.AbstractIT; import com.owncloud.android.ui.activity.UploadListActivity; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithServerTest; import org.junit.Rule; import org.junit.Test; @@ -45,6 +46,7 @@ public class UploadListActivityActivityIT extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithServerTest @ScreenshotTest public void openDrawer() { super.openDrawer(activityRule); diff --git a/src/androidTest/java/com/nextcloud/client/etm/EtmActivityTest.kt b/src/androidTest/java/com/nextcloud/client/etm/EtmActivityTest.kt index 1329768e0cd4..ee486ba532f3 100644 --- a/src/androidTest/java/com/nextcloud/client/etm/EtmActivityTest.kt +++ b/src/androidTest/java/com/nextcloud/client/etm/EtmActivityTest.kt @@ -29,6 +29,7 @@ import com.facebook.testing.screenshot.Screenshot import com.owncloud.android.AbstractIT import com.owncloud.android.lib.resources.status.OwnCloudVersion import com.owncloud.android.utils.ScreenshotTest +import com.owncloud.android.utils.ScreenshotWithServerTest import org.junit.Assume import org.junit.Before import org.junit.Rule @@ -47,6 +48,7 @@ class EtmActivityTest : AbstractIT() { } @Test + @ScreenshotWithServerTest @ScreenshotTest fun overview() { val sut: Activity = activityRule.launchActivity(null) @@ -57,6 +59,7 @@ class EtmActivityTest : AbstractIT() { } @Test + @ScreenshotWithServerTest @ScreenshotTest fun preferences() { val sut: EtmActivity = activityRule.launchActivity(null) @@ -67,6 +70,7 @@ class EtmActivityTest : AbstractIT() { } @Test + @ScreenshotWithServerTest @ScreenshotTest fun accounts() { val sut: EtmActivity = activityRule.launchActivity(null) diff --git a/src/androidTest/java/com/owncloud/android/ActivitiesModuleMock.java b/src/androidTest/java/com/owncloud/android/ActivitiesModuleMock.java new file mode 100644 index 000000000000..97e0a1d61b6f --- /dev/null +++ b/src/androidTest/java/com/owncloud/android/ActivitiesModuleMock.java @@ -0,0 +1,37 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android; + +import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository; +import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi; + +import dagger.Module; +import dagger.Provides; + +@Module +public class ActivitiesModuleMock { + @Provides + ActivitiesRepository activitiesRepository(ActivitiesServiceApi api) { + return new LocalActivitiesRepository(); + } +} diff --git a/src/androidTest/java/com/owncloud/android/LocalActivitiesRepository.java b/src/androidTest/java/com/owncloud/android/LocalActivitiesRepository.java new file mode 100644 index 000000000000..a0ee7be9f349 --- /dev/null +++ b/src/androidTest/java/com/owncloud/android/LocalActivitiesRepository.java @@ -0,0 +1,133 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.resources.activities.model.Activity; +import com.owncloud.android.lib.resources.activities.model.RichElement; +import com.owncloud.android.lib.resources.activities.model.RichElementTypeAdapter; +import com.owncloud.android.lib.resources.activities.models.PreviewObject; +import com.owncloud.android.lib.resources.activities.models.PreviewObjectAdapter; +import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import androidx.annotation.NonNull; + +import static com.owncloud.android.ui.activity.ContactsPreferenceActivity.TAG; + +public class LocalActivitiesRepository implements ActivitiesRepository { + String json = "{\n" + + " \"ocs\": {\n" + + " \"meta\": {\n" + + " \"status\": \"ok\",\n" + + " \"statuscode\": 200,\n" + + " \"message\": \"OK\"\n" + + " },\n" + + " \"data\": [\n" + + " {\n" + + " \"activity_id\": 1114442,\n" + + " \"app\": \"files\",\n" + + " \"type\": \"file_created\",\n" + + " \"user\": \"test\",\n" + + " \"subject\": \"You created IMG_0255.JPG\",\n" + + " \"subject_rich\": [\n" + + " \"You created {file}\",\n" + + " {\n" + + " \"file\": {\n" + + " \"type\": \"file\",\n" + + " \"id\": \"3523820\",\n" + + " \"name\": \"IMG_0255.JPG\",\n" + + " \"path\": \"IMG_0255.JPG\",\n" + + " \"link\": \"https:\\/\\/cloud.server.com\\/f\\/3523820\"\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"message\": \"\",\n" + + " \"message_rich\": [\n" + + " \"\",\n" + + " []\n" + + " ],\n" + + " \"object_type\": \"files\",\n" + + " \"object_id\": 3523820,\n" + + " \"object_name\": \"\\/IMG_0255.JPG\",\n" + + " \"objects\": {\n" + + " \"3523820\": \"\\/IMG_0255.JPG\"\n" + + " },\n" + + " \"link\": \"https:\\/\\/cloud.server.com\\/apps\\/files\\/?dir=\\/\",\n" + + " \"icon\": \"https:\\/\\/cloud.server.com\\/apps\\/files\\/img\\/add-color.svg\",\n" + + " \"datetime\": \"2020-03-19T12:18:25+00:00\",\n" + + " \"previews\": [\n" + + " {\n" + + " \"link\": \"https:\\/\\/cloud.server.com\\/apps\\/files\\/?dir=\\/&scrollto=IMG_0255.JPG\",\n" + + " \"source\": \"https:\\/\\/cloud.server.com\\/core\\/preview.png?file=\\/IMG_0255.JPG&c=b68e0f2668cc89eec0d17e6125ff8ae7&x=150&y=150\",\n" + + " \"mimeType\": \"image\\/jpeg\",\n" + + " \"isMimeTypeIcon\": false,\n" + + " \"fileId\": 3523820,\n" + + " \"view\": \"files\"\n" + + " }\n" + + " ]\n" + + " }]}}"; + + @Override + public void getActivities(int lastGiven, @NonNull LoadActivitiesCallback callback) { + + ArrayList activities = parseResult(json); + + callback.onActivitiesLoaded(activities, 1); + } + + protected ArrayList parseResult(String response) { + if (response == null || response.isEmpty()) { + return new ArrayList<>(); + } + + try { + JsonParser jsonParser = new JsonParser(); + JsonObject jo = (JsonObject) jsonParser.parse(response); + JsonArray jsonDataArray = jo.getAsJsonObject("ocs").getAsJsonArray("data"); + + Gson gson = new GsonBuilder() + .registerTypeAdapter(RichElement.class, new RichElementTypeAdapter()) + .registerTypeAdapter(PreviewObject.class, new PreviewObjectAdapter()) + .create(); + Type listType = new TypeToken>() { + }.getType(); + + return gson.fromJson(jsonDataArray, listType); + + } catch (JsonSyntaxException e) { + Log_OC.e(TAG, "Not a valid json: " + response, e); + return new ArrayList<>(); + } + } +} diff --git a/src/androidTest/java/com/owncloud/android/TestApp.kt b/src/androidTest/java/com/owncloud/android/TestApp.kt new file mode 100644 index 000000000000..a71068ff0910 --- /dev/null +++ b/src/androidTest/java/com/owncloud/android/TestApp.kt @@ -0,0 +1,33 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android + + +class TestApp : MainApp() { + override fun setupDagger() { + DaggerTestAppComponent.builder() + .application(this) + .build() + .inject(this); + } +} diff --git a/src/androidTest/java/com/owncloud/android/TestAppComponent.java b/src/androidTest/java/com/owncloud/android/TestAppComponent.java new file mode 100644 index 000000000000..5b8ef7430c40 --- /dev/null +++ b/src/androidTest/java/com/owncloud/android/TestAppComponent.java @@ -0,0 +1,67 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android; + +import android.app.Application; + +import com.nextcloud.client.appinfo.AppInfoModule; +import com.nextcloud.client.device.DeviceModule; +import com.nextcloud.client.di.AppModule; +import com.nextcloud.client.di.ViewModelModule; +import com.nextcloud.client.jobs.JobsModule; +import com.nextcloud.client.network.NetworkModule; +import com.nextcloud.client.onboarding.OnboardingModule; +import com.nextcloud.client.preferences.PreferencesModule; + +import javax.inject.Singleton; + +import dagger.BindsInstance; +import dagger.Component; +import dagger.android.support.AndroidSupportInjectionModule; + +@Singleton +@Component(modules = { + AndroidSupportInjectionModule.class, + AppModule.class, + PreferencesModule.class, + AppInfoModule.class, + NetworkModule.class, + DeviceModule.class, + OnboardingModule.class, + ViewModelModule.class, + JobsModule.class, + ActivitiesModuleMock.class +}) + +public interface TestAppComponent { + + void inject(TestApp app); + + @Component.Builder + interface Builder { + @BindsInstance + Builder application(Application application); + + TestAppComponent build(); + } +} diff --git a/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java b/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java index 0169fee46773..7567fd35474b 100644 --- a/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java +++ b/src/androidTest/java/com/owncloud/android/ui/activity/ManageAccountsActivityIT.java @@ -28,6 +28,7 @@ import com.nextcloud.client.account.User; import com.owncloud.android.AbstractIT; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithServerTest; import org.junit.Rule; import org.junit.Test; @@ -41,6 +42,7 @@ public class ManageAccountsActivityIT extends AbstractIT { false); @Test + @ScreenshotWithServerTest @ScreenshotTest public void open() { Activity sut = activityRule.launchActivity(null); @@ -51,6 +53,7 @@ public void open() { } @Test + @ScreenshotWithServerTest @ScreenshotTest public void userInfoDetail() { ManageAccountsActivity sut = activityRule.launchActivity(null); diff --git a/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt b/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt index f9d966e124df..4810c990853b 100644 --- a/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt +++ b/src/androidTest/java/com/owncloud/android/ui/fragment/OCFileListFragmentIT.kt @@ -50,6 +50,7 @@ import com.owncloud.android.operations.UploadFileOperation import com.owncloud.android.ui.activity.FileDisplayActivity import com.owncloud.android.utils.FileStorageUtils import com.owncloud.android.utils.ScreenshotTest +import com.owncloud.android.utils.ScreenshotWithServerTest import junit.framework.TestCase import org.junit.Assert.assertTrue import org.junit.Rule @@ -89,6 +90,7 @@ class OCFileListFragmentIT : AbstractIT() { } @Test + @ScreenshotWithServerTest @ScreenshotTest fun showRichWorkspace() { assertTrue(CreateFolderOperation("/test/", account, targetContext).execute(client, storageManager).isSuccess) @@ -167,6 +169,7 @@ class OCFileListFragmentIT : AbstractIT() { } @Test + @ScreenshotWithServerTest @ScreenshotTest fun createAndShowShareToUser() { val path = "/shareToAdmin/" @@ -192,6 +195,7 @@ class OCFileListFragmentIT : AbstractIT() { } @Test + @ScreenshotWithServerTest @ScreenshotTest fun createAndShowShareToGroup() { val path = "/shareToGroup/" @@ -249,6 +253,7 @@ class OCFileListFragmentIT : AbstractIT() { // } @Test + @ScreenshotWithServerTest @ScreenshotTest fun createAndShowShareViaLink() { val path = "/shareViaLink/" diff --git a/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java b/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java index 694ea3f53545..78430ad35224 100644 --- a/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java +++ b/src/androidTest/java/com/owncloud/android/ui/preview/PreviewTextFileFragmentTest.java @@ -31,6 +31,7 @@ import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.MimeTypeUtil; import com.owncloud.android.utils.ScreenshotTest; +import com.owncloud.android.utils.ScreenshotWithServerTest; import org.junit.Rule; import org.junit.Test; @@ -51,6 +52,7 @@ public class PreviewTextFileFragmentTest extends AbstractIT { Manifest.permission.WRITE_EXTERNAL_STORAGE); @Test + @ScreenshotWithServerTest @ScreenshotTest public void displaySimpleTextFile() { FileDisplayActivity sut = activityRule.launchActivity(null); @@ -69,6 +71,7 @@ public void displaySimpleTextFile() { } @Test + @ScreenshotWithServerTest @ScreenshotTest public void displayJavaSnippetFile() throws IOException { FileDisplayActivity sut = activityRule.launchActivity(null); diff --git a/src/main/java/com/nextcloud/client/di/ActivitiesModule.java b/src/main/java/com/nextcloud/client/di/ActivitiesModule.java new file mode 100644 index 000000000000..13b40797f199 --- /dev/null +++ b/src/main/java/com/nextcloud/client/di/ActivitiesModule.java @@ -0,0 +1,38 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.client.di; + +import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository; +import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi; +import com.owncloud.android.ui.activities.data.activities.RemoteActivitiesRepository; + +import dagger.Module; +import dagger.Provides; + +@Module +public class ActivitiesModule { + @Provides + ActivitiesRepository activitiesRepository(ActivitiesServiceApi api) { + return new RemoteActivitiesRepository(api); + } +} diff --git a/src/main/java/com/nextcloud/client/di/AppComponent.java b/src/main/java/com/nextcloud/client/di/AppComponent.java index 9ab3436b88e7..4f7cc047773e 100644 --- a/src/main/java/com/nextcloud/client/di/AppComponent.java +++ b/src/main/java/com/nextcloud/client/di/AppComponent.java @@ -45,7 +45,8 @@ DeviceModule.class, OnboardingModule.class, ViewModelModule.class, - JobsModule.class + JobsModule.class, + ActivitiesModule.class }) @Singleton public interface AppComponent { diff --git a/src/main/java/com/nextcloud/client/di/AppModule.java b/src/main/java/com/nextcloud/client/di/AppModule.java index 6d50d1bbe2c1..3f90a0158503 100644 --- a/src/main/java/com/nextcloud/client/di/AppModule.java +++ b/src/main/java/com/nextcloud/client/di/AppModule.java @@ -50,10 +50,8 @@ import com.nextcloud.client.network.ClientFactory; import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.UploadsStorageManager; -import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository; import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApi; import com.owncloud.android.ui.activities.data.activities.ActivitiesServiceApiImpl; -import com.owncloud.android.ui.activities.data.activities.RemoteActivitiesRepository; import com.owncloud.android.ui.activities.data.files.FilesRepository; import com.owncloud.android.ui.activities.data.files.FilesServiceApiImpl; import com.owncloud.android.ui.activities.data.files.RemoteFilesRepository; @@ -68,7 +66,7 @@ import dagger.Provides; @Module(includes = {ComponentsModule.class, VariantComponentsModule.class}) -class AppModule { +public class AppModule { @Provides AccountManager accountManager(Application application) { @@ -109,10 +107,6 @@ ActivitiesServiceApi activitiesServiceApi(UserAccountManager accountManager) { return new ActivitiesServiceApiImpl(accountManager); } - @Provides - ActivitiesRepository activitiesRepository(ActivitiesServiceApi api) { - return new RemoteActivitiesRepository(api); - } @Provides FilesRepository filesRepository(UserAccountManager accountManager, ClientFactory clientFactory) { diff --git a/src/main/java/com/owncloud/android/MainApp.java b/src/main/java/com/owncloud/android/MainApp.java index ca92e5980bad..8560e6a53bf1 100644 --- a/src/main/java/com/owncloud/android/MainApp.java +++ b/src/main/java/com/owncloud/android/MainApp.java @@ -98,6 +98,7 @@ import androidx.annotation.RequiresApi; import androidx.annotation.StringRes; +import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDelegate; import androidx.core.util.Pair; @@ -222,10 +223,7 @@ protected void attachBaseContext(Context base) { super.attachBaseContext(base); initGlobalContext(this); - DaggerAppComponent.builder() - .application(this) - .build() - .inject(this); + setupDagger(); // we don't want to handle crashes occurring inside crash reporter activity/process; // let the platform deal with those @@ -240,6 +238,14 @@ protected void attachBaseContext(Context base) { } } + @VisibleForTesting + public void setupDagger() { + DaggerAppComponent.builder() + .application(this) + .build() + .inject(this); + } + @SuppressFBWarnings("ST") @Override public void onCreate() { diff --git a/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java b/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java index 0bce2c2b5d86..056e25fb725e 100644 --- a/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java +++ b/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java @@ -29,7 +29,6 @@ import android.widget.TextView; import com.nextcloud.client.network.ClientFactory; -import com.nextcloud.common.NextcloudClient; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; @@ -52,7 +51,6 @@ import javax.inject.Inject; import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; @@ -233,12 +231,12 @@ public void onActivityClicked(RichObject richObject) { } @Override - public void showActivities(List activities, NextcloudClient client, int lastGiven) { + public void showActivities(List activities, int lastGiven) { boolean clear = false; if (this.lastGiven == UNDEFINED) { clear = true; } - adapter.setActivityItems(activities, client, clear); + adapter.setActivityItems(activities, clear); this.lastGiven = lastGiven; // Hide the recyclerView if list is empty diff --git a/src/main/java/com/owncloud/android/ui/activities/ActivitiesContract.java b/src/main/java/com/owncloud/android/ui/activities/ActivitiesContract.java index 8ab3b55eda37..87c763b95bdd 100644 --- a/src/main/java/com/owncloud/android/ui/activities/ActivitiesContract.java +++ b/src/main/java/com/owncloud/android/ui/activities/ActivitiesContract.java @@ -18,7 +18,6 @@ */ package com.owncloud.android.ui.activities; -import com.nextcloud.common.NextcloudClient; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.ui.activity.BaseActivity; @@ -27,7 +26,7 @@ public interface ActivitiesContract { interface View { - void showActivities(List activities, NextcloudClient client, int lastGiven); + void showActivities(List activities, int lastGiven); void showActivitiesLoadError(String error); void showActivityDetailUI(OCFile ocFile); void showActivityDetailUIIsNull(); diff --git a/src/main/java/com/owncloud/android/ui/activities/ActivitiesPresenter.java b/src/main/java/com/owncloud/android/ui/activities/ActivitiesPresenter.java index bab61e165f0e..89dcbf56c0d5 100644 --- a/src/main/java/com/owncloud/android/ui/activities/ActivitiesPresenter.java +++ b/src/main/java/com/owncloud/android/ui/activities/ActivitiesPresenter.java @@ -19,7 +19,6 @@ package com.owncloud.android.ui.activities; -import com.nextcloud.common.NextcloudClient; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.ui.activities.data.activities.ActivitiesRepository; import com.owncloud.android.ui.activities.data.files.FilesRepository; @@ -51,11 +50,11 @@ public void loadActivities(int lastGiven) { activitiesView.setProgressIndicatorState(true); activitiesRepository.getActivities(lastGiven, new ActivitiesRepository.LoadActivitiesCallback() { @Override - public void onActivitiesLoaded(List activities, NextcloudClient client, int lastGiven) { + public void onActivitiesLoaded(List activities, int lastGiven) { if (!activityStopped) { activitiesView.setProgressIndicatorState(false); - activitiesView.showActivities(activities, client, lastGiven); + activitiesView.showActivities(activities, lastGiven); } } diff --git a/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesRepository.java b/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesRepository.java index e8c54e9e74ab..22010888919d 100644 --- a/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesRepository.java +++ b/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesRepository.java @@ -18,8 +18,6 @@ */ package com.owncloud.android.ui.activities.data.activities; -import com.nextcloud.common.NextcloudClient; - import java.util.List; import androidx.annotation.NonNull; @@ -29,7 +27,7 @@ */ public interface ActivitiesRepository { interface LoadActivitiesCallback { - void onActivitiesLoaded(List activities, NextcloudClient client, int lastGiven); + void onActivitiesLoaded(List activities, int lastGiven); void onActivitiesLoadedError(String error); } diff --git a/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApi.java b/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApi.java index 419a5c0ba884..49b687b7c6d4 100644 --- a/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApi.java +++ b/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApi.java @@ -18,7 +18,6 @@ */ package com.owncloud.android.ui.activities.data.activities; -import com.nextcloud.common.NextcloudClient; import com.owncloud.android.lib.resources.activities.model.Activity; import java.util.List; @@ -31,10 +30,9 @@ public interface ActivitiesServiceApi { interface ActivitiesServiceCallback { - void onLoaded(T activities, NextcloudClient client, int lastGiven); + void onLoaded(T activities, int lastGiven); void onError (String error); } void getAllActivities(int lastGiven, ActivitiesServiceApi.ActivitiesServiceCallback> callback); - } diff --git a/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.java b/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.java index 0f7e2963d3ec..6e84e37726ea 100644 --- a/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.java +++ b/src/main/java/com/owncloud/android/ui/activities/data/activities/ActivitiesServiceApiImpl.java @@ -71,7 +71,6 @@ private static class GetActivityListTask extends AsyncTask private Account account; private int lastGiven; private String errorMessage; - private NextcloudClient client; private GetActivityListTask(Account account, int lastGiven, @@ -89,7 +88,7 @@ protected Boolean doInBackground(Void... voids) { OwnCloudAccount ocAccount; try { ocAccount = new OwnCloudAccount(account, context); - client = OwnCloudClientManagerFactory.getDefaultSingleton(). + NextcloudClient client = OwnCloudClientManagerFactory.getDefaultSingleton(). getNextcloudClientFor(ocAccount, MainApp.getAppContext()); GetActivitiesRemoteOperation getRemoteActivitiesOperation; @@ -138,7 +137,7 @@ protected Boolean doInBackground(Void... voids) { protected void onPostExecute(Boolean success) { super.onPostExecute(success); if (success) { - callback.onLoaded(activities, client, lastGiven); + callback.onLoaded(activities, lastGiven); } else { callback.onError(errorMessage); } diff --git a/src/main/java/com/owncloud/android/ui/activities/data/activities/RemoteActivitiesRepository.java b/src/main/java/com/owncloud/android/ui/activities/data/activities/RemoteActivitiesRepository.java index 524c8dbcf730..74488f987209 100644 --- a/src/main/java/com/owncloud/android/ui/activities/data/activities/RemoteActivitiesRepository.java +++ b/src/main/java/com/owncloud/android/ui/activities/data/activities/RemoteActivitiesRepository.java @@ -18,8 +18,6 @@ */ package com.owncloud.android.ui.activities.data.activities; -import com.nextcloud.common.NextcloudClient; - import java.util.List; import androidx.annotation.NonNull; @@ -38,8 +36,8 @@ public void getActivities(int lastGiven, @NonNull LoadActivitiesCallback callbac activitiesServiceApi.getAllActivities(lastGiven, new ActivitiesServiceApi.ActivitiesServiceCallback>() { @Override - public void onLoaded(List activities, NextcloudClient client, int lastGiven) { - callback.onActivitiesLoaded(activities, client, lastGiven); + public void onLoaded(List activities, int lastGiven) { + callback.onActivitiesLoaded(activities, lastGiven); } @Override diff --git a/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java index 67a49a836a0b..15fb25713d69 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java @@ -119,12 +119,16 @@ public ActivityListAdapter( this.storageManager = storageManager; this.capability = capability; this.clientFactory = clientFactory; + try { + this.client = clientFactory.createNextcloudClient(currentAccountProvider.getUser()); + } catch (ClientFactory.CreationException e) { + Log_OC.e(this, "Failed to create client", e); + } px = getThumbnailDimension(); this.isDetailView = isDetailView; } - public void setActivityItems(List activityItems, NextcloudClient client, boolean clear) { - this.client = client; + public void setActivityItems(List activityItems, boolean clear) { String sTime = ""; if (clear) { diff --git a/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java index 500a9f775138..44b4457f78fd 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java @@ -20,7 +20,6 @@ package com.owncloud.android.ui.adapter; import android.content.Intent; -import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Typeface; import android.graphics.drawable.PictureDrawable; diff --git a/src/main/java/com/owncloud/android/utils/ScreenshotWithServerTest.java b/src/main/java/com/owncloud/android/utils/ScreenshotWithServerTest.java new file mode 100644 index 000000000000..65636214bf3f --- /dev/null +++ b/src/main/java/com/owncloud/android/utils/ScreenshotWithServerTest.java @@ -0,0 +1,37 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.utils; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotate any screenshot test with this so it is run only when updating/testing screenshots + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ScreenshotWithServerTest { +} diff --git a/src/main/java/com/owncloud/android/utils/ScreenshotWithoutServerTest.java b/src/main/java/com/owncloud/android/utils/ScreenshotWithoutServerTest.java new file mode 100644 index 000000000000..7638b5a73116 --- /dev/null +++ b/src/main/java/com/owncloud/android/utils/ScreenshotWithoutServerTest.java @@ -0,0 +1,37 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.utils; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotate any screenshot test with this so it is run only when updating/testing screenshots + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ScreenshotWithoutServerTest { +}