Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e74b3b8 authored by Aga Wronska's avatar Aga Wronska Committed by Android (Google) Code Review
Browse files

Merge "Add Search View UI tests"

parents bd925dac 619f3be0
Loading
Loading
Loading
Loading
+293 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source 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.android.documentsui;

import static com.android.documentsui.StubProvider.DEFAULT_AUTHORITY;
import static com.android.documentsui.StubProvider.ROOT_0_ID;
import static com.android.documentsui.StubProvider.ROOT_1_ID;

import android.app.Instrumentation;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Configurator;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.Until;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.view.MotionEvent;

import com.android.documentsui.model.RootInfo;

@LargeTest
public class SearchViewUiTest extends InstrumentationTestCase {

    private static final int TIMEOUT = 5000;
    private static final String TAG = "SearchViewUiTest";
    private static final String TARGET_PKG = "com.android.documentsui";
    private static final String LAUNCHER_PKG = "com.android.launcher";

    private UiBot mBot;
    private UiDevice mDevice;
    private Context mContext;
    private ContentResolver mResolver;
    private DocumentsProviderHelper mDocsHelper;
    private ContentProviderClient mClient;
    private RootInfo mRoot_0;
    private RootInfo mRoot_1;

    private UiObject mSearchView;
    private UiObject mSearchTextField;
    private UiObject mDocsList;
    private UiObject mMessageTextView;
    private UiObject mSearchIcon;

    public void setUp() throws Exception {
        // Initialize UiDevice instance.
        Instrumentation instrumentation = getInstrumentation();

        mDevice = UiDevice.getInstance(instrumentation);

        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);

        // Start from the home screen.
        mDevice.pressHome();
        mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), TIMEOUT);

        // NOTE: Must be the "target" context, else security checks in content provider will fail.
        mContext = instrumentation.getTargetContext();
        mResolver = mContext.getContentResolver();

        mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
        mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);

        // Launch app.
        Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(TARGET_PKG);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        mContext.startActivity(intent);
        // Wait for the app to appear.
        mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), TIMEOUT);
        mDevice.waitForIdle();

        mBot = new UiBot(mDevice, TIMEOUT);

        resetStorage(); // Just incase a test failed and tearDown didn't happen.

        initUiObjects();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        mDevice.pressBack();
        resetStorage();
        mClient.release();
    }

    private void resetStorage() throws RemoteException {
        mClient.call("clear", null, null);
        // TODO: Would be nice to have an event to wait on here.
        mDevice.waitForIdle();
    }

    private void initTestFiles() throws RemoteException {
        mRoot_0 = mDocsHelper.getRoot(ROOT_0_ID);
        mRoot_1 = mDocsHelper.getRoot(ROOT_1_ID);

        mDocsHelper.createDocument(mRoot_0, "text/plain", "file10.log");
        mDocsHelper.createDocument(mRoot_0, "image/png", "file1.png");
        mDocsHelper.createDocument(mRoot_0, "text/csv", "file2.csv");

        mDocsHelper.createDocument(mRoot_1, "text/plain", "anotherFile0.log");
        mDocsHelper.createDocument(mRoot_1, "text/plain", "poodles.text");
    }

    private void initUiObjects() {
        mSearchView = mBot.findSearchView();
        mSearchTextField = mBot.findSearchViewTextField();
        mDocsList = mBot.findDocumentsList();
        mMessageTextView = mBot.findMessageTextView();
        mSearchIcon = mBot.findSearchViewIcon();
    }

    public void testSearchViewExpandsOnClick() throws Exception {
        assertTrue(mSearchIcon.exists());
        assertFalse(mSearchTextField.exists());

        mSearchView.click();

        assertTrue(mSearchTextField.exists());
        assertTrue(mSearchTextField.isFocused());
        assertFalse(mSearchIcon.exists());
    }

    public void testSearchViewCollapsesOnBack() throws Exception {
        assertTrue(mSearchIcon.exists());
        assertFalse(mSearchTextField.exists());

        mSearchView.click();

        mDevice.pressBack();

        assertTrue(mSearchIcon.exists());
        assertFalse(mSearchTextField.exists());
    }

    public void testSearchViewClearsTextOnBack() throws Exception {
        assertTrue(mSearchIcon.exists());
        assertFalse(mSearchTextField.exists());

        String query = "file2";
        mSearchView.click();
        mSearchTextField.setText(query);

        assertSearchTextField(true, query);

        mDevice.pressBack();

        assertTrue(mSearchIcon.exists());
        assertFalse(mSearchTextField.exists());
    }

    public void testSearchFound() throws Exception {
        initTestFiles();

        mBot.openRoot(ROOT_0_ID);

        assertDefaultTestDir0();

        String query = "file1";
        mSearchView.click();
        mSearchTextField.setText(query);

        assertTrue(mDocsList.exists());
        assertSearchTextField(true, query);

        mDevice.pressEnter();

        assertTrue(mDocsList.exists());
        assertEquals(2, mDocsList.getChildCount());
        mBot.assertHasDocuments("file1.png", "file10.log");
        assertSearchTextField(false, query);
    }

    public void testSearchFoundClearsOnBack() throws Exception {
        initTestFiles();

        mBot.openRoot(ROOT_0_ID);

        assertDefaultTestDir0();

        String query = "file1";
        mSearchView.click();
        mSearchTextField.setText(query);

        mDevice.pressEnter();
        mDevice.pressBack();

        assertDefaultTestDir0();
    }

    public void testSearchNoResults() throws Exception {
        initTestFiles();

        mBot.openRoot(ROOT_0_ID);

        assertDefaultTestDir0();

        String query = "chocolate";
        mSearchView.click();
        mSearchTextField.setText(query);

        mDevice.pressEnter();

        assertFalse(mDocsList.exists());
        assertTrue(mMessageTextView.exists());
        assertEquals(mContext.getString(R.string.empty), mMessageTextView.getText());
        assertSearchTextField(false, query);
    }

    public void testSearchNoResultsClearsOnBack() throws Exception {
        initTestFiles();

        mBot.openRoot(ROOT_0_ID);

        assertDefaultTestDir0();

        String query = "chocolate";
        mSearchView.click();
        mSearchTextField.setText(query);

        mDevice.pressEnter();
        mDevice.pressBack();

        assertDefaultTestDir0();
    }

    public void testSearchFoundClearsDirectoryChange() throws Exception {
        initTestFiles();

        mBot.openRoot(ROOT_0_ID);

        assertDefaultTestDir0();

        String query = "file1";
        mSearchView.click();
        mSearchTextField.setText(query);

        mDevice.pressEnter();

        mBot.openRoot(ROOT_1_ID);

        // This assert is failing right now - fix will come with SearchManager refactoring
        // assertDefaultTestDir1();
        //
        // mBot.openRoot(ROOT_0_ID);
        //
        // assertDefaultTestDir0();
    }

    private void assertDefaultTestDir0() throws UiObjectNotFoundException {
        assertTrue(mSearchIcon.exists());
        assertTrue(mDocsList.exists());
        assertFalse(mSearchTextField.exists());
        assertEquals(3, mDocsList.getChildCount());
        mBot.assertHasDocuments("file2.csv", "file1.png", "file10.log");
    }

    private void assertDefaultTestDir1() throws UiObjectNotFoundException {
        assertTrue(mSearchIcon.exists());
        assertFalse(mSearchTextField.exists());
        assertTrue(mDocsList.exists());
        assertEquals(2, mDocsList.getChildCount());
        mBot.assertHasDocuments("anotherFile0.log", "poodles.txt");
    }

    private void assertSearchTextField(boolean isFocused, String query)
            throws UiObjectNotFoundException {
        assertFalse(mSearchIcon.exists());
        assertTrue(mSearchTextField.exists());
        assertEquals(isFocused, mSearchTextField.isFocused());
        assertEquals(query, mSearchTextField.getText());
    }
}
+25 −1
Original line number Diff line number Diff line
@@ -135,7 +135,8 @@ public class StubProvider extends DocumentsProvider {
            final RootInfo info = entry.getValue();
            final RowBuilder row = result.newRow();
            row.add(Root.COLUMN_ROOT_ID, id);
            row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD);
            row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD
                    | Root.FLAG_SUPPORTS_SEARCH);
            row.add(Root.COLUMN_TITLE, id);
            row.add(Root.COLUMN_DOCUMENT_ID, info.document.documentId);
            row.add(Root.COLUMN_AVAILABLE_BYTES, info.getRemainingCapacity());
@@ -269,6 +270,29 @@ public class StubProvider extends DocumentsProvider {
        return result;
    }

    @Override
    public Cursor querySearchDocuments(String rootId, String query, String[] projection)
            throws FileNotFoundException {

        StubDocument parentDocument = mRoots.get(rootId).document;
        if (parentDocument == null || parentDocument.file.isFile()) {
            throw new FileNotFoundException();
        }

        final MatrixCursor result = new MatrixCursor(
                projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);

        for (File file : parentDocument.file.listFiles()) {
            if (file.getName().toLowerCase().contains(query)) {
                StubDocument document = mStorage.get(getDocumentIdForFile(file));
                if (document != null) {
                    includeDocument(result, document);
                }
            }
        }
        return result;
    }

    @Override
    public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
            throws FileNotFoundException {
+37 −0
Original line number Diff line number Diff line
@@ -187,4 +187,41 @@ class UiBot {
        mDevice.wait(Until.findObject(selector), mTimeout);
        return mDevice.findObject(selector);
    }

    private UiObject findObject(String resourceId) {
        final UiSelector object = new UiSelector().resourceId(resourceId);
        return mDevice.findObject(object);
    }

    private UiObject findObject(String parentResourceId, String childResourceId) {
        final UiSelector selector = new UiSelector()
                .resourceId(parentResourceId)
                .childSelector(new UiSelector().resourceId(childResourceId));
        return mDevice.findObject(selector);
    }

    UiObject findDocumentsList() {
        return findObject(
                "com.android.documentsui:id/container_directory",
                "com.android.documentsui:id/list");
    }

    UiObject findSearchView() {
        return findObject("com.android.documentsui:id/menu_search");
    }

    UiObject findSearchViewTextField() {
        return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
    }

    UiObject findSearchViewIcon() {
        return findObject("com.android.documentsui:id/menu_search", "android:id/search_button");
    }

    UiObject findMessageTextView() {
        return findObject(
                "com.android.documentsui:id/container_directory",
                "com.android.documentsui:id/message");
    }

}