Преглед на файлове

TrashbinActivity:
- moved to ViewBindings
- add UI test for error/view

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>

tobiasKaminsky преди 4 години
родител
ревизия
f7ab5d90dc

BIN
screenshots/gplay/debug/com.owncloud.android.ui.trashbin.TrashbinActivityIT_empty.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.trashbin.TrashbinActivityIT_error.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.trashbin.TrashbinActivityIT_files.png


+ 86 - 0
src/androidTest/java/com/owncloud/android/ui/trashbin/TrashbinActivityIT.kt

@@ -0,0 +1,86 @@
+/*
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.trashbin
+
+import androidx.test.espresso.intent.rule.IntentsTestRule
+import com.facebook.testing.screenshot.Screenshot
+import com.owncloud.android.AbstractIT
+import com.owncloud.android.utils.ScreenshotTest
+import org.junit.Rule
+import org.junit.Test
+
+class TrashbinActivityIT : AbstractIT() {
+    enum class TestCase {
+        ERROR, EMPTY, FILES
+    }
+
+    @get:Rule
+    var activityRule = IntentsTestRule(TrashbinActivity::class.java, true, false)
+
+    @Test
+    @ScreenshotTest
+    fun error() {
+        val sut: TrashbinActivity = activityRule.launchActivity(null)
+
+        val trashbinRepository = TrashbinLocalRepository(TestCase.ERROR)
+
+        sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
+
+        sut.runOnUiThread { sut.loadFolder() }
+
+        shortSleep()
+
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    @ScreenshotTest
+    fun files() {
+        val sut: TrashbinActivity = activityRule.launchActivity(null)
+
+        val trashbinRepository = TrashbinLocalRepository(TestCase.FILES)
+
+        sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
+
+        sut.runOnUiThread { sut.loadFolder() }
+
+        shortSleep()
+
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    @ScreenshotTest
+    fun empty() {
+        val sut: TrashbinActivity = activityRule.launchActivity(null)
+
+        val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
+
+        sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
+
+        sut.runOnUiThread { sut.loadFolder() }
+
+        shortSleep()
+
+        Screenshot.snapActivity(sut).record()
+    }
+}

+ 84 - 0
src/androidTest/java/com/owncloud/android/ui/trashbin/TrashbinLocalRepository.kt

@@ -0,0 +1,84 @@
+/*
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.trashbin
+
+import com.owncloud.android.R
+import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile
+import com.owncloud.android.ui.trashbin.TrashbinRepository.LoadFolderCallback
+
+class TrashbinLocalRepository(val testCase: TrashbinActivityIT.TestCase) : TrashbinRepository {
+    override fun emptyTrashbin(callback: TrashbinRepository.OperationCallback?) {
+        TODO("Not yet implemented")
+    }
+
+    override fun restoreFile(file: TrashbinFile?, callback: TrashbinRepository.OperationCallback?) {
+        TODO("Not yet implemented")
+    }
+
+    override fun removeTrashbinFile(file: TrashbinFile?, callback: TrashbinRepository.OperationCallback?) {
+        TODO("Not yet implemented")
+    }
+
+    @Suppress("MagicNumber")
+    override fun getFolder(remotePath: String?, callback: LoadFolderCallback?) {
+        when (testCase) {
+            TrashbinActivityIT.TestCase.ERROR -> callback?.onError(R.string.trashbin_loading_failed)
+            TrashbinActivityIT.TestCase.FILES -> {
+                val files = ArrayList<Any>()
+                files.add(
+                    TrashbinFile(
+                        "test.md",
+                        "text/markdown",
+                        "/trashbin/test.md",
+                        "subFolder/test.md",
+                        1395847838, // random date
+                        1395847908 // random date
+                    )
+                )
+                files.add(
+                    TrashbinFile(
+                        "image.jpg",
+                        "image/jpeg",
+                        "/trashbin/image.jpg",
+                        "image.jpg",
+                        1395841858, // random date
+                        1395837858 // random date
+                    )
+                )
+                files.add(
+                    TrashbinFile(
+                        "folder",
+                        "DIR",
+                        "/trashbin/folder/",
+                        "folder",
+                        1395347858, // random date
+                        1395849858 // random date
+                    )
+                )
+
+                callback?.onSuccess(files)
+            }
+            TrashbinActivityIT.TestCase.EMPTY -> callback?.onSuccess(ArrayList<Any>())
+        }
+    }
+}

+ 45 - 83
src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java

@@ -28,11 +28,9 @@ import android.os.Bundle;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-import android.widget.ImageView;
 import android.widget.PopupMenu;
 import android.widget.TextView;
 
-import com.google.android.material.button.MaterialButton;
 import com.google.android.material.snackbar.Snackbar;
 import com.nextcloud.client.account.CurrentAccountProvider;
 import com.nextcloud.client.account.User;
@@ -40,6 +38,7 @@ import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.network.ClientFactory;
 import com.nextcloud.client.preferences.AppPreferences;
 import com.owncloud.android.R;
+import com.owncloud.android.databinding.TrashbinActivityBinding;
 import com.owncloud.android.lib.resources.trashbin.model.TrashbinFile;
 import com.owncloud.android.ui.EmptyRecyclerView;
 import com.owncloud.android.ui.activity.FileActivity;
@@ -55,13 +54,9 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.core.content.res.ResourcesCompat;
 import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
-import butterknife.BindString;
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.Unbinder;
 
 import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
 
@@ -74,44 +69,16 @@ public class TrashbinActivity extends FileActivity implements
     TrashbinContract.View,
     Injectable {
 
-    @BindView(R.id.empty_list_progress)
-    public View emptyListProgress;
-
-    @BindView(R.id.empty_list_view)
-    public View emptyListView;
-
-    @BindView(R.id.empty_list_view_text)
-    public TextView emptyContentMessage;
-
-    @BindView(R.id.empty_list_view_headline)
-    public TextView emptyContentHeadline;
-
-    @BindView(R.id.empty_list_icon)
-    public ImageView emptyContentIcon;
-
-    @BindView(android.R.id.list)
-    public EmptyRecyclerView recyclerView;
-
-    @BindView(R.id.swipe_containing_list)
-    public SwipeRefreshLayout swipeListRefreshLayout;
-
-    @BindView(R.id.sort_button)
-    public MaterialButton sortButton;
-
-    @BindString(R.string.trashbin_empty_headline)
-    public String noResultsHeadline;
-
-    @BindString(R.string.trashbin_empty_message)
-    public String noResultsMessage;
-
     @Inject AppPreferences preferences;
     @Inject CurrentAccountProvider accountProvider;
     @Inject ClientFactory clientFactory;
-    private Unbinder unbinder;
     private TrashbinListAdapter trashbinListAdapter;
-    private TrashbinPresenter trashbinPresenter;
+
+    @VisibleForTesting
+    TrashbinPresenter trashbinPresenter;
 
     private boolean active;
+    private TrashbinActivityBinding binding;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -119,8 +86,10 @@ public class TrashbinActivity extends FileActivity implements
         final User user = accountProvider.getUser();
         final RemoteTrashbinRepository trashRepository = new RemoteTrashbinRepository(user, clientFactory);
         trashbinPresenter = new TrashbinPresenter(trashRepository, this);
-        setContentView(R.layout.trashbin_activity);
-        unbinder = ButterKnife.bind(this);
+
+        binding = TrashbinActivityBinding.inflate(getLayoutInflater());
+        setContentView(binding.getRoot());
+
         setupToolbar();
         findViewById(R.id.sort_list_button_group).setVisibility(View.VISIBLE);
         findViewById(R.id.switch_grid_view_button).setVisibility(View.GONE);
@@ -136,14 +105,14 @@ public class TrashbinActivity extends FileActivity implements
     }
 
     private void setupContent() {
-        recyclerView = findViewById(android.R.id.list);
-        recyclerView.setEmptyView(emptyListView);
-        emptyListView.setVisibility(View.GONE);
-        emptyContentIcon.setImageResource(R.drawable.ic_delete);
-        emptyContentIcon.setVisibility(View.VISIBLE);
-        emptyContentHeadline.setText(noResultsHeadline);
-        emptyContentMessage.setText(noResultsMessage);
-        emptyContentMessage.setVisibility(View.VISIBLE);
+        EmptyRecyclerView recyclerView = binding.list;
+        recyclerView.setEmptyView(binding.emptyList.emptyListView);
+        binding.emptyList.emptyListView.setVisibility(View.GONE);
+        binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_delete);
+        binding.emptyList.emptyListIcon.setVisibility(View.VISIBLE);
+        binding.emptyList.emptyListViewHeadline.setText(getString(R.string.trashbin_empty_headline));
+        binding.emptyList.emptyListViewText.setText(getString(R.string.trashbin_empty_message));
+        binding.emptyList.emptyListViewText.setVisibility(View.VISIBLE);
 
         trashbinListAdapter = new TrashbinListAdapter(
             this,
@@ -157,21 +126,21 @@ public class TrashbinActivity extends FileActivity implements
         recyclerView.setHasFooter(true);
         recyclerView.setLayoutManager(new LinearLayoutManager(this));
 
-        ThemeUtils.colorSwipeRefreshLayout(this, swipeListRefreshLayout);
-        swipeListRefreshLayout.setOnRefreshListener(this::loadFolder);
+        ThemeUtils.colorSwipeRefreshLayout(this, binding.swipeContainingList);
+        binding.swipeContainingList.setOnRefreshListener(this::loadFolder);
 
-        sortButton.setOnClickListener(l ->
-                                          openSortingOrderDialogFragment(getSupportFragmentManager(),
-                                                                         preferences.getSortOrderByType(
-                                                                             FileSortOrder.Type.trashBinView,
-                                                                             FileSortOrder.sort_new_to_old))
-                                     );
+        findViewById(R.id.sort_button).setOnClickListener(l ->
+                                                              openSortingOrderDialogFragment(getSupportFragmentManager(),
+                                                                                             preferences.getSortOrderByType(
+                                                                                                 FileSortOrder.Type.trashBinView,
+                                                                                                 FileSortOrder.sort_new_to_old))
+                                                         );
 
         loadFolder();
     }
 
-    private void loadFolder() {
-        swipeListRefreshLayout.setRefreshing(true);
+    protected void loadFolder() {
+        binding.swipeContainingList.setRefreshing(true);
         trashbinPresenter.loadFolder();
     }
 
@@ -209,12 +178,6 @@ public class TrashbinActivity extends FileActivity implements
         return retval;
     }
 
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        unbinder.unbind();
-    }
-
     @Override
     public void onOverflowIconClicked(TrashbinFile file, View view) {
         PopupMenu popup = new PopupMenu(this, view);
@@ -273,6 +236,7 @@ public class TrashbinActivity extends FileActivity implements
 
     @Override
     public void onSortingOrderChosen(FileSortOrder sortOrder) {
+        TextView sortButton = findViewById(R.id.sort_button);
         sortButton.setText(DisplayUtils.getSortOrderStringId(sortOrder));
         trashbinListAdapter.setSortOrder(sortOrder);
     }
@@ -281,8 +245,8 @@ public class TrashbinActivity extends FileActivity implements
     public void showTrashbinFolder(List<Object> trashbinFiles) {
         if (active) {
             trashbinListAdapter.setTrashbinFiles(trashbinFiles, true);
-            swipeListRefreshLayout.setRefreshing(false);
-            emptyListProgress.setVisibility(View.GONE);
+            binding.swipeContainingList.setRefreshing(false);
+            binding.emptyList.emptyListProgress.setVisibility(View.GONE);
         }
     }
 
@@ -301,8 +265,9 @@ public class TrashbinActivity extends FileActivity implements
     @Override
     public void showSnackbarError(int message, TrashbinFile file) {
         if (active) {
-            swipeListRefreshLayout.setRefreshing(false);
-            Snackbar.make(recyclerView, String.format(getString(message), file.getFileName()), Snackbar.LENGTH_LONG)
+            binding.swipeContainingList.setRefreshing(false);
+            Snackbar.make(binding.list,
+                          String.format(getString(message), file.getFileName()), Snackbar.LENGTH_LONG)
                 .show();
         }
     }
@@ -310,20 +275,17 @@ public class TrashbinActivity extends FileActivity implements
     @Override
     public void showError(int message) {
         if (active) {
-            swipeListRefreshLayout.setRefreshing(false);
-
-            if (emptyContentMessage != null) {
-                emptyContentHeadline.setText(R.string.common_error);
-                emptyContentIcon.setImageDrawable(ResourcesCompat.getDrawable(getResources(),
-                                                                              R.drawable.ic_list_empty_error,
-                                                                              null));
-                emptyContentMessage.setText(message);
-
-                emptyContentMessage.setVisibility(View.VISIBLE);
-                emptyContentIcon.setVisibility(View.VISIBLE);
-                emptyListView.setVisibility(View.VISIBLE);
-                emptyListProgress.setVisibility(View.GONE);
-            }
+            binding.swipeContainingList.setRefreshing(false);
+
+            binding.emptyList.emptyListViewHeadline.setText(R.string.common_error);
+            binding.emptyList.emptyListIcon.setImageDrawable(ResourcesCompat.getDrawable(getResources(),
+                                                                                         R.drawable.ic_list_empty_error,
+                                                                                         null));
+            binding.emptyList.emptyListViewText.setText(message);
+            binding.emptyList.emptyListViewText.setVisibility(View.VISIBLE);
+            binding.emptyList.emptyListIcon.setVisibility(View.VISIBLE);
+            binding.emptyList.emptyListView.setVisibility(View.VISIBLE);
+            binding.emptyList.emptyListProgress.setVisibility(View.GONE);
         }
     }
 }

+ 8 - 4
src/main/res/layout/trashbin_activity.xml

@@ -33,13 +33,15 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
-        <include layout="@layout/toolbar_standard" />
+        <include
+            android:id="@+id/toolbar_standard_include"
+            layout="@layout/toolbar_standard" />
 
         <androidx.coordinatorlayout.widget.CoordinatorLayout
             android:id="@+id/list_fragment_layout"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_below="@id/appbar">
+            android:layout_below="@id/toolbar_standard_include">
 
             <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
                 android:id="@+id/swipe_containing_list"
@@ -52,10 +54,12 @@
                 <com.owncloud.android.ui.EmptyRecyclerView
                     android:id="@android:id/list"
                     android:layout_width="match_parent"
-                    android:layout_height="match_parent"/>
+                    android:layout_height="match_parent" />
             </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
 
-            <include layout="@layout/empty_list"/>
+            <include
+                android:id="@+id/empty_list"
+                layout="@layout/empty_list" />
 
         </androidx.coordinatorlayout.widget.CoordinatorLayout>