[go: up one dir, main page]

blob: de6a04a9552ca4059706bf03db03bd91208c2a80 [file] [log] [blame]
// Copyright 2021 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.tasks.tab_management;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.Espresso.pressBack;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
import static androidx.test.espresso.matcher.RootMatchers.withDecorView;
import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.enterTabSwitcher;
import android.content.res.Configuration;
import android.os.Build;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.UiDevice;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.test.espresso.NoMatchingRootException;
import androidx.test.espresso.intent.Intents;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.filters.MediumTest;
import org.junit.After;
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.CriteriaHelper;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.app.ChromeActivity;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.tab_ui.R;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ActivityUtils;
import org.chromium.chrome.test.util.ChromeRenderTestRule;
import org.chromium.chrome.test.util.MenuUtils;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.test.util.UiRestriction;
import java.io.IOException;
/** End-to-end tests for PriceTrackingDialog component. */
@RunWith(ChromeJUnit4ClassRunner.class)
// clang-format off
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=" + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + "<Study",
"force-fieldtrials=Study/Group"})
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
@Features.DisableFeatures({ChromeFeatureList.START_SURFACE_ANDROID})
public class PriceTrackingDialogTest {
// clang-format on
private static final String BASE_PARAMS =
"force-fieldtrial-params=Study.Group:enable_price_tracking/true";
private static final String ACTION_APP_NOTIFICATION_SETTINGS =
"android.settings.APP_NOTIFICATION_SETTINGS";
private ModalDialogManager mModalDialogManager;
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Rule
public ChromeRenderTestRule mRenderTestRule =
ChromeRenderTestRule.Builder.withPublicCorpus().build();
@Rule
public IntentsTestRule<ChromeActivity> mIntentTestRule =
new IntentsTestRule<>(ChromeActivity.class, false, false);
@Before
public void setUp() throws Exception {
PriceTrackingUtilities.setIsSignedInAndSyncEnabledForTesting(true);
mActivityTestRule.startMainActivityOnBlankPage();
CriteriaHelper.pollUiThread(
mActivityTestRule.getActivity().getTabModelSelector()::isTabStateInitialized);
mModalDialogManager = TestThreadUtils.runOnUiThreadBlockingNoException(
mActivityTestRule.getActivity()::getModalDialogManager);
enterTabSwitcher(mActivityTestRule.getActivity());
}
@After
public void tearDown() {
ActivityUtils.clearActivityOrientation(mActivityTestRule.getActivity());
}
@Test
@MediumTest
@CommandLineFlags.Add({BASE_PARAMS})
public void testShowAndHidePriceTrackingDialog() {
final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
MenuUtils.invokeCustomMenuActionSync(
InstrumentationRegistry.getInstrumentation(), cta, R.id.track_prices_row_menu_id);
verifyDialogShowing(cta, false);
// Press back should dismiss the dialog.
pressBack();
verifyDialogHiding(cta);
// Open the price tracking dialog.
MenuUtils.invokeCustomMenuActionSync(
InstrumentationRegistry.getInstrumentation(), cta, R.id.track_prices_row_menu_id);
verifyDialogShowing(cta, false);
// Click outside of the dialog area to close the Price tracking dialog.
View dialogView = mModalDialogManager.getCurrentDialogForTest().get(
ModalDialogProperties.CUSTOM_VIEW);
int[] location = new int[2];
// Get the position of the dialog view and click slightly above so that we essentially click
// on the scrim.
dialogView.getLocationOnScreen(location);
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
.click(location[0], location[1] / 2);
verifyDialogHiding(cta);
}
@Test
@MediumTest
@CommandLineFlags.Add({BASE_PARAMS})
public void testTrackPricesSwitch() {
final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
MenuUtils.invokeCustomMenuActionSync(
InstrumentationRegistry.getInstrumentation(), cta, R.id.track_prices_row_menu_id);
verifyDialogShowing(cta, false);
onView(withId(R.id.track_prices_switch)).check(matches(isChecked()));
assertTrue(PriceTrackingUtilities.isTrackPricesOnTabsEnabled());
onView(withId(R.id.track_prices_switch)).perform(click());
onView(withId(R.id.track_prices_switch)).check(matches(isNotChecked()));
assertFalse(PriceTrackingUtilities.isTrackPricesOnTabsEnabled());
onView(withId(R.id.track_prices_switch)).perform(click());
onView(withId(R.id.track_prices_switch)).check(matches(isChecked()));
assertTrue(PriceTrackingUtilities.isTrackPricesOnTabsEnabled());
}
@Test
@MediumTest
@CommandLineFlags.Add({BASE_PARAMS + "/enable_price_notification/true"})
public void testPriceAlertsButton() {
Intents.init();
final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
MenuUtils.invokeCustomMenuActionSync(
InstrumentationRegistry.getInstrumentation(), cta, R.id.track_prices_row_menu_id);
verifyDialogShowing(cta, true);
onView(withId(R.id.price_alerts_row_menu_id)).check(matches(isDisplayed()));
onView(withId(R.id.price_alerts_arrow)).perform(click());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
intended(hasAction(ACTION_APP_NOTIFICATION_SETTINGS));
} else {
intended(hasAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS));
}
Intents.release();
}
@Test
@MediumTest
@Feature({"RenderTest"})
@CommandLineFlags.Add({BASE_PARAMS + "/enable_price_notification/true"})
public void testRenderPriceTrackingDialog_Portrait() throws IOException {
final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
MenuUtils.invokeCustomMenuActionSync(
InstrumentationRegistry.getInstrumentation(), cta, R.id.track_prices_row_menu_id);
verifyDialogShowing(cta, true);
View priceTrackingDialogView = mModalDialogManager.getCurrentDialogForTest().get(
ModalDialogProperties.CUSTOM_VIEW);
mRenderTestRule.render(priceTrackingDialogView, "price_tracking_dialog_portrait");
}
@Test
@MediumTest
@Feature({"RenderTest"})
@CommandLineFlags.Add({BASE_PARAMS + "/enable_price_notification/true"})
public void testRenderPriceTrackingDialog_Landscape() throws IOException {
final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
ActivityUtils.rotateActivityToOrientation(cta, Configuration.ORIENTATION_LANDSCAPE);
MenuUtils.invokeCustomMenuActionSync(
InstrumentationRegistry.getInstrumentation(), cta, R.id.track_prices_row_menu_id);
verifyDialogShowing(cta, true);
View priceTrackingDialogView = mModalDialogManager.getCurrentDialogForTest().get(
ModalDialogProperties.CUSTOM_VIEW);
mRenderTestRule.render(priceTrackingDialogView, "price_tracking_dialog_landscape");
}
private void verifyDialogShowing(
ChromeTabbedActivity cta, boolean isPriceAlertsRowMenuVisible) {
// Verify price tracking dialog view.
onView(withId(R.id.price_tracking_dialog))
.inRoot(withDecorView(not(cta.getWindow().getDecorView())))
.check((v, noMatchException) -> {
if (noMatchException != null) throw noMatchException;
String title = cta.getString(R.string.price_tracking_settings);
assertEquals(title, ((TextView) v.findViewById(R.id.title)).getText());
String trackPricesTitle = cta.getString(R.string.track_prices_on_tabs);
assertEquals(trackPricesTitle,
((TextView) v.findViewById(R.id.track_prices_title)).getText());
String trackPricesDescription =
cta.getString(R.string.track_prices_on_tabs_description);
assertEquals(trackPricesDescription,
((TextView) v.findViewById(R.id.track_prices_description)).getText());
String priceAlertsTitle = cta.getString(R.string.price_drop_alerts);
assertEquals(priceAlertsTitle,
((TextView) v.findViewById(R.id.price_alerts_title)).getText());
String priceAlertsDescription =
cta.getString(R.string.price_drop_alerts_description);
assertEquals(priceAlertsDescription,
((TextView) v.findViewById(R.id.price_alerts_description)).getText());
if (isPriceAlertsRowMenuVisible) {
assertEquals(View.VISIBLE,
((ViewGroup) v.findViewById(R.id.price_alerts_row_menu_id))
.getVisibility());
} else {
assertEquals(View.GONE,
((ViewGroup) v.findViewById(R.id.price_alerts_row_menu_id))
.getVisibility());
}
});
}
private void verifyDialogHiding(ChromeTabbedActivity cta) {
boolean isShowing = true;
try {
onView(withId(R.id.price_tracking_dialog))
.inRoot(withDecorView(not(cta.getWindow().getDecorView())))
.check(matches(isDisplayed()));
} catch (NoMatchingRootException e) {
isShowing = false;
} catch (Exception e) {
assert false : "error when inspecting price tracking dialog.";
}
assertFalse(isShowing);
}
}