blob: e505eb8dd915e92ba92ffb44345c29fe8979a324 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser;
import android.app.Dialog;
import android.support.test.filters.LargeTest;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.chrome.R;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.security_state.ConnectionSecurityLevel;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.ui.widget.TextViewWithClickableSpans;
/**
* Tests for the UsbChooserDialog class.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@RetryOnFailure
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class UsbChooserDialogTest {
/**
* Works like the UsbChooserDialog class, but records calls to native methods instead of
* calling back to C++.
*/
@Rule
public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
new ChromeActivityTestRule<>(ChromeActivity.class);
static class UsbChooserDialogWithFakeNatives extends UsbChooserDialog {
String mSelectedDeviceId = "";
UsbChooserDialogWithFakeNatives() {
super(42 /* nativeUsbChooserDialogPtr */);
}
@Override
void nativeOnItemSelected(long nativeUsbChooserDialogAndroid, String deviceId) {
mSelectedDeviceId = deviceId;
}
@Override
void nativeOnDialogCancelled(long nativeUsbChooserDialogAndroid) {}
@Override
void nativeLoadUsbHelpPage(long nativeUsbChooserDialogAndroid) {}
}
private UsbChooserDialogWithFakeNatives mChooserDialog;
@Before
public void setUp() throws Exception {
mActivityTestRule.startMainActivityOnBlankPage();
mChooserDialog = createDialog();
}
private UsbChooserDialogWithFakeNatives createDialog() {
return TestThreadUtils.runOnUiThreadBlockingNoException(
() -> {
UsbChooserDialogWithFakeNatives dialog =
new UsbChooserDialogWithFakeNatives();
dialog.show(mActivityTestRule.getActivity(), "https://origin.example.com/",
ConnectionSecurityLevel.SECURE);
return dialog;
});
}
private static void selectItem(final UsbChooserDialogWithFakeNatives chooserDialog,
int position) {
final Dialog dialog = chooserDialog.mItemChooserDialog.getDialogForTesting();
final ListView items = (ListView) dialog.findViewById(R.id.items);
final Button button = (Button) dialog.findViewById(R.id.positive);
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
return items.getChildAt(0) != null;
}
});
// The actual index for the first item displayed on screen.
int firstVisiblePosition = items.getFirstVisiblePosition();
TouchCommon.singleClickView(items.getChildAt(position - firstVisiblePosition));
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
return button.isEnabled();
}
});
TouchCommon.singleClickView(button);
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
return !chooserDialog.mSelectedDeviceId.equals("");
}
});
}
/**
* The messages include <link> ... </link> or <link1> ... </link1>, <link2> ... </link2>
* sections that are used to create clickable spans. For testing the messages, this function
* returns the raw string without the tags.
*/
private static String removeLinkTags(String message) {
return message.replaceAll("</?link1>", "").replaceAll(
"</?link2>", "").replaceAll("</?link>", "");
}
@Test
@LargeTest
public void testCancel() {
Dialog dialog = mChooserDialog.mItemChooserDialog.getDialogForTesting();
Assert.assertTrue(dialog.isShowing());
final ListView items = (ListView) dialog.findViewById(R.id.items);
final Button button = (Button) dialog.findViewById(R.id.positive);
// The 'Connect' button should be disabled and the list view should be hidden.
Assert.assertFalse(button.isEnabled());
Assert.assertEquals(View.GONE, items.getVisibility());
dialog.dismiss();
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
return mChooserDialog.mSelectedDeviceId.equals("");
}
});
}
@Test
@LargeTest
public void testSelectItem() throws InterruptedException {
Dialog dialog = mChooserDialog.mItemChooserDialog.getDialogForTesting();
TextViewWithClickableSpans statusView =
(TextViewWithClickableSpans) dialog.findViewById(R.id.status);
final ListView items = (ListView) dialog.findViewById(R.id.items);
final Button button = (Button) dialog.findViewById(R.id.positive);
final int position = 1;
TestThreadUtils.runOnUiThreadBlocking(() -> {
mChooserDialog.addDevice("device_id_0", "device_name_0");
mChooserDialog.addDevice("device_id_1", "device_name_1");
mChooserDialog.addDevice("device_id_2", "device_name_2");
// Show the desired position at the top of the ListView (in case
// not all the items can fit on small devices' screens).
items.setSelection(position);
});
// After adding items to the dialog, the help message should be showing,
// the 'Connect' button should still be disabled (since nothing's selected),
// and the list view should show.
Assert.assertEquals(removeLinkTags(mActivityTestRule.getActivity().getString(
R.string.usb_chooser_dialog_footnote_text)),
statusView.getText().toString());
Assert.assertFalse(button.isEnabled());
Assert.assertEquals(View.VISIBLE, items.getVisibility());
selectItem(mChooserDialog, position);
Assert.assertEquals("device_id_1", mChooserDialog.mSelectedDeviceId);
}
}