1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.documentsui;
18
19import static junit.framework.Assert.assertTrue;
20
21import static org.junit.Assert.assertEquals;
22
23import android.content.Intent;
24import android.net.Uri;
25import android.os.Parcelable;
26import android.provider.DocumentsContract;
27import android.provider.DocumentsContract.Path;
28import android.support.test.filters.MediumTest;
29import android.support.test.runner.AndroidJUnit4;
30
31import com.android.documentsui.base.DocumentStack;
32import com.android.documentsui.base.RootInfo;
33import com.android.documentsui.base.Shared;
34import com.android.documentsui.dirlist.DocumentDetails;
35import com.android.documentsui.files.LauncherActivity;
36import com.android.documentsui.sorting.SortDimension;
37import com.android.documentsui.sorting.SortModel;
38import com.android.documentsui.testing.DocumentStackAsserts;
39import com.android.documentsui.testing.Roots;
40import com.android.documentsui.testing.TestEnv;
41import com.android.documentsui.testing.TestEventHandler;
42import com.android.documentsui.testing.TestProvidersAccess;
43
44import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
47
48import java.util.Arrays;
49
50/**
51 * A unit test *for* AbstractActionHandler, not an abstract test baseclass.
52 */
53@RunWith(AndroidJUnit4.class)
54@MediumTest
55public class AbstractActionHandlerTest {
56
57    private TestActivity mActivity;
58    private TestEnv mEnv;
59    private AbstractActionHandler<TestActivity> mHandler;
60
61    @Before
62    public void setUp() {
63        mEnv = TestEnv.create();
64        mActivity = TestActivity.create(mEnv);
65        mHandler = new AbstractActionHandler<TestActivity>(
66                mActivity,
67                mEnv.state,
68                mEnv.providers,
69                mEnv.docs,
70                mEnv.searchViewManager,
71                mEnv::lookupExecutor,
72                mEnv.injector) {
73
74            @Override
75            public void openRoot(RootInfo root) {
76                throw new UnsupportedOperationException();
77            }
78
79            @Override
80            public boolean openDocument(DocumentDetails doc, @ViewType int type,
81                    @ViewType int fallback) {
82                throw new UnsupportedOperationException();
83            }
84
85            @Override
86            public void initLocation(Intent intent) {
87                throw new UnsupportedOperationException();
88            }
89
90            @Override
91            protected void launchToDefaultLocation() {
92                throw new UnsupportedOperationException();
93            }
94        };
95    }
96
97    @Test
98    public void testOpenNewWindow() {
99        DocumentStack path = new DocumentStack(Roots.create("123"));
100        mHandler.openInNewWindow(path);
101
102        Intent expected = LauncherActivity.createLaunchIntent(mActivity);
103        expected.putExtra(Shared.EXTRA_STACK, (Parcelable) path);
104        Intent actual = mActivity.startActivity.getLastValue();
105        assertEquals(expected.toString(), actual.toString());
106    }
107
108    @Test
109    public void testOpensContainerDocuments_jumpToNewLocation() throws Exception {
110        if (!mEnv.features.isLaunchToDocumentEnabled()) {
111            return;
112        }
113
114        mEnv.populateStack();
115
116        mEnv.searchViewManager.isSearching = true;
117        mEnv.docs.nextPath = new Path(
118                TestProvidersAccess.HOME.rootId,
119                Arrays.asList(TestEnv.FOLDER_1.documentId, TestEnv.FOLDER_2.documentId));
120        mEnv.docs.nextDocuments = Arrays.asList(TestEnv.FOLDER_1, TestEnv.FOLDER_2);
121
122        mHandler.openContainerDocument(TestEnv.FOLDER_2);
123
124        mEnv.beforeAsserts();
125
126        assertEquals(mEnv.docs.nextPath.getPath().size(), mEnv.state.stack.size());
127        assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.peek());
128    }
129
130
131    @Test
132    public void testOpensContainerDocuments_pushToRootDoc_NoFindPathSupport() throws Exception {
133        mEnv.populateStack();
134
135        mEnv.searchViewManager.isSearching = true;
136        mEnv.docs.nextDocuments = Arrays.asList(TestEnv.FOLDER_1, TestEnv.FOLDER_2);
137
138        mHandler.openContainerDocument(TestEnv.FOLDER_2);
139
140        mEnv.beforeAsserts();
141
142        assertEquals(2, mEnv.state.stack.size());
143        assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.pop());
144        assertEquals(TestEnv.FOLDER_0, mEnv.state.stack.pop());
145    }
146
147    @Test
148    public void testOpensDocument_AssertionErrorIfAlreadyInStack() throws Exception {
149        mEnv.populateStack();
150        boolean threw = false;
151        try {
152            mEnv.state.stack.push(TestEnv.FOLDER_0);
153        } catch (AssertionError e) {
154            threw = true;
155        }
156        assertTrue(threw);
157    }
158
159    @Test
160    public void testLaunchToDocuments() throws Exception {
161        if (!mEnv.features.isLaunchToDocumentEnabled()) {
162            return;
163        }
164
165        mEnv.docs.nextIsDocumentsUri = true;
166        mEnv.docs.nextPath = new Path(
167                TestProvidersAccess.HOME.rootId,
168                Arrays.asList(
169                        TestEnv.FOLDER_0.documentId,
170                        TestEnv.FOLDER_1.documentId,
171                        TestEnv.FILE_GIF.documentId));
172        mEnv.docs.nextDocuments =
173                Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1, TestEnv.FILE_GIF);
174
175        mActivity.refreshCurrentRootAndDirectory.assertNotCalled();
176        assertTrue(mHandler.launchToDocument(TestEnv.FILE_GIF.derivedUri));
177
178        mEnv.beforeAsserts();
179
180        DocumentStackAsserts.assertEqualsTo(mEnv.state.stack, TestProvidersAccess.HOME,
181                Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1));
182        mActivity.refreshCurrentRootAndDirectory.assertCalled();
183    }
184
185    @Test
186    public void testLaunchToDocuments_convertsTreeUriToDocumentUri() throws Exception {
187        if (!mEnv.features.isLaunchToDocumentEnabled()) {
188            return;
189        }
190
191        mEnv.docs.nextIsDocumentsUri = true;
192        mEnv.docs.nextPath = new Path(
193                TestProvidersAccess.HOME.rootId,
194                Arrays.asList(
195                        TestEnv.FOLDER_0.documentId,
196                        TestEnv.FOLDER_1.documentId,
197                        TestEnv.FILE_GIF.documentId));
198        mEnv.docs.nextDocuments =
199                Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1, TestEnv.FILE_GIF);
200
201        final Uri treeBaseUri = DocumentsContract.buildTreeDocumentUri(
202                TestProvidersAccess.HOME.authority, TestEnv.FOLDER_0.documentId);
203        final Uri treeDocUri = DocumentsContract.buildDocumentUriUsingTree(
204                treeBaseUri, TestEnv.FILE_GIF.documentId);
205        assertTrue(mHandler.launchToDocument(treeDocUri));
206
207        mEnv.beforeAsserts();
208
209        DocumentStackAsserts.assertEqualsTo(mEnv.state.stack, TestProvidersAccess.HOME,
210                Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1));
211        mEnv.docs.lastUri.assertLastArgument(TestEnv.FILE_GIF.derivedUri);
212        mActivity.refreshCurrentRootAndDirectory.assertCalled();
213    }
214
215    @Test
216    public void testLoadChildrenDocuments() throws Exception {
217        mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
218        mEnv.state.stack.push(TestEnv.FOLDER_0);
219
220        mEnv.state.sortModel.sortByUser(
221                SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING);
222
223        mEnv.mockProviders.get(TestProvidersAccess.HOME.authority)
224                .setNextChildDocumentsReturns(TestEnv.FILE_APK, TestEnv.FILE_GIF);
225
226        mHandler.loadDocumentsForCurrentStack();
227        mActivity.loaderManager.runAsyncTaskLoader(AbstractActionHandler.LOADER_ID);
228
229        assertEquals(2, mEnv.model.getItemCount());
230        String[] modelIds = mEnv.model.getModelIds();
231        assertEquals(TestEnv.FILE_APK, mEnv.model.getDocument(modelIds[0]));
232        assertEquals(TestEnv.FILE_GIF, mEnv.model.getDocument(modelIds[1]));
233    }
234
235    @Test
236    public void testLoadChildrenDocuments_failsWithNonRecentsAndEmptyStack() throws Exception {
237        mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
238
239        mEnv.mockProviders.get(TestProvidersAccess.HOME.authority)
240                .setNextChildDocumentsReturns(TestEnv.FILE_APK, TestEnv.FILE_GIF);
241
242        TestEventHandler<Model.Update> listener = new TestEventHandler<>();
243        mEnv.model.addUpdateListener(listener::accept);
244
245        mHandler.loadDocumentsForCurrentStack();
246
247        assertTrue(listener.getLastValue().hasException());
248    }
249}
250