Skip to content

Commit 3307c0a

Browse files
committed
fix automated tests
1 parent b50641b commit 3307c0a

File tree

1 file changed

+68
-132
lines changed

1 file changed

+68
-132
lines changed

app/src/androidTest/java/at/tomtasche/reader/test/MainActivityTests.java

Lines changed: 68 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,5 @@
11
package at.tomtasche.reader.test;
22

3-
import static androidx.test.espresso.Espresso.onView;
4-
import static androidx.test.espresso.action.ViewActions.clearText;
5-
import static androidx.test.espresso.action.ViewActions.click;
6-
import static androidx.test.espresso.action.ViewActions.typeText;
7-
import static androidx.test.espresso.assertion.ViewAssertions.matches;
8-
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
9-
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
10-
import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
11-
import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
12-
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
13-
import static androidx.test.espresso.matcher.ViewMatchers.withId;
14-
import static androidx.test.espresso.matcher.ViewMatchers.withText;
15-
import static org.hamcrest.Matchers.allOf;
16-
import static org.hamcrest.Matchers.anyOf;
17-
import static org.hamcrest.Matchers.equalTo;
18-
19-
import android.app.Activity;
203
import android.app.Instrumentation;
214
import android.content.Context;
225
import android.content.Intent;
@@ -29,7 +12,6 @@
2912
import androidx.core.content.FileProvider;
3013
import androidx.test.espresso.IdlingRegistry;
3114
import androidx.test.espresso.IdlingResource;
32-
import androidx.test.espresso.intent.Intents;
3315
import androidx.test.ext.junit.runners.AndroidJUnit4;
3416
import androidx.test.filters.LargeTest;
3517
import androidx.test.platform.app.InstrumentationRegistry;
@@ -49,12 +31,13 @@
4931
import java.io.IOException;
5032
import java.io.InputStream;
5133
import java.io.OutputStream;
34+
import java.lang.reflect.Field;
5235
import java.util.Map;
5336
import java.util.concurrent.CountDownLatch;
5437
import java.util.concurrent.TimeUnit;
5538
import java.util.concurrent.atomic.AtomicReference;
5639

57-
import at.tomtasche.reader.R;
40+
import at.tomtasche.reader.background.FileLoader;
5841
import at.tomtasche.reader.ui.EditActionModeCallback;
5942
import at.tomtasche.reader.ui.activity.MainActivity;
6043
import at.tomtasche.reader.ui.activity.DocumentFragment;
@@ -83,8 +66,6 @@ public void setUp() {
8366
// Close system dialogs which may cover our Activity.
8467
// Happens frequently on slow emulators.
8568
mainActivity.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
86-
87-
Intents.init();
8869

8970
// Log test setup for debugging
9071
Log.d("MainActivityTests", "setUp() called for test: " + getClass().getName());
@@ -93,8 +74,6 @@ public void setUp() {
9374
@After
9475
public void tearDown() {
9576
Log.d("MainActivityTests", "tearDown() called");
96-
97-
Intents.release();
9877

9978
if (null != m_idlingResource) {
10079
IdlingRegistry.getInstance().unregister(m_idlingResource);
@@ -150,78 +129,39 @@ public static void cleanupTestFiles() {
150129
}
151130

152131
@Test
153-
public void testODT() {
132+
public void testODT() throws InterruptedException {
154133
File testFile = s_testFiles.get("test.odt");
155134
Assert.assertNotNull(testFile);
156-
Context appCtx = InstrumentationRegistry.getInstrumentation().getTargetContext();
157-
Uri testFileUri = FileProvider.getUriForFile(appCtx, appCtx.getPackageName() + ".provider", testFile);
158-
Intents.intending(hasAction(Intent.ACTION_OPEN_DOCUMENT)).respondWith(
159-
new Instrumentation.ActivityResult(Activity.RESULT_OK,
160-
new Intent()
161-
.setData(testFileUri)
162-
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
163-
)
164-
);
165-
166-
onView(allOf(withId(R.id.menu_open), withContentDescription("Open document"), isDisplayed()))
167-
.perform(click());
168-
169-
// The menu item could be either Documents or Files.
170-
onView(allOf(withId(android.R.id.text1), anyOf(withText("Documents"), withText("Files")), isDisplayed()))
171-
.perform(click());
135+
MainActivity activity = mainActivityActivityTestRule.getActivity();
136+
DocumentFragment documentFragment = loadDocument(activity, testFile);
172137

173-
// next onView will be blocked until m_idlingResource is idle.
174-
onView(allOf(withId(R.id.menu_edit), withContentDescription("Edit document"), isEnabled()))
175-
.withFailureHandler((error, viewMatcher) -> {
176-
// fails on small screens, try again with overflow menu
177-
onView(allOf(withContentDescription("More options"), isDisplayed())).perform(click());
138+
PageView pageView = documentFragment.getPageView();
139+
Assert.assertNotNull(pageView);
140+
Assert.assertTrue("ODT should load", waitForPageLoaded(pageView, 10000));
178141

179-
onView(allOf(withId(R.id.menu_edit), withContentDescription("Edit document"), isDisplayed()))
180-
.perform(click());
181-
});
142+
String fileType = documentFragment.getLastFileType();
143+
Assert.assertNotNull(fileType);
144+
Assert.assertTrue("Expected ODT file type", fileType.startsWith("application/vnd.oasis.opendocument"));
182145
}
183146

184147
@Test
185-
public void testPDF() {
148+
public void testPDF() throws InterruptedException {
186149
File testFile = s_testFiles.get("dummy.pdf");
187150
Assert.assertNotNull(testFile);
188-
Context appCtx = InstrumentationRegistry.getInstrumentation().getTargetContext();
189-
Uri testFileUri = FileProvider.getUriForFile(appCtx, appCtx.getPackageName() + ".provider", testFile);
190-
Intents.intending(hasAction(Intent.ACTION_OPEN_DOCUMENT)).respondWith(
191-
new Instrumentation.ActivityResult(Activity.RESULT_OK,
192-
new Intent()
193-
.setData(testFileUri)
194-
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
195-
)
196-
);
197-
198-
onView(allOf(withId(R.id.menu_open), withContentDescription("Open document"), isDisplayed()))
199-
.perform(click());
200-
201-
// The menu item could be either Documents or Files.
202-
onView(allOf(withId(android.R.id.text1), anyOf(withText("Documents"), withText("Files")), isDisplayed()))
203-
.perform(click());
204-
205-
// next onView will be blocked until m_idlingResource is idle.
206-
207-
onView(allOf(withId(R.id.menu_edit), withContentDescription("Edit document"), isEnabled()))
208-
.withFailureHandler((error, viewMatcher) -> {
209-
// fails on small screens, try again with overflow menu
210-
onView(allOf(withContentDescription("More options"), isDisplayed())).perform(click());
151+
MainActivity activity = mainActivityActivityTestRule.getActivity();
152+
DocumentFragment documentFragment = loadDocument(activity, testFile);
211153

212-
onView(allOf(withId(R.id.menu_edit), withContentDescription("Edit document"), isDisplayed()))
213-
.perform(click());
214-
});
154+
PageView pageView = documentFragment.getPageView();
155+
Assert.assertNotNull(pageView);
156+
Assert.assertTrue("PDF should load", waitForPageLoaded(pageView, 10000));
215157

216-
try {
217-
Thread.sleep(10000);
218-
} catch (InterruptedException e) {
219-
throw new RuntimeException(e);
220-
}
158+
String fileType = documentFragment.getLastFileType();
159+
Assert.assertNotNull(fileType);
160+
Assert.assertTrue("Expected PDF file type", fileType.startsWith("application/pdf"));
221161
}
222162

223163
@Test
224-
public void testPasswordProtectedODT() {
164+
public void testPasswordProtectedODT() throws InterruptedException {
225165
File testFile = s_testFiles.get("password-test.odt");
226166
Assert.assertNotNull(testFile);
227167

@@ -237,52 +177,15 @@ public void testPasswordProtectedODT() {
237177
// Double-check we're using the right file
238178
Assert.assertEquals("password-test.odt file size mismatch", 12671L, testFile.length());
239179

240-
Context appCtx = InstrumentationRegistry.getInstrumentation().getTargetContext();
241-
Uri testFileUri = FileProvider.getUriForFile(appCtx, appCtx.getPackageName() + ".provider", testFile);
242-
Intents.intending(hasAction(Intent.ACTION_OPEN_DOCUMENT)).respondWith(
243-
new Instrumentation.ActivityResult(Activity.RESULT_OK,
244-
new Intent()
245-
.setData(testFileUri)
246-
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
247-
)
248-
);
249-
250-
onView(allOf(withId(R.id.menu_open), withContentDescription("Open document"), isDisplayed()))
251-
.perform(click());
252-
253-
onView(allOf(withId(android.R.id.text1), anyOf(withText("Documents"), withText("Files")), isDisplayed()))
254-
.perform(click());
255-
256-
// Wait for the password dialog to appear
257-
onView(withText("This document is password-protected"))
258-
.check(matches(isDisplayed()));
259-
260-
// Enter wrong password first
261-
onView(withClassName(equalTo("android.widget.EditText")))
262-
.perform(typeText("wrongpassword"));
263-
264-
onView(withId(android.R.id.button1))
265-
.perform(click());
266-
267-
// Should show password dialog again for wrong password
268-
onView(withText("This document is password-protected"))
269-
.check(matches(isDisplayed()));
270-
271-
// Clear the text field and enter correct password
272-
onView(withClassName(equalTo("android.widget.EditText")))
273-
.perform(clearText(), typeText("passwort"));
274-
275-
onView(withId(android.R.id.button1))
276-
.perform(click());
180+
MainActivity activity = mainActivityActivityTestRule.getActivity();
181+
DocumentFragment documentFragment = loadDocument(activity, testFile);
277182

278-
// Check if edit button becomes available (indicating successful load)
279-
onView(allOf(withId(R.id.menu_edit), withContentDescription("Edit document"), isEnabled()))
280-
.withFailureHandler((error, viewMatcher) -> {
281-
onView(allOf(withContentDescription("More options"), isDisplayed())).perform(click());
183+
setPasswordAndReload(documentFragment, "passwort");
282184

283-
onView(allOf(withId(R.id.menu_edit), withContentDescription("Edit document"), isDisplayed()))
284-
.perform(click());
285-
});
185+
PageView pageView = documentFragment.getPageView();
186+
Assert.assertNotNull(pageView);
187+
Assert.assertTrue("Password-protected ODT should load with correct password",
188+
waitForPageLoaded(pageView, 10000));
286189
}
287190

288191
@Test
@@ -355,6 +258,25 @@ private boolean waitForLastResult(DocumentFragment fragment, long timeoutMs) thr
355258
return false;
356259
}
357260

261+
private void setPasswordAndReload(DocumentFragment documentFragment, String password) {
262+
FileLoader.Result result = getLastResult(documentFragment);
263+
Assert.assertNotNull(result);
264+
Assert.assertNotNull(result.options);
265+
result.options.password = password;
266+
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> documentFragment.reloadUri(false));
267+
}
268+
269+
private FileLoader.Result getLastResult(DocumentFragment documentFragment) {
270+
try {
271+
Field field = DocumentFragment.class.getDeclaredField("lastResult");
272+
field.setAccessible(true);
273+
return (FileLoader.Result) field.get(documentFragment);
274+
} catch (NoSuchFieldException | IllegalAccessException e) {
275+
Assert.fail("Failed to access lastResult: " + e.getMessage());
276+
return null;
277+
}
278+
}
279+
358280
private void enterEditMode(MainActivity activity, DocumentFragment documentFragment) {
359281
AtomicReference<Boolean> started = new AtomicReference<>(false);
360282
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
@@ -364,27 +286,41 @@ private void enterEditMode(MainActivity activity, DocumentFragment documentFragm
364286
Assert.assertTrue("Failed to enter edit mode", started.get());
365287
}
366288

367-
private boolean waitForEditableState(PageView pageView, boolean expected, long timeoutMs)
368-
throws InterruptedException {
289+
private boolean waitForPageLoaded(PageView pageView, long timeoutMs) throws InterruptedException {
369290
long startMs = SystemClock.elapsedRealtime();
370291
while (SystemClock.elapsedRealtime() - startMs < timeoutMs) {
371-
if (expected == isEditableDom(pageView)) {
292+
String url = getPageViewUrl(pageView);
293+
if (url != null && !url.isEmpty() && !"about:blank".equals(url)) {
372294
return true;
373295
}
374296
SystemClock.sleep(250);
375297
}
376298
return false;
377299
}
378300

379-
private boolean waitForNonEditableState(PageView pageView, long timeoutMs) throws InterruptedException {
301+
private String getPageViewUrl(PageView pageView) throws InterruptedException {
302+
AtomicReference<String> url = new AtomicReference<>();
303+
CountDownLatch latch = new CountDownLatch(1);
304+
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
305+
url.set(pageView.getUrl());
306+
latch.countDown();
307+
});
308+
if (!latch.await(5, TimeUnit.SECONDS)) {
309+
Assert.fail("Timed out waiting for WebView URL");
310+
}
311+
return url.get();
312+
}
313+
314+
private boolean waitForEditableState(PageView pageView, boolean expected, long timeoutMs)
315+
throws InterruptedException {
380316
long startMs = SystemClock.elapsedRealtime();
381317
while (SystemClock.elapsedRealtime() - startMs < timeoutMs) {
382-
if (isEditableDom(pageView)) {
383-
return false;
318+
if (expected == isEditableDom(pageView)) {
319+
return true;
384320
}
385321
SystemClock.sleep(250);
386322
}
387-
return true;
323+
return false;
388324
}
389325

390326
private boolean isEditableDom(PageView pageView) throws InterruptedException {

0 commit comments

Comments
 (0)