diff options
author | weldoncyngn <wng@cyngn.com> | 2015-07-29 13:58:35 -0700 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2015-08-28 13:57:36 -0700 |
commit | 4803835d855055f376bc6728cd4b959ab8d0a3a9 (patch) | |
tree | da36d00a06d9e895ea819e3f8738f09fe540030b | |
parent | 60b5090aa7cf6fe7a640720c5e6a43a563c830e4 (diff) | |
download | android_packages_apps_CMFileManager-staging/dev.tar.gz android_packages_apps_CMFileManager-staging/dev.tar.bz2 android_packages_apps_CMFileManager-staging/dev.zip |
Initial commit for Espresso tests.staging/dev
Change-Id: Ie2cd998d9399d51ad646d7ffe3e82cf9ca61a6b7
-rw-r--r-- | androidTest/.gitignore | 7 | ||||
-rwxr-xr-x | androidTest/Android.mk | 54 | ||||
-rwxr-xr-x | androidTest/AndroidManifest.xml | 22 | ||||
-rwxr-xr-x | androidTest/README.md | 8 | ||||
-rw-r--r-- | androidTest/res/drawable-hdpi/ic_launcher.png | bin | 0 -> 4811 bytes | |||
-rw-r--r-- | androidTest/res/drawable-mdpi/ic_launcher.png | bin | 0 -> 3033 bytes | |||
-rw-r--r-- | androidTest/res/drawable-xhdpi/ic_launcher.png | bin | 0 -> 6887 bytes | |||
-rw-r--r-- | androidTest/res/values/strings.xml | 19 | ||||
-rw-r--r-- | androidTest/src/com/cyanogenmod/filemanager/activities/MainActivityTest.java | 481 | ||||
-rw-r--r-- | androidTest/src/com/cyanogenmod/filemanager/activities/WelcomeActivityTest.java | 137 | ||||
-rwxr-xr-x | src/com/cyanogenmod/filemanager/activities/MainActivity.java | 4 |
11 files changed, 731 insertions, 1 deletions
diff --git a/androidTest/.gitignore b/androidTest/.gitignore new file mode 100644 index 00000000..663bbcab --- /dev/null +++ b/androidTest/.gitignore @@ -0,0 +1,7 @@ +/.settings +/bin +/gen +/.checkstyle +/.classpath +/.project +/project.properties diff --git a/androidTest/Android.mk b/androidTest/Android.mk new file mode 100755 index 00000000..b9def492 --- /dev/null +++ b/androidTest/Android.mk @@ -0,0 +1,54 @@ +# +# Copyright (C) 2012 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# We only want this apk build for tests. +LOCAL_MODULE_TAGS := tests + +LOCAL_JAVA_LIBRARIES := android.test.runner + +LOCAL_STATIC_JAVA_LIBRARIES := espresso + +annotation_dir := ../../../../frameworks/testing/runner/src/main/java/android/support/test/annotation +rules_dir := ../../../../frameworks/testing/rules/src/main + +# Include all test java files. +LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES += $(call all-java-files-under, $(annotation_dir)) +LOCAL_SRC_FILES += $(call all-java-files-under, $(rules_dir)) + +# Notice that we don't have to include the src files of CMFileManager because, by +# running the tests using an instrumentation targeting CMFileManager, we +# automatically get all of its classes loaded into our environment. + +LOCAL_PACKAGE_NAME := CMFileManagerAndroidTests + +LOCAL_INSTRUMENTATION_FOR := CMFileManager + +LOCAL_CERTIFICATE := platform + +LOCAL_PROGUARD_ENABLED := disabled + +include $(BUILD_PACKAGE) + +include $(CLEAR_VARS) + +LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ + espresso:../../../../prebuilts/misc/common/android-support-test/espresso-core.jar + +include $(BUILD_MULTI_PREBUILT) diff --git a/androidTest/AndroidManifest.xml b/androidTest/AndroidManifest.xml new file mode 100755 index 00000000..ab81c3c4 --- /dev/null +++ b/androidTest/AndroidManifest.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.cyanogenmod.filemanager.test"> + + <original-package android:name="com.cyanogenmod.filemanager.test" /> + + <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="17" /> + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> + + <instrumentation + android:name="android.support.test.runner.AndroidJUnitRunner" + android:targetPackage="com.cyanogenmod.filemanager" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + <uses-library android:name="android.test.runner" /> + </application> + +</manifest> diff --git a/androidTest/README.md b/androidTest/README.md new file mode 100755 index 00000000..40e099e7 --- /dev/null +++ b/androidTest/README.md @@ -0,0 +1,8 @@ +To run the espresso tests: + +mm + +adb install -r $OUT/data/app/CMFileManagerAndroidTests/CMFileManagerAndroidTests.apk + +adb shell am instrument -w -e class com.cyanogenmod.filemanager.activities.WelcomeActivityTest com.cyanogenmod.filemanager.test/android.support.test.runner.AndroidJUnitRunner +adb shell am instrument -w -e class com.cyanogenmod.filemanager.activities.MainActivityTest com.cyanogenmod.filemanager.test/android.support.test.runner.AndroidJUnitRunner diff --git a/androidTest/res/drawable-hdpi/ic_launcher.png b/androidTest/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..6705a79d --- /dev/null +++ b/androidTest/res/drawable-hdpi/ic_launcher.png diff --git a/androidTest/res/drawable-mdpi/ic_launcher.png b/androidTest/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..7d7c4881 --- /dev/null +++ b/androidTest/res/drawable-mdpi/ic_launcher.png diff --git a/androidTest/res/drawable-xhdpi/ic_launcher.png b/androidTest/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..51e4604b --- /dev/null +++ b/androidTest/res/drawable-xhdpi/ic_launcher.png diff --git a/androidTest/res/values/strings.xml b/androidTest/res/values/strings.xml new file mode 100644 index 00000000..219dcb07 --- /dev/null +++ b/androidTest/res/values/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ** Copyright (C) 2015 The CyanogenMod Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. +--> +<resources> + <string name="app_name">File Manager Tests</string> +</resources> diff --git a/androidTest/src/com/cyanogenmod/filemanager/activities/MainActivityTest.java b/androidTest/src/com/cyanogenmod/filemanager/activities/MainActivityTest.java new file mode 100644 index 00000000..a9750a66 --- /dev/null +++ b/androidTest/src/com/cyanogenmod/filemanager/activities/MainActivityTest.java @@ -0,0 +1,481 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.activities; + +import android.app.Activity; +import android.support.test.espresso.action.ViewActions; +import android.support.test.espresso.matcher.BoundedMatcher; +import android.support.test.espresso.matcher.ViewMatchers; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.View; +import android.widget.Adapter; +import android.widget.AdapterView; +import android.widget.ListView; + +import com.cyanogen.ambient.storage.provider.StorageProviderInfo; +import com.cyanogenmod.filemanager.R; +import com.cyanogenmod.filemanager.console.storageapi.StorageApiConsole; +import com.cyanogenmod.filemanager.model.FileSystemObject; +import com.cyanogenmod.filemanager.util.StorageHelper; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.runner.RunWith; +import org.junit.Test; + +import java.io.InvalidClassException; +import java.lang.InterruptedException; +import java.util.List; +import java.util.Random; + +import static android.support.test.espresso.Espresso.onData; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.Espresso.pressBack; +import static android.support.test.espresso.action.ViewActions.clearText; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.longClick; +import static android.support.test.espresso.action.ViewActions.typeText; +import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + +/** + * The timeouts for each test size is: + * @SmallTest - 1 minute + * @MediumTest - 3 minutes + * @LargeTest - 5 minutes + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class MainActivityTest { + private static final String TAG = MainActivityTest.class.getSimpleName(); + private static final String OK = "OK"; + private static final String YES = "Yes"; + private static final String NEW_FOLDER = "New folder"; + private static final String NEW_FILE = "New file"; + private static final String DELETE_SELECTION = "Delete selection"; + private static final String COPY_TO = "Copy to"; + private static final String MOVE_TO = "Move to"; + private static final String DROPBOX = "Dropbox"; + private static final String LOCAL_STORAGE = "Local storage"; + private static final String COPY = "Copy"; + private static final String MOVE = "Move"; + private static final String MORE_OPTIONS = "More options"; + + private MainActivity mActivity; + + /** + * A JUnit {@link Rule @Rule} to launch your activity under test. This is a replacement + * for {@link ActivityInstrumentationTestCase2}. + * <p> + * Rules are interceptors which are executed for each test method and will run before + * any of your setup code in the {@link Before @Before} method. + * <p> + * {@link ActivityTestRule} will create and launch of the activity for you and also expose + * the activity under test. To get a reference to the activity you can use + * the {@link ActivityTestRule#getActivity()} method. + */ + @Rule + public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>( + MainActivity.class); + + @Before + public void setUp() { + mActivity = (MainActivity) mActivityRule.getActivity(); + Assert.assertNotNull(mActivity); + } + + /** + * Tests the Navigation Fragment of the Main Activity. + * Navigates to Storage API provider. Verify the provider's title is Dropbox. + * Verify the navigation fragment is presented. + */ + @Test + public void navigateToDropbox() throws InterruptedException { + pauseForProviderToLoad(); + List<StorageProviderInfo> providerInfoList = mActivity.getProviderList(); + Assert.assertNotNull("providerInfoList is null", providerInfoList); + Assert.assertEquals("No longer support single provider. Modify test.", + providerInfoList.size(), 1); + StorageProviderInfo storageProviderInfo = providerInfoList.get(0); + Assert.assertFalse("Provider still needs authentication", storageProviderInfo.needAuthentication()); + Assert.assertEquals("Not equal to Dropbox", storageProviderInfo.getTitle(), "Dropbox"); + String path = StorageApiConsole.constructStorageApiFilePathFromProvider( + storageProviderInfo.getRootDocumentId(), + StorageApiConsole.getHashCodeFromProvider(storageProviderInfo)); + mActivity.navigateToPath(path); + Thread.sleep(1000); + Assert.assertTrue("Current Fragment is not NAVIGATION", + mActivity.isCurrentFragment(MainActivity.FragmentType.NAVIGATION)); + } + + /** + * Tests dismissing add cloud storage card. + */ + @Test + public void dismissAddCloudStorageCard() throws InterruptedException, InvalidClassException { + onView(withId(R.id.dismiss_card)).check(matches(isDisplayed())); + onView(withId(R.id.dismiss_card)).perform(click()); + onView(withId(R.id.dismiss_card)).check(matches(not(isDisplayed()))); + } + + /** + * Tests creating local folder and file. + */ + @Test + public void createDeleteLocalFolderAndFile() throws InterruptedException { + String FOLDER_NAME = "BTestFolder" + new Random().nextInt(); + String FILE_NAME = "TestFile" + new Random().nextInt(); + + mActivity.navigateToPath(StorageHelper.getLocalStoragePath(mActivity)); + + // create a folder + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FOLDER)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FOLDER_NAME)); + onView(withText(OK)).perform(click()); + + // check folder exists + onView(withId(R.id.navigation_view_layout)) + .check(matches(withAdaptedData(withDocumentName(FOLDER_NAME)))); + + // create a file + onData(withDocumentName(FOLDER_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(click()); + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FILE)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FILE_NAME)); + onView(withText(OK)).perform(click()); + + // check file exists + onView(withId(R.id.navigation_view_layout)) + .check(matches(withAdaptedData(withDocumentName(FILE_NAME)))); + + Thread.sleep(2000); + pressBack(); + Thread.sleep(2000); + + // delete the folder + onData(withDocumentName(FOLDER_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(longClick()); + onView(withId(R.id.ab_actions)).perform(click()); + onView(withText(DELETE_SELECTION)).perform(click()); + onView(withText(YES)).perform(click()); + + // check folder is gone + onView(withId(R.id.navigation_view_layout)) + .check(matches(not(withAdaptedData(withDocumentName(FOLDER_NAME))))); + } + + /** + * Tests copying a file from local to Dropbox + */ + @Test + public void copyFileFromLocalToDropbox() { + String FILE_NAME = "LocalFile" + new Random().nextInt(); + mActivity.navigateToPath(StorageHelper.getLocalStoragePath(mActivity)); + + // create a file + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FILE)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FILE_NAME)); + onView(withText(OK)).perform(click()); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + + // long press the file + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(longClick()); + onView(withId(R.id.ab_actions)).perform(click()); + onView(withText(COPY_TO)).perform(click()); + onView(withText(DROPBOX)).perform(click()); + onView(withText(COPY)).perform(click()); + + // Check file in Dropbox + List<StorageProviderInfo> providerInfoList = mActivity.getProviderList(); + StorageProviderInfo storageProviderInfo = providerInfoList.get(0); + String path = StorageApiConsole.constructStorageApiFilePathFromProvider( + storageProviderInfo.getRootDocumentId(), + StorageApiConsole.getHashCodeFromProvider(storageProviderInfo)); + mActivity.navigateToPath(path); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(click()); + } + + /** + * Tests moving a file from local to Dropbox + */ + @Test + public void moveFileFromLocalToDropbox() { + String FILE_NAME = "LocalFile" + new Random().nextInt(); + mActivity.navigateToPath(StorageHelper.getLocalStoragePath(mActivity)); + + // create a file + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FILE)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FILE_NAME)); + onView(withText(OK)).perform(click()); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + + // long press the file + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(longClick()); + onView(withId(R.id.ab_actions)).perform(click()); + onView(withText(MOVE_TO)).perform(click()); + onView(withText(DROPBOX)).perform(click()); + onView(withText(MOVE)).perform(click()); + + // Check not in local storage + onView(withId(R.id.navigation_view_layout)) + .check(matches(not(withAdaptedData(withDocumentName(FILE_NAME))))); + + // Check file in Dropbox + List<StorageProviderInfo> providerInfoList = mActivity.getProviderList(); + StorageProviderInfo storageProviderInfo = providerInfoList.get(0); + String path = StorageApiConsole.constructStorageApiFilePathFromProvider( + storageProviderInfo.getRootDocumentId(), + StorageApiConsole.getHashCodeFromProvider(storageProviderInfo)); + mActivity.navigateToPath(path); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(click()); + } + + /** + * Tests copying a file from local to Dropbox + */ + @Test + public void copyFileFromDropboxToLocal() throws InterruptedException { + String FILE_NAME = "DropboxFile" + new Random().nextInt(); + + pauseForProviderToLoad(); + List<StorageProviderInfo> providerInfoList = mActivity.getProviderList(); + StorageProviderInfo storageProviderInfo = providerInfoList.get(0); + String path = StorageApiConsole.constructStorageApiFilePathFromProvider( + storageProviderInfo.getRootDocumentId(), + StorageApiConsole.getHashCodeFromProvider(storageProviderInfo)); + mActivity.navigateToPath(path); + + // create a file + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FILE)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FILE_NAME)); + onView(withText(OK)).perform(click()); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + + // long press the file + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(longClick()); + onView(withId(R.id.ab_actions)).perform(click()); + onView(withText(COPY_TO)).perform(click()); + onView(withText(LOCAL_STORAGE)).perform(click()); + onView(withText(COPY)).perform(click()); + + // Check file in local storage + mActivity.navigateToPath(StorageHelper.getLocalStoragePath(mActivity)); + pauseForProviderToLoad(); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + } + + /** + * Tests moving a file from Dropbox to local + */ + @Test + public void moveFileFromDropboxToLocal() throws InterruptedException { + String FILE_NAME = "DropboxFile" + new Random().nextInt(); + + pauseForProviderToLoad(); + List<StorageProviderInfo> providerInfoList = mActivity.getProviderList(); + StorageProviderInfo storageProviderInfo = providerInfoList.get(0); + String path = StorageApiConsole.constructStorageApiFilePathFromProvider( + storageProviderInfo.getRootDocumentId(), + StorageApiConsole.getHashCodeFromProvider(storageProviderInfo)); + mActivity.navigateToPath(path); + + // create a file + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FILE)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FILE_NAME)); + onView(withText(OK)).perform(click()); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + + // long press the file + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(longClick()); + onView(withId(R.id.ab_actions)).perform(click()); + onView(withText(MOVE_TO)).perform(click()); + onView(withText(LOCAL_STORAGE)).perform(click()); + onView(withText(MOVE)).perform(click()); + + // Check not in Dropbox + onView(withId(R.id.navigation_view_layout)) + .check(matches(not(withAdaptedData(withDocumentName(FILE_NAME))))); + + // Check file in local storage + mActivity.navigateToPath(StorageHelper.getLocalStoragePath(mActivity)); + pauseForProviderToLoad(); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + } + + /** + * Tests moving a file from Dropbox to local + */ + @Test + public void createDeleteFileAndFolderinDropbox() throws InterruptedException { + String FILE_NAME = "DropboxFile" + new Random().nextInt(); + String FOLDER_NAME = "DropboxFile" + new Random().nextInt(); + + // open Dropbox Navigation View + pauseForProviderToLoad(); + List<StorageProviderInfo> providerInfoList = mActivity.getProviderList(); + StorageProviderInfo storageProviderInfo = providerInfoList.get(0); + String path = StorageApiConsole.constructStorageApiFilePathFromProvider( + storageProviderInfo.getRootDocumentId(), + StorageApiConsole.getHashCodeFromProvider(storageProviderInfo)); + mActivity.navigateToPath(path); + + // create a file + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FILE)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FILE_NAME)); + onView(withText(OK)).perform(click()); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + + // create a folder + onView(withContentDescription(MORE_OPTIONS)).perform(click()); + onView(withText(NEW_FOLDER)).perform(click()); + onView(withId(R.id.input_name_dialog_edit)).perform(clearText()).perform(typeText(FOLDER_NAME)); + onView(withText(OK)).perform(click()); + onData(withDocumentName(FOLDER_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + + // move the file into the folder + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(longClick()); + onView(withId(R.id.ab_actions)).perform(click()); + onView(withText(MOVE_TO)).perform(click()); + onView(withText(DROPBOX)).perform(click()); + onData(withDocumentName(FOLDER_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(click()); + onView(withText(MOVE)).perform(click()); + + // check the file is not in root folder + onView(withId(R.id.navigation_view_layout)) + .check(matches(not(withAdaptedData(withDocumentName(FILE_NAME))))); + + // check the file is moved into the folder + onData(withDocumentName(FOLDER_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .perform(click()); + onData(withDocumentName(FILE_NAME)) + .inAdapterView(allOf(isAssignableFrom(ListView.class), isDisplayed())) + .check(matches(isDisplayed())); + } + + /** + * Returns a Matcher<Object> from a document name which matches FileSystemObject.getName() + * @param name + * @return Matcher<Object> + */ + public static Matcher<Object> withDocumentName(final String name) { + return new BoundedMatcher<Object, FileSystemObject>(FileSystemObject.class) { + + @Override + protected boolean matchesSafely(FileSystemObject systemObj) { + return name.equals(systemObj.getName()); + } + + @Override + public void describeTo(Description description) { + description.appendText("with name: " + name); + } + }; + } + + /** + * Returns a Matcher<View> asserting that a data item is not in an adapter + * @param dataMatcher + * @return Matcher<View> + */ + private static Matcher<View> withAdaptedData(final Matcher<Object> dataMatcher) { + return new TypeSafeMatcher<View>() { + + @Override + public void describeTo(Description description) { + description.appendText("with class name: "); + dataMatcher.describeTo(description); + } + + @Override + public boolean matchesSafely(View view) { + if (!(view instanceof AdapterView)) { + return false; + } + + @SuppressWarnings("rawtypes") + Adapter adapter = ((AdapterView) view).getAdapter(); + for (int i = 0; i < adapter.getCount(); i++) { + if (dataMatcher.matches(adapter.getItem(i))) { + return true; + } + } + return false; + } + }; + } + + private void pauseForProviderToLoad() throws InterruptedException { + Thread.sleep(2000); // need time for Activity to initialize getProviderList() + } +} diff --git a/androidTest/src/com/cyanogenmod/filemanager/activities/WelcomeActivityTest.java b/androidTest/src/com/cyanogenmod/filemanager/activities/WelcomeActivityTest.java new file mode 100644 index 00000000..7eea3590 --- /dev/null +++ b/androidTest/src/com/cyanogenmod/filemanager/activities/WelcomeActivityTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.filemanager.activities; + +import com.cyanogenmod.filemanager.R; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.app.Activity; +import android.support.test.espresso.action.ViewActions; +import android.support.test.espresso.matcher.ViewMatchers; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.SmallTest; +import android.widget.TextView; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; +import static android.support.test.espresso.action.ViewActions.typeText; +import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; +import static android.support.test.espresso.matcher.ViewMatchers.Visibility; + +/** + * Basic tests showcasing simple view matchers and actions like {@link ViewMatchers#withId}, + * {@link ViewActions#click} and {@link ViewActions#typeText}. + * <p> + * Note that there is no need to tell Espresso that a view is in a different {@link Activity}. + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class WelcomeActivityTest { + + /** + * A JUnit {@link Rule @Rule} to launch your activity under test. This is a replacement + * for {@link ActivityInstrumentationTestCase2}. + * <p> + * Rules are interceptors which are executed for each test method and will run before + * any of your setup code in the {@link Before @Before} method. + * <p> + * {@link ActivityTestRule} will create and launch of the activity for you and also expose + * the activity under test. To get a reference to the activity you can use + * the {@link ActivityTestRule#getActivity()} method. + */ + @Rule + public ActivityTestRule<WelcomeActivity> mActivityRule = new ActivityTestRule<>( + WelcomeActivity.class); + + /** + * This test goes through the welcome screens and tries clicking connect button. + */ + @Test + public void testClickConnectCloud() { + goThroughWelcomePages(); + onView(withId(R.id.dismiss_card)).perform(click()); + onView(withId(R.id.dismiss_card)).check(doesNotExist()); + } + + /** + * This test goes back and forth the welcome, verifying texts and buttons. + */ + @Test + public void testClickNextOnWelcomePage() { + goThroughWelcomePages(); + + onView(withId(R.id.prevButton)).perform(click()); + + // Third page, to go back to the second page + onView(withId(R.id.nextButton)).check(matches(isDisplayed())); + onView(withId(R.id.pagination)).check(matches(isDisplayed())); + onView(withId(R.id.prevButton)).perform(click()); + + // Second page, to go back to the first page + onView(withId(R.id.titleMessageOne)).check(matches(withText(R.string.second_title))); + onView(withId(R.id.bottomMessageOne)).check(matches(withText(R.string.first_message))); + onView(withId(R.id.nextButton)).check(matches(isDisplayed())); + onView(withId(R.id.pagination)).check(matches(isDisplayed())); + onView(withId(R.id.prevButton)).perform(click()); + + goThroughWelcomePages(); + + onView(withId(R.id.nextButton)).perform(click()); + } + + /** + * Helper function. + */ + private void goThroughWelcomePages() { + // First page + onView(withId(R.id.welcome_textview_0)).check(matches(withText(R.string.welcome_to))); + onView(withId(R.id.welcome_textview_1)).check(matches(withText(R.string.file))); + onView(withId(R.id.welcome_textview_2)).check(matches(withText(R.string.manager))); + onView(withId(R.id.welcome_textview_3)).check(matches(withText(R.string.welcome_desc))); + onView(withId(R.id.prevButton)).check(matches(withEffectiveVisibility(Visibility.INVISIBLE))); + onView(withId(R.id.pagination)).check(matches(isDisplayed())); + onView(withId(R.id.nextButton)).perform(click()); + // Second page + onView(withId(R.id.titleMessageOne)).check(matches(withText(R.string.second_title))); + onView(withId(R.id.bottomMessageOne)).check(matches(withText(R.string.first_message))); + onView(withId(R.id.prevButton)).check(matches(isDisplayed())); + onView(withId(R.id.pagination)).check(matches(isDisplayed())); + onView(withId(R.id.nextButton)).perform(click()); + // Third page + onView(withId(R.id.prevButton)).check(matches(isDisplayed())); + onView(withId(R.id.pagination)).check(matches(isDisplayed())); + onView(withId(R.id.nextButton)).perform(click()); + // Last page + onView(withId(R.id.dismiss_card)).check(matches(withText(R.string.connect_now))); + onView(withId(R.id.cardHeaderText)).check(matches(withText(R.string.add_cloud_storage))); + onView(withId(R.id.cardChildText)).check(matches(withText(R.string.oobe_add_cloud_storage_desc))); + onView(withId(R.id.nextButton)).check(matches(isDisplayed())); + onView(withId(R.id.pagination)).check(matches(isDisplayed())); + } +} diff --git a/src/com/cyanogenmod/filemanager/activities/MainActivity.java b/src/com/cyanogenmod/filemanager/activities/MainActivity.java index bd86fdef..51726a67 100755 --- a/src/com/cyanogenmod/filemanager/activities/MainActivity.java +++ b/src/com/cyanogenmod/filemanager/activities/MainActivity.java @@ -32,6 +32,7 @@ import android.graphics.drawable.StateListDrawable; import android.net.Uri; import android.nfc.NfcAdapter; import android.os.Bundle; +import android.support.annotation.VisibleForTesting; import android.support.design.widget.NavigationView; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; @@ -425,7 +426,8 @@ public class MainActivity extends ActionBarActivity } } - private boolean isCurrentFragment(FragmentType fragmentType) { + @VisibleForTesting + protected boolean isCurrentFragment(FragmentType fragmentType) { if (fragmentType == FragmentType.HOME) { return getSupportFragmentManager().getFragments().size() <= 0; } else { |