EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.chrome.browser.test]

COVERAGE SUMMARY FOR SOURCE FILE [ModalDialogTest.java]

nameclass, %method, %block, %line, %
ModalDialogTest.java100% (9/9)97%  (37/38)88%  (592/673)86%  (130.6/152)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ModalDialogTest$JavascriptAppModalDialogShownCriteria100% (1/1)100% (3/3)68%  (17/25)62%  (5/8)
isSatisfied (): boolean 100% (1/1)50%  (8/16)25%  (1/4)
ModalDialogTest$JavascriptAppModalDialogShownCriteria (boolean): void 100% (1/1)100% (6/6)100% (3/3)
access$100 (ModalDialogTest$JavascriptAppModalDialogShownCriteria): boolean 100% (1/1)100% (3/3)100% (1/1)
     
class ModalDialogTest$2100% (1/1)100% (2/2)86%  (25/29)83%  (5.8/7)
call (): String 100% (1/1)80%  (16/20)80%  (4.8/6)
ModalDialogTest$2 (ModalDialogTest, AlertDialog): void 100% (1/1)100% (9/9)100% (1/1)
     
class ModalDialogTest100% (1/1)95%  (20/21)87%  (429/495)86%  (106/123)
testBeforeUnloadDialog (): void 0%   (0/1)0%   (0/66)0%   (0/17)
<static initializer> 100% (1/1)100% (7/7)100% (2/2)
ModalDialogTest (): void 100% (1/1)100% (3/3)100% (2/2)
access$000 (): String 100% (1/1)100% (2/2)100% (1/1)
checkButtonPresenceVisibilityText (JavascriptAppModalDialog, int, int, String... 100% (1/1)100% (56/56)100% (6/6)
clickButton (JavascriptAppModalDialog, int): void 100% (1/1)100% (8/8)100% (2/2)
clickCancel (JavascriptAppModalDialog): void 100% (1/1)100% (5/5)100% (2/2)
clickOk (JavascriptAppModalDialog): void 100% (1/1)100% (5/5)100% (2/2)
executeJavaScriptAndWaitForDialog (String): TestCallbackHelperContainer$OnEva... 100% (1/1)100% (9/9)100% (2/2)
executeJavaScriptAndWaitForDialog (TestCallbackHelperContainer$OnEvaluateJava... 100% (1/1)100% (19/19)100% (4/4)
getActiveTabTestCallbackHelperContainer (): TabShellTabUtils$TestCallbackHelp... 100% (1/1)100% (6/6)100% (1/1)
getAlertDialogButtons (AlertDialog): Button [] 100% (1/1)100% (8/8)100% (1/1)
getCurrentDialog (): JavascriptAppModalDialog 100% (1/1)100% (7/7)100% (1/1)
setUp (): void 100% (1/1)100% (11/11)100% (4/4)
testAlertModalDialog (): void 100% (1/1)100% (18/18)100% (6/6)
testAlertModalDialogWithTwoClicks (): void 100% (1/1)100% (21/21)100% (7/7)
testBeforeUnloadOnReloadDialog (): void 100% (1/1)100% (26/26)100% (7/7)
testConfirmModalDialog (): void 100% (1/1)100% (91/91)100% (22/22)
testDialogDismissedAfterClosingTab (): void 100% (1/1)100% (29/29)100% (8/8)
testDisableRepeatedDialogs (): void 100% (1/1)100% (59/59)100% (16/16)
testPromptModalDialog (): void 100% (1/1)100% (39/39)100% (11/11)
     
class ModalDialogTest$1100% (1/1)100% (2/2)89%  (24/27)95%  (4.8/5)
call (): Boolean 100% (1/1)83%  (15/18)94%  (3.8/4)
ModalDialogTest$1 (ModalDialogTest, JavascriptAppModalDialog): void 100% (1/1)100% (9/9)100% (1/1)
     
class ModalDialogTest$3100% (1/1)100% (2/2)100% (13/13)100% (3/3)
ModalDialogTest$3 (ModalDialogTest): void 100% (1/1)100% (6/6)100% (1/1)
run (): void 100% (1/1)100% (7/7)100% (2/2)
     
class ModalDialogTest$4100% (1/1)100% (2/2)100% (35/35)100% (6/6)
ModalDialogTest$4 (ModalDialogTest, AlertDialog): void 100% (1/1)100% (9/9)100% (1/1)
call (): Button [] 100% (1/1)100% (26/26)100% (5/5)
     
class ModalDialogTest$5100% (1/1)100% (2/2)100% (8/8)100% (2/2)
ModalDialogTest$5 (ModalDialogTest): void 100% (1/1)100% (6/6)100% (1/1)
call (): JavascriptAppModalDialog 100% (1/1)100% (2/2)100% (1/1)
     
class ModalDialogTest$6100% (1/1)100% (2/2)100% (19/19)100% (3/3)
ModalDialogTest$6 (ModalDialogTest, JavascriptAppModalDialog, int): void 100% (1/1)100% (12/12)100% (1/1)
run (): void 100% (1/1)100% (7/7)100% (2/2)
     
class ModalDialogTest$JavascriptAppModalDialogShownCriteria$1100% (1/1)100% (2/2)100% (22/22)100% (3/3)
ModalDialogTest$JavascriptAppModalDialogShownCriteria$1 (ModalDialogTest$Java... 100% (1/1)100% (6/6)100% (1/1)
call (): Boolean 100% (1/1)100% (16/16)100% (2/2)

1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4 
5package org.chromium.chrome.browser.test;
6 
7import android.app.AlertDialog;
8import android.content.DialogInterface;
9import android.test.suitebuilder.annotation.MediumTest;
10import android.util.Log;
11import android.view.View;
12import android.widget.Button;
13import android.widget.CheckBox;
14import android.widget.EditText;
15 
16import org.chromium.base.ThreadUtils;
17import org.chromium.base.test.util.DisabledTest;
18import org.chromium.base.test.util.Feature;
19import org.chromium.base.test.util.UrlUtils;
20import org.chromium.chrome.browser.JavascriptAppModalDialog;
21import org.chromium.chrome.testshell.ChromiumTestShellTestBase;
22import org.chromium.chrome.testshell.TabShellTabUtils;
23import org.chromium.chrome.testshell.TabShellTabUtils.TestCallbackHelperContainerForTab;
24import org.chromium.content.browser.test.util.Criteria;
25import org.chromium.content.browser.test.util.CriteriaHelper;
26import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
27import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
28 
29import java.util.concurrent.Callable;
30import java.util.concurrent.ExecutionException;
31import java.util.concurrent.TimeoutException;
32 
33/**
34 * Test suite for displaying and functioning of modal dialogs.
35 */
36public class ModalDialogTest extends ChromiumTestShellTestBase {
37    private final static String TAG = "ModalDialogTest";
38    private final static String EMPTY_PAGE = UrlUtils.encodeHtmlDataUri(
39            "<html><title>Modal Dialog Test</title><p>Testcase.</p></title></html>");
40    private final static String BEFORE_UNLOAD_URL = UrlUtils.encodeHtmlDataUri(
41            "<html>" +
42            "<head><script>window.onbeforeunload=function() {" +
43            "return 'Are you sure?';" +
44            "};</script></head></html>");
45 
46    @Override
47    public void setUp() throws Exception {
48        super.setUp();
49        launchChromiumTestShellWithUrl(EMPTY_PAGE);
50        assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
51    }
52 
53    /**
54     * Verifies modal alert-dialog appearance and that JavaScript execution is
55     * able to continue after dismissal.
56     */
57    @MediumTest
58    @Feature({"Browser", "Main"})
59    public void testAlertModalDialog()
60            throws InterruptedException, TimeoutException, ExecutionException {
61        final OnEvaluateJavaScriptResultHelper scriptEvent =
62                executeJavaScriptAndWaitForDialog("alert('Hello Android!');");
63 
64        JavascriptAppModalDialog jsDialog = getCurrentDialog();
65        assertNotNull("No dialog showing.", jsDialog);
66 
67        clickOk(jsDialog);
68        assertTrue("JavaScript execution should continue after closing prompt.",
69                scriptEvent.waitUntilHasValue());
70    }
71 
72    /**
73     * Verifies that clicking on a button twice doesn't crash.
74     */
75    @MediumTest
76    @Feature({"Browser", "Main"})
77    public void testAlertModalDialogWithTwoClicks()
78            throws InterruptedException, TimeoutException, ExecutionException {
79        OnEvaluateJavaScriptResultHelper scriptEvent =
80                executeJavaScriptAndWaitForDialog("alert('Hello Android');");
81        JavascriptAppModalDialog jsDialog = getCurrentDialog();
82        assertNotNull("No dialog showing.", jsDialog);
83 
84        clickOk(jsDialog);
85        clickOk(jsDialog);
86 
87        assertTrue("JavaScript execution should continue after closing prompt.",
88                scriptEvent.waitUntilHasValue());
89    }
90 
91    /**
92     * Verifies that modal confirm-dialogs display, two buttons are visible and
93     * the return value of [Ok] equals true, [Cancel] equals false.
94     */
95    @MediumTest
96    @Feature({"Browser", "Main"})
97    public void testConfirmModalDialog()
98            throws InterruptedException, TimeoutException, ExecutionException {
99        OnEvaluateJavaScriptResultHelper scriptEvent =
100                executeJavaScriptAndWaitForDialog("confirm('Android');");
101 
102        JavascriptAppModalDialog jsDialog = getCurrentDialog();
103        assertNotNull("No dialog showing.", jsDialog);
104 
105        Button[] buttons = getAlertDialogButtons(jsDialog.getDialogForTest());
106        assertNotNull("No cancel button in confirm dialog.", buttons[0]);
107        assertEquals("Cancel button is not visible.", View.VISIBLE, buttons[0].getVisibility());
108        if (buttons[1] != null) {
109            assertNotSame("Neutral button visible when it should not.",
110                    View.VISIBLE, buttons[1].getVisibility());
111        }
112        assertNotNull("No OK button in confirm dialog.", buttons[2]);
113        assertEquals("OK button is not visible.", View.VISIBLE, buttons[2].getVisibility());
114 
115        clickOk(jsDialog);
116        assertTrue("JavaScript execution should continue after closing dialog.",
117                scriptEvent.waitUntilHasValue());
118 
119        String resultString = scriptEvent.getJsonResultAndClear();
120        assertEquals("Invalid return value.", "true", resultString);
121 
122        // Try again, pressing cancel this time.
123        scriptEvent = executeJavaScriptAndWaitForDialog("confirm('Android');");
124        jsDialog = getCurrentDialog();
125        assertNotNull("No dialog showing.", jsDialog);
126 
127        clickCancel(jsDialog);
128        assertTrue("JavaScript execution should continue after closing dialog.",
129                scriptEvent.waitUntilHasValue());
130 
131        resultString = scriptEvent.getJsonResultAndClear();
132        assertEquals("Invalid return value.", "false", resultString);
133    }
134 
135    /**
136     * Verifies that modal prompt-dialogs display and the result is returned.
137     */
138    @MediumTest
139    @Feature({"Browser", "Main"})
140    public void testPromptModalDialog()
141            throws InterruptedException, TimeoutException, ExecutionException {
142        final String promptText = "Hello Android!";
143        final OnEvaluateJavaScriptResultHelper scriptEvent =
144                executeJavaScriptAndWaitForDialog("prompt('Android', 'default');");
145 
146        final JavascriptAppModalDialog jsDialog = getCurrentDialog();
147        assertNotNull("No dialog showing.", jsDialog);
148 
149        // Set the text in the prompt field of the dialog.
150        boolean result = ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
151            @Override
152            public Boolean call() {
153                EditText prompt = (EditText) jsDialog.getDialogForTest().findViewById(
154                        org.chromium.chrome.R.id.js_modal_dialog_prompt);
155                if (prompt == null) return false;
156                prompt.setText(promptText);
157                return true;
158            }
159        });
160        assertTrue("Failed to find prompt view in prompt dialog.", result);
161 
162        clickOk(jsDialog);
163        assertTrue("JavaScript execution should continue after closing prompt.",
164                scriptEvent.waitUntilHasValue());
165 
166        String resultString = scriptEvent.getJsonResultAndClear();
167        assertEquals("Invalid return value.", '"' + promptText + '"', resultString);
168    }
169 
170    /**
171     * Verifies beforeunload dialogs are shown and they block/allow navigation
172     * as appropriate.
173     */
174    //@MediumTest
175    //@Feature({"Browser", "Main"})
176    @DisabledTest //crbug/270593
177    public void testBeforeUnloadDialog()
178            throws InterruptedException, TimeoutException, ExecutionException {
179        loadUrlWithSanitization(BEFORE_UNLOAD_URL);
180        executeJavaScriptAndWaitForDialog("history.back();");
181 
182        JavascriptAppModalDialog jsDialog = getCurrentDialog();
183        assertNotNull("No dialog showing.", jsDialog);
184        checkButtonPresenceVisibilityText(
185                jsDialog, 0, org.chromium.chrome.R.string.stay_on_this_page,
186                "Stay on this page");
187        clickCancel(jsDialog);
188 
189        assertEquals(BEFORE_UNLOAD_URL, getActivity().getActiveContentView().getUrl());
190        executeJavaScriptAndWaitForDialog("history.back();");
191 
192        jsDialog = getCurrentDialog();
193        assertNotNull("No dialog showing.", jsDialog);
194        checkButtonPresenceVisibilityText(
195                jsDialog, 2, org.chromium.chrome.R.string.leave_this_page,
196                "Leave this page");
197 
198        final TestCallbackHelperContainer.OnPageFinishedHelper onPageLoaded =
199                getActiveTabTestCallbackHelperContainer().getOnPageFinishedHelper();
200        int callCount = onPageLoaded.getCallCount();
201        clickOk(jsDialog);
202        onPageLoaded.waitForCallback(callCount);
203        assertEquals(EMPTY_PAGE, getActivity().getActiveContentView().getUrl());
204    }
205 
206    /**
207     * Verifies that when showing a beforeunload dialogs as a result of a page
208     * reload, the correct UI strings are used.
209     */
210    @MediumTest
211    @Feature({"Browser", "Main"})
212    public void testBeforeUnloadOnReloadDialog()
213            throws InterruptedException, TimeoutException, ExecutionException {
214        loadUrlWithSanitization(BEFORE_UNLOAD_URL);
215        executeJavaScriptAndWaitForDialog("window.location.reload();");
216 
217        JavascriptAppModalDialog jsDialog = getCurrentDialog();
218        assertNotNull("No dialog showing.", jsDialog);
219 
220        checkButtonPresenceVisibilityText(
221                jsDialog, 0, org.chromium.chrome.R.string.dont_reload_this_page,
222                "Don't reload this page");
223        checkButtonPresenceVisibilityText(
224                jsDialog, 2, org.chromium.chrome.R.string.reload_this_page,
225                "Reload this page");
226    }
227 
228    /**
229     * Verifies that repeated dialogs give the option to disable dialogs
230     * altogether and then that disabling them works.
231     */
232    @MediumTest
233    @Feature({"Browser", "Main"})
234    public void testDisableRepeatedDialogs()
235            throws InterruptedException, TimeoutException, ExecutionException {
236        OnEvaluateJavaScriptResultHelper scriptEvent =
237                executeJavaScriptAndWaitForDialog("alert('Android');");
238 
239        // Show a dialog once.
240        JavascriptAppModalDialog jsDialog = getCurrentDialog();
241        assertNotNull("No dialog showing.", jsDialog);
242 
243        clickCancel(jsDialog);
244        scriptEvent.waitUntilHasValue();
245 
246        // Show it again, it should have the option to suppress subsequent dialogs.
247        scriptEvent = executeJavaScriptAndWaitForDialog("alert('Android');");
248        jsDialog = getCurrentDialog();
249        assertNotNull("No dialog showing.", jsDialog);
250        final AlertDialog dialog = jsDialog.getDialogForTest();
251        String errorMessage = ThreadUtils.runOnUiThreadBlocking(new Callable<String>() {
252            @Override
253            public String call() {
254                final CheckBox suppress = (CheckBox) dialog.findViewById(
255                        org.chromium.chrome.R.id.suppress_js_modal_dialogs);
256                if (suppress == null) return "Suppress checkbox not found.";
257                if (suppress.getVisibility() != View.VISIBLE) {
258                    return "Suppress checkbox is not visible.";
259                }
260                suppress.setChecked(true);
261                return null;
262            }
263        });
264        assertNull(errorMessage, errorMessage);
265        clickCancel(jsDialog);
266        scriptEvent.waitUntilHasValue();
267 
268        scriptEvent.evaluateJavaScript(getActivity().getActiveContentView().getContentViewCore(),
269                "alert('Android');");
270        assertTrue("No further dialog boxes should be shown.", scriptEvent.waitUntilHasValue());
271    }
272 
273    /**
274     * Displays a dialog and closes the tab in the background before attempting
275     * to accept the dialog. Verifies that the dialog is dismissed when the tab
276     * is closed.
277     */
278    @MediumTest
279    @Feature({"Browser", "Main"})
280    public void testDialogDismissedAfterClosingTab()
281            throws InterruptedException, TimeoutException, ExecutionException {
282        executeJavaScriptAndWaitForDialog("alert('Android')");
283 
284        final TestCallbackHelperContainerForTab.OnCloseTabHelper onTabClosed =
285                getActiveTabTestCallbackHelperContainer().getOnCloseTabHelper();
286        int callCount = onTabClosed.getCallCount();
287        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
288            @Override
289            public void run() {
290                getActivity().createTab(EMPTY_PAGE);
291            }
292        });
293        onTabClosed.waitForCallback(callCount);
294 
295        // Closing the tab should have dismissed the dialog.
296        boolean criteriaSatisfied = CriteriaHelper.pollForCriteria(
297                new JavascriptAppModalDialogShownCriteria(false));
298        assertTrue("The dialog should have been dismissed when its tab was closed.",
299                criteriaSatisfied);
300    }
301 
302    /**
303     * Asynchronously executes the given code for spawning a dialog and waits
304     * for the dialog to be visible.
305     */
306    private OnEvaluateJavaScriptResultHelper executeJavaScriptAndWaitForDialog(String script)
307            throws InterruptedException {
308        final OnEvaluateJavaScriptResultHelper helper =
309                getActiveTabTestCallbackHelperContainer().getOnEvaluateJavaScriptResultHelper();
310        return executeJavaScriptAndWaitForDialog(helper, script);
311    }
312 
313    /**
314     * Given a JavaScript evaluation helper, asynchronously executes the given
315     * code for spawning a dialog and waits for the dialog to be visible.
316     */
317    private OnEvaluateJavaScriptResultHelper executeJavaScriptAndWaitForDialog(
318            final OnEvaluateJavaScriptResultHelper helper, String script)
319            throws InterruptedException {
320        helper.evaluateJavaScript(getActivity().getActiveContentView().getContentViewCore(),
321                script);
322        boolean criteriaSatisfied = CriteriaHelper.pollForCriteria(
323                new JavascriptAppModalDialogShownCriteria(true));
324        assertTrue("Could not spawn or locate a modal dialog.", criteriaSatisfied);
325        return helper;
326    }
327 
328    /**
329     * Returns an array of the 3 buttons for this dialog, in the order
330     * BUTTON_NEGATIVE, BUTTON_NEUTRAL and BUTTON_POSITIVE. Any of these values
331     * can be null.
332     */
333    private Button[] getAlertDialogButtons(final AlertDialog dialog) throws ExecutionException {
334        return ThreadUtils.runOnUiThreadBlocking(new Callable<Button[]>() {
335            @Override
336            public Button[] call() {
337                final Button[] buttons = new Button[3];
338                buttons[0] = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
339                buttons[1] = dialog.getButton(DialogInterface.BUTTON_NEUTRAL);
340                buttons[2] = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
341                return buttons;
342            }
343        });
344    }
345 
346    /**
347     * Returns the current JavaScript modal dialog showing or null if no such dialog is currently
348     * showing.
349     */
350    private JavascriptAppModalDialog getCurrentDialog() throws ExecutionException {
351        return ThreadUtils.runOnUiThreadBlocking(new Callable<JavascriptAppModalDialog>() {
352            @Override
353            public JavascriptAppModalDialog call() {
354                return JavascriptAppModalDialog.getCurrentDialogForTest();
355            }
356        });
357    }
358 
359    private static class JavascriptAppModalDialogShownCriteria implements Criteria {
360        private final boolean mShouldBeShown;
361 
362        public JavascriptAppModalDialogShownCriteria(boolean shouldBeShown) {
363            mShouldBeShown = shouldBeShown;
364        }
365 
366        @Override
367        public boolean isSatisfied() {
368            try {
369                return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
370                    @Override
371                    public Boolean call() {
372                        final boolean isShown =
373                                JavascriptAppModalDialog.getCurrentDialogForTest() != null;
374                        return mShouldBeShown == isShown;
375                    }
376                });
377            } catch (ExecutionException e) {
378                Log.e(TAG, "Failed to getCurrentDialog", e);
379                return false;
380            }
381        }
382    }
383 
384    /**
385     * Simulates pressing the OK button of the passed dialog.
386     */
387    private void clickOk(JavascriptAppModalDialog dialog) {
388        clickButton(dialog, DialogInterface.BUTTON_POSITIVE);
389    }
390 
391    /**
392     * Simulates pressing the Cancel button of the passed dialog.
393     */
394    private void clickCancel(JavascriptAppModalDialog dialog) {
395        clickButton(dialog, DialogInterface.BUTTON_NEGATIVE);
396    }
397 
398    private void clickButton(final JavascriptAppModalDialog dialog, final int whichButton) {
399        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
400            @Override
401            public void run() {
402                dialog.onClick(null, whichButton);
403            }
404        });
405    }
406 
407    private void checkButtonPresenceVisibilityText(
408            JavascriptAppModalDialog jsDialog, int buttonIndex,
409            int expectedTextResourceId, String readableName) throws ExecutionException {
410        final Button[] buttons = getAlertDialogButtons(jsDialog.getDialogForTest());
411        final Button button = buttons[buttonIndex];
412        assertNotNull("No '" + readableName + "' button in confirm dialog.", button);
413        assertEquals("'" + readableName + "' button is not visible.",
414                View.VISIBLE,
415                button.getVisibility());
416        assertEquals("'" + readableName + "' button has wrong text",
417                getActivity().getResources().getString(expectedTextResourceId),
418                button.getText().toString());
419    }
420 
421    private TestCallbackHelperContainerForTab getActiveTabTestCallbackHelperContainer() {
422        return TabShellTabUtils.getTestCallbackHelperContainer(getActivity().getActiveTab());
423    }
424}

[all classes][org.chromium.chrome.browser.test]
EMMA 2.0.5312 (C) Vladimir Roubtsov