Skip to content

Commit 71cdfc6

Browse files
author
irgendeinich
committed
Make tests work on emulator
Fix crash when accessing pdfView before fragment is created
1 parent c5e9f46 commit 71cdfc6

File tree

6 files changed

+104
-41
lines changed

6 files changed

+104
-41
lines changed

android/src/main/java/com/pspdfkit/react/TestingModule.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ public static void resetValues() {
3737

3838
public static String getValue(@NonNull String key) throws InterruptedException {
3939
synchronized (values) {
40-
while (!values.containsKey(key)) {
41-
values.wait(1000);
40+
if (!values.containsKey(key)) {
41+
values.wait(60000);
42+
if (!values.containsKey(key)) {
43+
throw new IllegalArgumentException("Key " + key + " was not found.");
44+
}
4245
}
4346
return values.get(key);
4447
}

android/src/main/java/com/pspdfkit/views/PdfView.java

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,16 @@
4949
import java.util.List;
5050
import java.util.concurrent.Callable;
5151

52+
import io.reactivex.ObservableSource;
5253
import io.reactivex.Single;
5354
import io.reactivex.android.schedulers.AndroidSchedulers;
55+
import io.reactivex.disposables.CompositeDisposable;
5456
import io.reactivex.disposables.Disposable;
5557
import io.reactivex.functions.Action;
5658
import io.reactivex.functions.Consumer;
59+
import io.reactivex.functions.Function;
5760
import io.reactivex.schedulers.Schedulers;
61+
import io.reactivex.subjects.BehaviorSubject;
5862

5963
/**
6064
* This view displays a {@link com.pspdfkit.ui.PdfFragment} and all associated toolbars.
@@ -79,7 +83,12 @@ public class PdfView extends FrameLayout {
7983

8084
private PdfThumbnailBar pdfThumbnailBar;
8185

86+
@NonNull
87+
private CompositeDisposable pendingFragmentActions = new CompositeDisposable();
88+
89+
@Nullable
8290
private PdfFragment fragment;
91+
private BehaviorSubject<PdfFragment> fragmentGetter = BehaviorSubject.create();
8392

8493
public PdfView(@NonNull Context context) {
8594
super(context);
@@ -218,6 +227,7 @@ private void setupFragment() {
218227
}
219228

220229
fragment = pdfFragment;
230+
fragmentGetter.onNext(fragment);
221231
}
222232
}
223233

@@ -280,6 +290,10 @@ public void removeFragment() {
280290
isActive = false;
281291

282292
fragment = null;
293+
fragmentGetter.onComplete();
294+
fragmentGetter = BehaviorSubject.create();
295+
pendingFragmentActions.dispose();
296+
pendingFragmentActions = new CompositeDisposable();
283297
}
284298

285299
void manuallyLayoutChildren() {
@@ -330,15 +344,25 @@ public EventDispatcher getEventDispatcher() {
330344
}
331345

332346
public void enterAnnotationCreationMode() {
333-
if (fragment != null) {
334-
fragment.enterAnnotationCreationMode();
335-
}
347+
pendingFragmentActions.add(fragmentGetter.take(1)
348+
.observeOn(Schedulers.io())
349+
.subscribe(new Consumer<PdfFragment>() {
350+
@Override
351+
public void accept(PdfFragment pdfFragment) {
352+
pdfFragment.enterAnnotationCreationMode();
353+
}
354+
}));
336355
}
337356

338357
public void exitCurrentlyActiveMode() {
339-
if (fragment != null) {
340-
fragment.exitCurrentlyActiveMode();
341-
}
358+
pendingFragmentActions.add(fragmentGetter.take(1)
359+
.observeOn(Schedulers.io())
360+
.subscribe(new Consumer<PdfFragment>() {
361+
@Override
362+
public void accept(PdfFragment pdfFragment) {
363+
pdfFragment.exitCurrentlyActiveMode();
364+
}
365+
}));
342366
}
343367

344368
public void saveCurrentDocument() {
@@ -354,9 +378,19 @@ public void saveCurrentDocument() {
354378
}
355379
}
356380

357-
public Single<List<Annotation>> getAnnotations(int pageIndex, @Nullable String type) {
358-
return fragment.getDocument().getAnnotationProvider().getAllAnnotationsOfType(getTypeFromString(type), pageIndex, 1)
359-
.toList();
381+
public Single<List<Annotation>> getAnnotations(final int pageIndex, @Nullable final String type) {
382+
return fragmentGetter.take(1).map(new Function<PdfFragment, PdfDocument>() {
383+
384+
@Override
385+
public PdfDocument apply(PdfFragment pdfFragment) {
386+
return pdfFragment.getDocument();
387+
}
388+
}).flatMap(new Function<PdfDocument, ObservableSource<Annotation>>() {
389+
@Override
390+
public ObservableSource<Annotation> apply(PdfDocument pdfDocument) {
391+
return pdfDocument.getAnnotationProvider().getAllAnnotationsOfType(getTypeFromString(type), pageIndex, 1);
392+
}
393+
}).toList();
360394
}
361395

362396
private EnumSet<AnnotationType> getTypeFromString(@Nullable String type) {
@@ -526,7 +560,7 @@ public void accept(FormElement formElement) {
526560
selectedIndices.add(indices.getInt(i));
527561
}
528562
choiceFormElement.setSelectedIndexes(selectedIndices);
529-
}catch (JSONException ex) {
563+
} catch (JSONException ex) {
530564
// This isn't an index maybe we can set a custom value on a combobox.
531565
if (formElement instanceof ComboBoxFormElement) {
532566
((ComboBoxFormElement) formElement).setCustomText(value);

samples/Catalog/android/app/src/androidTest/java/com/pspdfkit/react/PdfViewTest.java

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import com.pspdfkit.react.test.TestActivity;
1212
import com.pspdfkit.ui.PdfFragment;
1313

14-
import org.json.JSONArray;
1514
import org.json.JSONException;
1615
import org.json.JSONObject;
1716
import org.junit.Before;
@@ -21,8 +20,6 @@
2120

2221
import static android.support.test.espresso.Espresso.onView;
2322
import static android.support.test.espresso.action.ViewActions.click;
24-
import static android.support.test.espresso.assertion.ViewAssertions.matches;
25-
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
2623
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
2724
import static android.support.test.espresso.matcher.ViewMatchers.withId;
2825
import static android.support.test.espresso.matcher.ViewMatchers.withText;
@@ -43,35 +40,27 @@ public void clearAnnotationCreator() {
4340
}
4441

4542
@Test
46-
public void testAuthorNameProp() {
43+
public void testAuthorNameProp() throws InterruptedException {
4744
// AuthorNameScreen.js
4845

4946
// Pre Condition: No annotation creator is set.
5047
assertFalse(PSPDFKitPreferences.get(activityRule.getActivity()).isAnnotationCreatorSet());
5148

52-
// Wait until react is loaded.
53-
onView(isRoot()).perform(waitForView(withText("Test Cases")));
54-
55-
// Open the screen containing the logic we want to test.
56-
onView(withText("AuthorName")).perform(click());
49+
openExample("AuthorName");
5750

5851
// Check that annotation creator is set.
5952
assertEquals("Author", PSPDFKitPreferences.get(activityRule.getActivity()).getAnnotationCreator(null));
6053
}
6154

6255
@Test
63-
public void testEnterAndExitAnnotationCreation() {
56+
public void testEnterAndExitAnnotationCreation() throws InterruptedException {
6457
// AnnotationToolbarScreen.js
6558

66-
// Wait until react is loaded.
67-
onView(isRoot()).perform(waitForView(withText("Test Cases")));
68-
69-
// Open the screen containing the logic we want to test.
70-
onView(withText("AnnotationToolbar")).perform(click());
59+
openExample("AnnotationToolbar");
7160

7261
// Open toolbar and check that it is displayed,
7362
onView(withText("OPEN")).perform(click());
74-
onView(withId(R.id.pspdf__annotation_creation_toolbar)).check(matches(isDisplayed()));
63+
onView(isRoot()).perform(waitForView(withId(R.id.pspdf__annotation_creation_toolbar)));
7564

7665
// Now close it again.
7766
onView(withText("CLOSE")).perform(click());
@@ -82,11 +71,7 @@ public void testEnterAndExitAnnotationCreation() {
8271
public void testGetEmptyAnnotations() throws InterruptedException {
8372
// GetAnnotationsScreen.js
8473

85-
// Wait until react is loaded.
86-
onView(isRoot()).perform(waitForView(withText("Test Cases")));
87-
88-
// Open the screen containing the logic we want to test.
89-
onView(withText("GetAnnotations")).perform(click());
74+
openExample("GetAnnotations");
9075

9176
// Get annotations for first page should return nothing.
9277
onView(withText("GET")).perform(click());
@@ -99,11 +84,7 @@ public void testGetEmptyAnnotations() throws InterruptedException {
9984
public void testGetAnnotation() throws InterruptedException, JSONException {
10085
// GetAnnotationsScreen.js
10186

102-
// Wait until react is loaded.
103-
onView(isRoot()).perform(waitForView(withText("Test Cases")));
104-
105-
// Open the screen containing the logic we want to test.
106-
onView(withText("GetAnnotations")).perform(click());
87+
openExample("GetAnnotations");
10788

10889
PdfFragment fragment = (PdfFragment) activityRule.getActivity().getSupportFragmentManager().findFragmentByTag("PDF1");
10990
FreeTextAnnotation annotation = new FreeTextAnnotation(0, new RectF(0, 0, 100, 100), "Test");
@@ -112,9 +93,35 @@ public void testGetAnnotation() throws InterruptedException, JSONException {
11293
// Get annotations for first page should return nothing.
11394
onView(withText("GET")).perform(click());
11495
JSONObject annotations = new JSONObject(TestingModule.getValue("annotations"));
115-
96+
11697
JSONObject originalInstantJson = new JSONObject(annotation.toInstantJson());
11798
assertEquals(JsonUtilities.jsonObjectToMap(originalInstantJson), JsonUtilities.jsonObjectToMap(annotations.getJSONArray("annotations").getJSONObject(0)));
11899
}
119100

101+
@Test
102+
public void testGettingAnnotationsInComponentDidMount() throws InterruptedException {
103+
// GetAnnotationsScreen.js
104+
105+
openExample("GetAnnotations");
106+
107+
// The ComponentDidMount calls get annotations, make sure we don't crash.
108+
String annotations = TestingModule.getValue("on_load_annotations");
109+
110+
assertEquals("{\"annotations\":[]}", annotations);
111+
}
112+
113+
private void openExample(String exampleName) throws InterruptedException {
114+
// Wait until react is loaded.
115+
onView(isRoot()).perform(waitForView(withText("Test Cases")));
116+
117+
// Open the screen containing the logic we want to test.
118+
onView(withText(exampleName)).perform(click());
119+
120+
// Wait till react is ready.
121+
TestingModule.getValue("did_load");
122+
123+
// And just give it a moment more.
124+
Thread.sleep(500);
125+
}
126+
120127
}

samples/Catalog/testing/AnnotationToolbarScreen.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import React, { Component } from "react";
22

33
import {
44
View,
5-
Button
5+
Button,
6+
NativeModules
67
} from "react-native"
78

89
import PSPDFKitView from "react-native-pspdfkit";
@@ -14,6 +15,10 @@ export default class AnnotationToolbarScreen extends Component<{}> {
1415
};
1516
};
1617

18+
componentDidMount() {
19+
NativeModules.TestingModule.setValue("did_load", "true");
20+
}
21+
1722
render() {
1823
return (
1924
<View style={{ flex: 1 }}>

samples/Catalog/testing/AuthorNameScreen.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import React, { Component } from "react";
2-
2+
import {
3+
NativeModules
4+
} from "react-native"
35
import PSPDFKitView from "react-native-pspdfkit";
46

57
export default class AuthorNameScreen extends Component<{}> {
@@ -9,6 +11,10 @@ export default class AuthorNameScreen extends Component<{}> {
911
};
1012
};
1113

14+
componentDidMount() {
15+
NativeModules.TestingModule.setValue("did_load", "true");
16+
}
17+
1218
render() {
1319
return (
1420
<PSPDFKitView

samples/Catalog/testing/GetAnnotationsScreen.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ export default class GetAnnotationsScreen extends Component<{}> {
1515
};
1616
};
1717

18+
componentDidMount() {
19+
NativeModules.TestingModule.setValue("did_load", "true");
20+
// We want to make sure that immediately accessing the pdf view doesn't crash.
21+
this.refs.pdfView.getAnnotations(0, null).then(annotations => {
22+
NativeModules.TestingModule.setValue("on_load_annotations", JSON.stringify(annotations));
23+
})
24+
}
25+
1826
render() {
1927
return (
2028
<View style={{ flex: 1 }}>

0 commit comments

Comments
 (0)