Skip to content

Commit a6c8983

Browse files
committed
[wpe] Add prompt dialog and instrumentation tests
Add rest of the dialogs and ensure their behavior matches Android system webview by implementing instrumentation tests to guarantee correct results Patch also introduces bunch of instrumentation test helper classes and functions
1 parent 18c568d commit a6c8983

File tree

14 files changed

+583
-102
lines changed

14 files changed

+583
-102
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.wpe.wpeview;
2+
3+
import android.util.Log;
4+
5+
import androidx.annotation.NonNull;
6+
7+
import com.wpe.wpeview.util.CallbackHelper;
8+
9+
import java.util.concurrent.TimeUnit;
10+
import java.util.concurrent.TimeoutException;
11+
12+
public class TestWPEViewClient implements WPEViewClient {
13+
14+
private final CallbackHelper onPageFinishedHelper;
15+
private final OnEvaluateJavaScriptResultHelper onEvaluateJavascriptResultHelper;
16+
17+
public TestWPEViewClient() {
18+
onPageFinishedHelper = new CallbackHelper();
19+
onEvaluateJavascriptResultHelper = new OnEvaluateJavaScriptResultHelper();
20+
}
21+
22+
CallbackHelper getOnPageFinishedHelper() { return onPageFinishedHelper; }
23+
OnEvaluateJavaScriptResultHelper getOnEvaluateJavascriptResultHelper() { return onEvaluateJavascriptResultHelper; }
24+
25+
public static class OnEvaluateJavaScriptResultHelper extends CallbackHelper {
26+
private String result;
27+
public void evaluateJavascript(WPEView view, String script) {
28+
view.evaluateJavascript(script, this::notifyCalled);
29+
}
30+
31+
public boolean hasValue() { return result != null; }
32+
33+
public String getResultAndClear() {
34+
assert hasValue();
35+
String res = result;
36+
result = null;
37+
return res;
38+
}
39+
40+
public boolean waitUntilHasValue(long timeout, TimeUnit unit) throws TimeoutException {
41+
// Reads and writes are atomic for reference variables in java, this is thread safe
42+
if (hasValue())
43+
return true;
44+
waitForCallback(timeout, unit);
45+
return hasValue();
46+
}
47+
48+
private void notifyCalled(String result) {
49+
this.result = result;
50+
notifyCalled();
51+
}
52+
}
53+
54+
@Override
55+
public void onPageFinished(@NonNull WPEView view, @NonNull String url) {
56+
onPageFinishedHelper.notifyCalled();
57+
}
58+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.wpe.wpeview;
2+
3+
import androidx.test.core.app.ActivityScenario;
4+
5+
import org.junit.Assert;
6+
7+
import java.util.concurrent.TimeUnit;
8+
import java.util.concurrent.TimeoutException;
9+
10+
public class WPEViewActivityScenarioHelper {
11+
public static void loadHtmlSync(ActivityScenario<WPEViewTestActivity> scenario, TestWPEViewClient wpeViewClient,
12+
String html) {
13+
scenario.onActivity(activity -> {
14+
activity.getWPEView().setWPEViewClient(wpeViewClient);
15+
activity.getWPEView().loadHtml(html, null);
16+
});
17+
wpeViewClient.getOnPageFinishedHelper().waitForCallback(2, TimeUnit.SECONDS);
18+
}
19+
20+
public static String evaluateJavaScriptAndWaitForResult(ActivityScenario<WPEViewTestActivity> scenario,
21+
TestWPEViewClient wpeViewClient, String script)
22+
throws TimeoutException {
23+
TestWPEViewClient.OnEvaluateJavaScriptResultHelper onEvaluateJavaScriptResultHelper =
24+
wpeViewClient.getOnEvaluateJavascriptResultHelper();
25+
scenario.onActivity(
26+
activity -> { onEvaluateJavaScriptResultHelper.evaluateJavascript(activity.getWPEView(), script); });
27+
onEvaluateJavaScriptResultHelper.waitUntilHasValue(5, TimeUnit.SECONDS);
28+
Assert.assertTrue("Failed to retrieve JavaScript evaluation results.",
29+
onEvaluateJavaScriptResultHelper.hasValue());
30+
return wpeViewClient.getOnEvaluateJavascriptResultHelper().getResultAndClear();
31+
}
32+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package com.wpe.wpeview;
2+
3+
import android.util.Log;
4+
5+
import androidx.annotation.NonNull;
6+
import androidx.lifecycle.Lifecycle;
7+
import androidx.test.core.app.ActivityScenario;
8+
import androidx.test.ext.junit.rules.ActivityScenarioRule;
9+
import androidx.test.runner.AndroidJUnit4;
10+
11+
import org.junit.Assert;
12+
import org.junit.Rule;
13+
import org.junit.Test;
14+
import org.junit.runner.RunWith;
15+
16+
import java.util.concurrent.CountDownLatch;
17+
import java.util.concurrent.TimeUnit;
18+
import java.util.concurrent.atomic.AtomicBoolean;
19+
20+
@RunWith(AndroidJUnit4.class)
21+
public class WPEViewDialogOverrideTest {
22+
private static final String EMPTY_PAGE = "<!doctype html>"
23+
+ "<title>Dialog Test</title><p>Testcase.</p>";
24+
25+
@Rule
26+
public ActivityScenarioRule<WPEViewTestActivity> wpeViewActivityTestRule =
27+
new ActivityScenarioRule<>(WPEViewTestActivity.class);
28+
29+
@Test
30+
public void testOverrideAlertHandling() throws Throwable {
31+
final String alertText = "Hello World!";
32+
33+
final AtomicBoolean callbackCalled = new AtomicBoolean(false);
34+
35+
TestWPEViewClient wpeViewClient = new TestWPEViewClient();
36+
ActivityScenario<WPEViewTestActivity> scenario = wpeViewActivityTestRule.getScenario();
37+
scenario
38+
.onActivity(activity -> {
39+
activity.getWPEView().setWPEChromeClient(new WPEChromeClient() {
40+
@Override
41+
public boolean onJsAlert(@NonNull WPEView view, @NonNull String url, @NonNull String message,
42+
@NonNull WPEJsResult result) {
43+
callbackCalled.set(true);
44+
result.confirm();
45+
return true;
46+
}
47+
});
48+
})
49+
.moveToState(Lifecycle.State.RESUMED);
50+
51+
WPEViewActivityScenarioHelper.loadHtmlSync(scenario, wpeViewClient, EMPTY_PAGE);
52+
WPEViewActivityScenarioHelper.evaluateJavaScriptAndWaitForResult(scenario, wpeViewClient,
53+
"alert('" + alertText + "')");
54+
55+
Assert.assertTrue(callbackCalled.get());
56+
}
57+
58+
@Test
59+
public void testOverrideConfirmHandlingConfirmed() throws Throwable {
60+
final String confirmText = "Would you like to confirm?";
61+
62+
final AtomicBoolean callbackCalled = new AtomicBoolean(false);
63+
64+
TestWPEViewClient wpeViewClient = new TestWPEViewClient();
65+
ActivityScenario<WPEViewTestActivity> scenario = wpeViewActivityTestRule.getScenario();
66+
scenario
67+
.onActivity(activity -> {
68+
activity.getWPEView().setWPEChromeClient(new WPEChromeClient() {
69+
@Override
70+
public boolean onJsConfirm(@NonNull WPEView view, @NonNull String url, @NonNull String message,
71+
@NonNull WPEJsResult result) {
72+
callbackCalled.set(true);
73+
result.confirm();
74+
return true;
75+
}
76+
});
77+
activity.getWPEView().loadHtml(EMPTY_PAGE, null);
78+
})
79+
.moveToState(Lifecycle.State.RESUMED);
80+
81+
WPEViewActivityScenarioHelper.loadHtmlSync(scenario, wpeViewClient, EMPTY_PAGE);
82+
String result = WPEViewActivityScenarioHelper.evaluateJavaScriptAndWaitForResult(
83+
scenario, wpeViewClient, "confirm('" + confirmText + "')");
84+
85+
Assert.assertTrue(callbackCalled.get());
86+
Assert.assertEquals("true", result);
87+
}
88+
89+
@Test
90+
public void testOverrideConfirmHandlingCancelled() throws Throwable {
91+
final String confirmText = "Would you like to confirm?";
92+
93+
final AtomicBoolean callbackCalled = new AtomicBoolean(false);
94+
95+
TestWPEViewClient wpeViewClient = new TestWPEViewClient();
96+
ActivityScenario<WPEViewTestActivity> scenario = wpeViewActivityTestRule.getScenario();
97+
scenario
98+
.onActivity(activity -> {
99+
activity.getWPEView().setWPEChromeClient(new WPEChromeClient() {
100+
@Override
101+
public boolean onJsConfirm(@NonNull WPEView view, @NonNull String url, @NonNull String message,
102+
@NonNull WPEJsResult result) {
103+
callbackCalled.set(true);
104+
result.cancel();
105+
return true;
106+
}
107+
});
108+
activity.getWPEView().loadHtml(EMPTY_PAGE, null);
109+
})
110+
.moveToState(Lifecycle.State.RESUMED);
111+
112+
WPEViewActivityScenarioHelper.loadHtmlSync(scenario, wpeViewClient, EMPTY_PAGE);
113+
String result = WPEViewActivityScenarioHelper.evaluateJavaScriptAndWaitForResult(
114+
scenario, wpeViewClient, "confirm('" + confirmText + "')");
115+
116+
Assert.assertTrue(callbackCalled.get());
117+
Assert.assertEquals("false", result);
118+
}
119+
120+
@Test
121+
public void testOverridePromptHandling() throws Throwable {
122+
final String promptText = "How is the weather today?";
123+
final String promptDefault = "It's sunny and warm today.";
124+
final String promptResult = "It’s so hot.";
125+
126+
final AtomicBoolean callbackCalled = new AtomicBoolean(false);
127+
128+
TestWPEViewClient wpeViewClient = new TestWPEViewClient();
129+
ActivityScenario<WPEViewTestActivity> scenario = wpeViewActivityTestRule.getScenario();
130+
scenario
131+
.onActivity(activity -> {
132+
activity.getWPEView().setWPEChromeClient(new WPEChromeClient() {
133+
@Override
134+
public boolean onJsPrompt(@NonNull WPEView view, @NonNull String url, @NonNull String message,
135+
@NonNull String defaultValue, @NonNull WPEJsPromptResult result) {
136+
Assert.assertEquals(promptText, message);
137+
Assert.assertEquals(promptDefault, defaultValue);
138+
139+
result.confirm(promptResult);
140+
callbackCalled.set(true);
141+
return true;
142+
}
143+
});
144+
})
145+
.moveToState(Lifecycle.State.RESUMED);
146+
WPEViewActivityScenarioHelper.loadHtmlSync(scenario, wpeViewClient, EMPTY_PAGE);
147+
String result = WPEViewActivityScenarioHelper.evaluateJavaScriptAndWaitForResult(
148+
scenario, wpeViewClient, "prompt(\"" + promptText + "\", \"" + promptDefault + "\")");
149+
Assert.assertTrue(callbackCalled.get());
150+
Assert.assertEquals("\"" + promptResult + "\"", result);
151+
}
152+
}

wpe/src/androidTest/java/com/wpe/wpeview/WPEViewImeTest.java

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,34 +32,29 @@ public class WPEViewImeTest {
3232
public void testIMEVisible() {
3333
CountDownLatch latch = new CountDownLatch(1);
3434
ActivityScenario<WPEViewTestActivity> scenario = wpeViewActivityTestRule.getScenario();
35-
scenario.onActivity(activity -> {
36-
activity.getWPEView().setWPEViewClient(new WPEViewClient() {
37-
@Override
38-
public void onPageFinished(@NonNull WPEView view, @NonNull String url) {
39-
String focusScript = "function onDocumentFocused() {\n"
40-
+ " document.getElementById('editor').focus();\n"
41-
+ " test.onEditorFocused();\n"
42-
+ "}\n"
43-
+ "(function() {\n"
44-
+ "if (document.hasFocus()) {\n"
45-
+ " onDocumentFocused();"
46-
+ "} else {\n"
47-
+ " window.addEventListener('focus', onDocumentFocused);\n"
48-
+ "}})();";
49-
view.evaluateJavascript(focusScript, new WPECallback<String>() {
50-
@Override
51-
public void onResult(String value) {
52-
latch.countDown();
53-
}
54-
});
55-
}
56-
});
57-
58-
String htmlDocument = "<html><body contenteditable id='editor'></body></html>";
59-
activity.getWPEView().loadHtml(htmlDocument, null);
60-
});
35+
scenario
36+
.onActivity(activity -> {
37+
activity.getWPEView().setWPEViewClient(new WPEViewClient() {
38+
@Override
39+
public void onPageFinished(@NonNull WPEView view, @NonNull String url) {
40+
String focusScript = "function onDocumentFocused() {\n"
41+
+ " document.getElementById('editor').focus();\n"
42+
+ " test.onEditorFocused();\n"
43+
+ "}\n"
44+
+ "(function() {\n"
45+
+ "if (document.hasFocus()) {\n"
46+
+ " onDocumentFocused();"
47+
+ "} else {\n"
48+
+ " window.addEventListener('focus', onDocumentFocused);\n"
49+
+ "}})();";
50+
view.evaluateJavascript(focusScript, value -> latch.countDown());
51+
}
52+
});
6153

62-
scenario.moveToState(Lifecycle.State.RESUMED);
54+
String htmlDocument = "<html><body contenteditable id='editor'></body></html>";
55+
activity.getWPEView().loadHtml(htmlDocument, null);
56+
})
57+
.moveToState(Lifecycle.State.RESUMED);
6358

6459
try {
6560
latch.await(10, TimeUnit.SECONDS);

0 commit comments

Comments
 (0)