chromium/ios/chrome/browser/bring_android_tabs/ui_bundled/bring_android_tabs_tab_list_egtest.mm

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/bring_android_tabs/ui_bundled/bring_android_tabs_test_session.h"
#import "ios/chrome/browser/bring_android_tabs/ui_bundled/bring_android_tabs_test_utils.h"
#import "ios/chrome/browser/bring_android_tabs/ui_bundled/constants.h"
#import "ios/chrome/common/ui/confirmation_alert/constants.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#import "ios/third_party/earl_grey2/src/CommonLib/GREYConstants.h"
#import "net/test/embedded_test_server/embedded_test_server.h"

namespace {

// Returns the matcher for the Tab List From Android.
id<GREYMatcher> TabListFromAndroidMatcher() {
  return grey_accessibilityID(kBringAndroidTabsPromptTabListAXId);
}

// Returns the matcher for the Tab List From Android.
id<GREYMatcher> OpenButtonMatcher() {
  return grey_accessibilityID(kBringAndroidTabsPromptTabListOpenButtonAXId);
}

// Returns the matcher for the entry of "/pony.html" in the recent tabs panel.
id<GREYMatcher> PonyPageTitle() {
  return grey_allOf(
      grey_ancestor(TabListFromAndroidMatcher()),
      chrome_test_util::StaticTextWithAccessibilityLabel(@"ponies"),
      grey_sufficientlyVisible(), nil);
}

// Returns the matcher for the entry of "/chromium_logo_page.html" in the recent
// tabs panel.
id<GREYMatcher> ChromiumLogoPageTitle() {
  return grey_allOf(
      grey_ancestor(TabListFromAndroidMatcher()),
      chrome_test_util::StaticTextWithAccessibilityLabel(@"chromium logo"),
      grey_sufficientlyVisible(), nil);
}

// Triggers the tab list by selecting "review tabs" from the Bring Android Tabs
// confirmation alert prompt.
void TriggerTabList() {
  SignInViaFREWithHistorySyncEnabled(YES);
  [ChromeEarlGreyUI openTabGrid];
  VerifyConfirmationAlertPromptVisibility(YES);
  [[EarlGrey selectElementWithMatcher:
                 grey_accessibilityID(
                     kConfirmationAlertTertiaryActionAccessibilityIdentifier)]
      performAction:grey_tap()];
  VerifyTabListPromptVisibility(YES);
}

}  // namespace

// Test suite that tests user interactions with the Bring Android Tabs
// tab list.
@interface BringAndroidTabsTabListTestCase : ChromeTestCase

@end

@implementation BringAndroidTabsTabListTestCase

- (AppLaunchConfiguration)appConfigurationForTestCase {
  return GetConfiguration(/*is_android_switcher=*/YES);
}

- (void)setUp {
  [[self class] testForStartup];
  [super setUp];
  if (![ChromeEarlGrey isIPadIdiom]) {
    GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
    AddSessionToFakeSyncServerFromTestServer(
        BringAndroidTabsTestSession::kRecentFromAndroidPhone,
        self.testServer->base_url());
  }
}

- (void)tearDown {
  CleanUp();
  [super tearDown];
}

// Tests that all tabs are opened when no tab is deselected from the list.
- (void)testOpenAllTabs {
  if ([ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_SKIPPED(@"Test skipped on iPad.");
  }
  TriggerTabList();
  [[EarlGrey selectElementWithMatcher:OpenButtonMatcher()]
      performAction:grey_tap()];
  // New tab page already exists in the tab grid.
  [ChromeEarlGrey waitForMainTabCount:GetTabCountOnPrompt() + 1];
  VerifyTabListPromptVisibility(NO);
  VerifyThatPromptDoesNotShowOnRestart(self.testServer->base_url());
}

// Deselects a tab and tests that the remaining tab is opened.
- (void)testDeselectAndOpenTabs {
  if ([ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_SKIPPED(@"Test skipped on iPad.");
  }
  TriggerTabList();
  // Deselect one of the tabs in the list.
  [[EarlGrey selectElementWithMatcher:PonyPageTitle()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:OpenButtonMatcher()]
      performAction:grey_tap()];
  // Expected tab count accounts for the existing new tab page in the tab grid.
  [ChromeEarlGrey waitForMainTabCount:GetTabCountOnPrompt()];
  VerifyTabListPromptVisibility(NO);
  VerifyThatPromptDoesNotShowOnRestart(self.testServer->base_url());
}

// Tests that swiping down on the list dismisses the view and does not open any
// tabs.
- (void)testSwipeToDismiss {
  if ([ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_SKIPPED(@"Test skipped on iPad.");
  }
  TriggerTabList();
  [[EarlGrey selectElementWithMatcher:TabListFromAndroidMatcher()]
      performAction:grey_swipeFastInDirection(kGREYDirectionDown)];
  // New tab page is in the tab grid.
  [ChromeEarlGrey waitForMainTabCount:1];
  VerifyTabListPromptVisibility(NO);
  VerifyThatPromptDoesNotShowOnRestart(self.testServer->base_url());
}

// Tests that tapping cancel dismisses the view and does not open any tabs.
- (void)testTapCancelToDismiss {
  if ([ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_SKIPPED(@"Test skipped on iPad.");
  }
  TriggerTabList();
  id<GREYMatcher> cancelButtonMatcher =
      grey_accessibilityID(kBringAndroidTabsPromptTabListCancelButtonAXId);
  [[EarlGrey selectElementWithMatcher:cancelButtonMatcher]
      performAction:grey_tap()];
  // New tab page is in the tab grid.
  [ChromeEarlGrey waitForMainTabCount:1];
  VerifyTabListPromptVisibility(NO);
  VerifyThatPromptDoesNotShowOnRestart(self.testServer->base_url());
}

// Tests that the open tabs button is disabled when all of the tabs are
// deselected.
- (void)testOpenButtonDisabled {
  if ([ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_SKIPPED(@"Test skipped on iPad.");
  }
  TriggerTabList();
  // Deselect all of the tabs in the list.
  [[EarlGrey selectElementWithMatcher:PonyPageTitle()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:ChromiumLogoPageTitle()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:OpenButtonMatcher()]
      assertWithMatcher:grey_allOf(grey_not(grey_enabled()),
                                   grey_sufficientlyVisible(), nil)];
  VerifyThatPromptDoesNotShowOnRestart(self.testServer->base_url());
}

@end