chromium/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_groups_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 "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#import "ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_util.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/signin/model/fake_system_identity.h"
#import "ios/chrome/browser/tabs/model/inactive_tabs/features.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_constants.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_groups_constants.h"
#import "ios/chrome/browser/ui/tab_switcher/test/query_title_server_util.h"
#import "ios/chrome/browser/ui/tab_switcher/test/tabs_egtest_util.h"
#import "ios/chrome/grit/ios_strings.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_matchers_app_interface.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/chrome/test/earl_grey/web_http_server_chrome_test_case.h"
#import "ios/testing/earl_grey/app_launch_manager.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#import "ios/testing/earl_grey/matchers.h"
#import "net/test/embedded_test_server/embedded_test_server.h"
#import "ui/base/l10n/l10n_util.h"

using chrome_test_util::AddTabToGroupSubMenuButton;
using chrome_test_util::AddTabToNewGroupButton;
using chrome_test_util::ButtonWithAccessibilityLabel;
using chrome_test_util::ButtonWithAccessibilityLabelId;
using chrome_test_util::CloseGroupButton;
using chrome_test_util::ContextMenuItemWithAccessibilityLabel;
using chrome_test_util::ContextMenuItemWithAccessibilityLabelId;
using chrome_test_util::CreateTabGroupCancelButton;
using chrome_test_util::CreateTabGroupCreateButton;
using chrome_test_util::CreateTabGroupTextField;
using chrome_test_util::CreateTabGroupTextFieldClearButton;
using chrome_test_util::DeleteGroupButton;
using chrome_test_util::DeleteGroupConfirmationButton;
using chrome_test_util::RenameGroupButton;
using chrome_test_util::TabGridCellAtIndex;
using chrome_test_util::TabGridEditAddToButton;
using chrome_test_util::TabGridEditButton;
using chrome_test_util::TabGridEditMenuCloseAllButton;
using chrome_test_util::TabGridGroupCellAtIndex;
using chrome_test_util::TabGridGroupCellWithName;
using chrome_test_util::TabGridNewTabButton;
using chrome_test_util::TabGridSearchBar;
using chrome_test_util::TabGridSearchTabsButton;
using chrome_test_util::TabGridSelectTabsMenuButton;
using chrome_test_util::TabGridUndoCloseAllButton;
using chrome_test_util::TabGroupBackButton;
using chrome_test_util::TabGroupCreationView;
using chrome_test_util::TabGroupOverflowMenuButton;
using chrome_test_util::TabGroupSnackBar;
using chrome_test_util::TabGroupView;
using chrome_test_util::TabGroupViewTitle;
using chrome_test_util::UngroupButton;
using chrome_test_util::UngroupConfirmationButton;
using chrome_test_util::WindowWithNumber;
using testing::NavigationBarBackButton;

namespace {

NSString* const kTab1Title = @"Tab1";
NSString* const kTab2Title = @"Tab2";

// Put the number at the beginning to avoid issues with sentence case, as the
// keyboard default can differ iPhone vs iPad, simulator vs device.
NSString* const kGroup1Name = @"1group";
NSString* const kGroup2Name = @"2group";

// Displays the tab cell context menu by long pressing at the tab cell at
// `tab_cell_index`.
void DisplayContextMenuForTabCellAtIndex(int tab_cell_index) {
  [[EarlGrey selectElementWithMatcher:TabGridCellAtIndex(tab_cell_index)]
      performAction:grey_longPress()];
}

// Displays the group cell context menu by long pressing at the group cell at
// `group_cell_index`.
void DisplayContextMenuForGroupCellAtIndex(int group_cell_index) {
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellAtIndex(group_cell_index)]
      performAction:grey_longPress()];
}

// Creates a group with default title from a tab cell at index `tab_cell_index`
// when no group is in the grid.
void CreateDefaultFirstGroupFromTabCellAtIndex(int tab_cell_index) {
  DisplayContextMenuForTabCellAtIndex(tab_cell_index);
  [[EarlGrey
      selectElementWithMatcher:
          ContextMenuItemWithAccessibilityLabel(l10n_util::GetPluralNSStringF(
              IDS_IOS_CONTENT_CONTEXT_ADDTABTONEWTABGROUP, 1))]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupCreationView()];
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
}

// Creates a group with default title from a tab cell at index `tab_cell_index`
// when the grid contains groups.
void CreateAdditionalDefaultGroupFromTabCellAtIndex(int tab_cell_index) {
  DisplayContextMenuForTabCellAtIndex(tab_cell_index);
  [[EarlGrey
      selectElementWithMatcher:ContextMenuItemWithAccessibilityLabel(
                                   l10n_util::GetPluralNSStringF(
                                       IDS_IOS_CONTENT_CONTEXT_ADDTABTOTABGROUP,
                                       1))] performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:AddTabToGroupSubMenuButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupCreationView()];
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
}

// Returns the matcher for the tab grid tab count.
id<GREYMatcher> TabGridTabCount(NSString* count_string) {
  return grey_allOf(grey_ancestor(grey_kindOfClassName(@"TabGridPageControl")),
                    grey_text(count_string), grey_sufficientlyVisible(), nil);
}

// Adds the tab at `tab_cell_index` to the group with `title`.
void AddTabAtIndexToGroupWithTitle(int tab_cell_index, NSString* title) {
  DisplayContextMenuForTabCellAtIndex(tab_cell_index);
  [[EarlGrey
      selectElementWithMatcher:ContextMenuItemWithAccessibilityLabel(
                                   l10n_util::GetPluralNSStringF(
                                       IDS_IOS_CONTENT_CONTEXT_ADDTABTOTABGROUP,
                                       1))] performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:ContextMenuItemWithAccessibilityLabel(
                                          title)] performAction:grey_tap()];
}

// Opens the tab group at `group_cell_index`.
void OpenTabGroupAtIndex(int group_cell_index) {
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGridGroupCellAtIndex(
                                                          group_cell_index)];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellAtIndex(group_cell_index)]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGridCellAtIndex(0)];
}

// Opens the tab group creation view using the long press context menu for the
// tab at `index`.
void OpenTabGroupCreationViewUsingLongPressForCellAtIndex(int index) {
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::TabGridCellAtIndex(index)]
      performAction:grey_longPress()];

  [[EarlGrey
      selectElementWithMatcher:grey_text(l10n_util::GetPluralNSStringF(
                                   IDS_IOS_CONTENT_CONTEXT_ADDTABTONEWTABGROUP,
                                   1))] performAction:grey_tap()];

  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupCreationView()];
}

// Sets the tab group name in the tab group creation view.
void SetTabGroupCreationName(NSString* group_name) {
  [[EarlGrey selectElementWithMatcher:CreateTabGroupTextField()]
      performAction:grey_tap()];
  [ChromeEarlGrey simulatePhysicalKeyboardEvent:group_name flags:0];
}

// Renames the group cell at index `group_cell_index` with `title`.
void RenameGroupAtIndex(int group_cell_index, NSString* title) {
  DisplayContextMenuForGroupCellAtIndex(group_cell_index);
  [[EarlGrey selectElementWithMatcher:RenameGroupButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupCreationView()];
  [ChromeEarlGrey simulatePhysicalKeyboardEvent:title flags:0];
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey
      waitForUIElementToDisappearWithMatcher:TabGroupCreationView()];
}

// Ungroups the group cell at index `group_cell_index`.
void UngroupGroupAtIndex(int group_cell_index) {
  DisplayContextMenuForGroupCellAtIndex(group_cell_index);
  [[EarlGrey selectElementWithMatcher:UngroupButton()]
      performAction:grey_tap()];
  // Tap a ungroup button again to confirm the deletion.
  [[EarlGrey selectElementWithMatcher:UngroupConfirmationButton()]
      performAction:grey_tap()];
}

// Deletes the group cell at index `group_cell_index`.
void DeleteGroupAtIndex(int group_cell_index) {
  DisplayContextMenuForGroupCellAtIndex(group_cell_index);
  [[EarlGrey selectElementWithMatcher:DeleteGroupButton()]
      performAction:grey_tap()];
  // Tap a delete button again to confirm the deletion.
  [[EarlGrey selectElementWithMatcher:DeleteGroupConfirmationButton()]
      performAction:grey_tap()];
}

// Closes the group cell at index `group_cell_index`.
void CloseGroupAtIndex(int group_cell_index) {
  DisplayContextMenuForGroupCellAtIndex(group_cell_index);
  [[EarlGrey selectElementWithMatcher:CloseGroupButton()]
      performAction:grey_tap()];
}

// Matcher for the pinned cell at the given `index`.
id<GREYMatcher> GetMatcherForPinnedCellWithTitle(NSString* title) {
  return grey_allOf(
      grey_accessibilityLabel([NSString stringWithFormat:@"Pinned, %@", title]),
      grey_kindOfClassName(@"PinnedCell"), grey_sufficientlyVisible(), nil);
}

}  // namespace

// Test Tab Groups feature.
@interface TabGroupsTestCase : ChromeTestCase
@end

@implementation TabGroupsTestCase

- (void)setUp {
  [super setUp];
  RegisterQueryTitleHandler(self.testServer);
  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start");
  [ChromeEarlGrey
      resetDataForLocalStatePref:prefs::kIncognitoAuthenticationSetting];
}

- (void)tearDown {
  [ChromeEarlGrey
      resetDataForLocalStatePref:prefs::kIncognitoAuthenticationSetting];
  [super tearDown];
}

- (AppLaunchConfiguration)appConfigurationForTestCase {
  AppLaunchConfiguration config;
  config.features_enabled.push_back(kTabGroupsInGrid);
  config.features_enabled.push_back(kTabGroupsIPad);
  config.features_enabled.push_back(kModernTabStrip);
  config.features_enabled.push_back(kTabGroupSync);
  config.features_enabled.push_back(kTabGroupIndicator);
  return config;
}

// Verifies that the tab grid has exactly `expectedCount` tabs.
- (void)verifyVisibleTabsCount:(NSUInteger)expectedCount {
  // Verify that the cell # `expectedCount` exist.
  if (expectedCount == 0) {
    [[EarlGrey selectElementWithMatcher:TabGridCell()]
        assertWithMatcher:grey_nil()];
  } else {
    [[[EarlGrey selectElementWithMatcher:TabGridCell()]
        atIndex:expectedCount - 1] assertWithMatcher:grey_notNil()];
  }
  // Then verify that there is no more cells after that.
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(TabGridCell(),
                                          TabGridCellAtIndex(expectedCount),
                                          nil)] assertWithMatcher:grey_nil()];
}

// Tests that creates a tab group and opens the grouped tab.
- (void)testCompleteTabGroupCreation {
  [ChromeEarlGreyUI openTabGrid];

  // Open the creation view.
  OpenTabGroupCreationViewUsingLongPressForCellAtIndex(0);
  SetTabGroupCreationName(kGroup1Name);

  // Valid the creation.
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey
      waitForUIElementToDisappearWithMatcher:TabGroupCreationView()];

  // Open the group.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup1Name, 1)]
      performAction:grey_tap()];

  // Open the tab.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridCellAtIndex(0)]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:chrome_test_util::RegularTabGrid()]
      assertWithMatcher:grey_notVisible()];
}

// Tests that cancels a tab group creation.
- (void)testCancelTabGroupCreation {
  [ChromeEarlGreyUI openTabGrid];

  // Open the creation view.
  OpenTabGroupCreationViewUsingLongPressForCellAtIndex(0);
  SetTabGroupCreationName(kGroup1Name);

  // Cancel the creation.
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCancelButton()]
      performAction:grey_tap()];

  [ChromeEarlGrey
      waitForUIElementToDisappearWithMatcher:TabGroupCreationView()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup1Name, 0)]
      assertWithMatcher:grey_nil()];
}

// Tests clearing the text field in Tab Group creation flow.
- (void)testClearTextTabGroupCreation {
  [ChromeEarlGreyUI openTabGrid];

  // Open the creation view.
  OpenTabGroupCreationViewUsingLongPressForCellAtIndex(0);
  SetTabGroupCreationName(kGroup1Name);

  // Clear the text field.
  [[EarlGrey selectElementWithMatcher:CreateTabGroupTextFieldClearButton()]
      performAction:grey_tap()];

  // Valid the creation.
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];

  // Check that there is no group named kGroup1Name but one with the number of
  // tabs.
  [ChromeEarlGrey
      waitForUIElementToDisappearWithMatcher:TabGroupCreationView()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup1Name, 0)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_notNil()];
}

// Tests the group creation based on the context menu a tab cell in the grid.
- (void)testGroupCreationUsingTabContextMenuInGrid {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  // Check for the presence of the tab cell with the title `Tab 1` in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // `Tab 1` tab cell no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];

  OpenTabGroupAtIndex(0);

  // Check that `Tab 1` tab cell is in the group.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];

  [[EarlGrey selectElementWithMatcher:NavigationBarBackButton()]
      performAction:grey_tap()];

  // Create a tab cell with `Tab 2` as its title.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab2Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateAdditionalDefaultGroupFromTabCellAtIndex(1);

  // `Tab 2` tab cell no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_nil()];

  OpenTabGroupAtIndex(1);

  // Check that `Tab 2` tab cell is in the group.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_notNil()];
}

// Tests adding a tab to a group from the tab's context menu.
- (void)testAddingTabToGroupUsingTabContextMenu {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  // Check for the presence of the tab cell with the title `Tab 1` in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey selectElementWithMatcher:TabGridTabCount(@"1")]
      assertWithMatcher:grey_notNil()];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // `Tab 1` tab cell no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];

  // Create a tab cell with `Tab 2` as its title.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab2Title)];
  [ChromeEarlGreyUI openTabGrid];
  [[EarlGrey selectElementWithMatcher:TabGridTabCount(@"2")]
      assertWithMatcher:grey_notNil()];

  AddTabAtIndexToGroupWithTitle(
      1, l10n_util::GetPluralNSStringF(IDS_IOS_TAB_GROUP_TABS_NUMBER, 1));

  // `Tab 2` tab cell no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGridTabCount(@"2")]
      assertWithMatcher:grey_notNil()];

  OpenTabGroupAtIndex(0);

  // Check that `Tab 2` tab cell is in the group.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_notNil()];

  // Close the tab and check it is no longer visible.
  [[EarlGrey selectElementWithMatcher:chrome_test_util::
                                          TabGridCloseButtonForCellAtIndex(1)]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_nil()];
}

// Tests the group renaming from the group's context menu in the grid.
- (void)testRenamingGroupUsingGridContextMenu {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  // Check for the presence of the tab cell with the title `Tab 1` in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // `Tab 1` tab cell no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];

  RenameGroupAtIndex(0, kGroup1Name);

  // Check the group's new name.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup1Name, 1)]
      assertWithMatcher:grey_notNil()];
}

// Tests the ungrouping of a group from its context menu in the grid.
- (void)testUngroupingGroupUsingGridContextMenu {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  UngroupGroupAtIndex(0);

  // `Tab 1` tab cell is now present in the grid.
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabWithTitle(kTab1Title)];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];

  // The created group is no longer in the grid.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];
}

// Tests the group deletion from the group's context menu in the grid.
- (void)testDeletingGroupUsingGridContextMenu {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  DeleteGroupAtIndex(0);

  // The tab and the group are deleted.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];

  // Check that the snackbar is not dislpayed.
  [[EarlGrey selectElementWithMatcher:TabGroupSnackBar(1)]
      assertWithMatcher:grey_nil()];
}

// Tests closing a group from the group's context menu action in the grid.
- (void)testClosingGroupUsingGridContextMenu {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  CloseGroupAtIndex(0);

  // The tab and the group are closed.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];

  // Check that the snackbar is dislpayed.
  [[EarlGrey selectElementWithMatcher:TabGroupSnackBar(1)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests ungrouping of a group from the overflow menu in the group view.
- (void)testUngroupingGroupFromGroupView {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // Open the group view.
  OpenTabGroupAtIndex(0);

  // Display the tab group overflow menu.
  [[EarlGrey selectElementWithMatcher:TabGroupOverflowMenuButton()]
      performAction:grey_tap()];

  // Tap the ungroup button.
  [[EarlGrey selectElementWithMatcher:UngroupButton()]
      performAction:grey_tap()];
  // Tap a delete button again to confirm the deletion.
  [[EarlGrey selectElementWithMatcher:UngroupConfirmationButton()]
      performAction:grey_tap()];

  // `Tab 1` tab cell is now present in the grid.
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabWithTitle(kTab1Title)];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];

  // The created group is no longer in the grid.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];
}

// Tests the group deletion from the overflow menu in the group view.
- (void)testDeletingGroupFromGroupView {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // Open the group view.
  OpenTabGroupAtIndex(0);

  // Display the tab group overflow menu.
  [[EarlGrey selectElementWithMatcher:TabGroupOverflowMenuButton()]
      performAction:grey_tap()];

  // Tap the delete button.
  [[EarlGrey selectElementWithMatcher:DeleteGroupButton()]
      performAction:grey_tap()];
  // Tap a delete button again to confirm the deletion.
  [[EarlGrey selectElementWithMatcher:DeleteGroupConfirmationButton()]
      performAction:grey_tap()];

  // The tab and the group are deleted.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];
}

// Tests tapping on the "+" button in the Tab Group view.
- (void)testAddNewTabButtonFromGroupView {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  [ChromeEarlGrey waitForMainTabCount:1];

  // Open the group view.
  OpenTabGroupAtIndex(0);

  // Check that the title is "1 tab".
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kTabGroupViewTitleIdentifier)]
      assertWithMatcher:grey_accessibilityLabel(l10n_util::GetPluralNSStringF(
                            IDS_IOS_TAB_GROUP_TABS_NUMBER, 1))];

  [[EarlGrey
      selectElementWithMatcher:grey_allOf(ButtonWithAccessibilityLabelId(
                                              IDS_IOS_TAB_GRID_CREATE_NEW_TAB),
                                          grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];

  [ChromeEarlGrey waitForMainTabCount:2];

  [ChromeEarlGreyUI openTabGrid];

  // Make sure the Tab Group view is reopened and its title is "2 tabs".
  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                          kTabGroupViewTitleIdentifier)]
      assertWithMatcher:grey_accessibilityLabel(l10n_util::GetPluralNSStringF(
                            IDS_IOS_TAB_GROUP_TABS_NUMBER, 2))];
}

// Tests cancelling of the deletion of a group from the overflow menu in the
// group view.
- (void)testCancellingActionToGroupFromGroupView {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // Open the group view.
  OpenTabGroupAtIndex(0);

  // Display the tab group overflow menu.
  [[EarlGrey selectElementWithMatcher:TabGroupOverflowMenuButton()]
      performAction:grey_tap()];

  // Tap the delete button.
  [[EarlGrey selectElementWithMatcher:DeleteGroupButton()]
      performAction:grey_tap()];
  // Cancel the action by tapping a tab itself (= outside the delete button).
  // We have a cancel button only on iPhone.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      performAction:grey_tap()];

  // Check that `Tab 1` tab cell still exists in the group.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];

  // Go back to the tab grid.
  [[EarlGrey selectElementWithMatcher:TabGroupBackButton()]
      performAction:grey_tap()];
  // Check that the group still exists.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_notNil()];
}

// Tests closing the group from the close button.
- (void)testCloseTabGroup {
  AppLaunchConfiguration config = [self appConfigurationForTestCase];
  config.iph_feature_enabled = "IPH_iOSSavedTabGroupClosed";
  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];

  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TabGridCloseButtonForGroupCellAtIndex(0)]
      performAction:grey_tap()];

  // The tab and the group are deleted.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];

  // The snackbar is not shown, the IPH is shown.
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::StaticTextWithAccessibilityLabelId(
                     IDS_IOS_TAB_GRID_SAVED_TAB_GROUPS)]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:TabGroupSnackBar(1)]
      assertWithMatcher:grey_nil()];

  // Check that the second close doesn't trigger the IPH.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];
  CreateDefaultFirstGroupFromTabCellAtIndex(0);
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::TabGridCloseButtonForGroupCellAtIndex(0)]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];

  // The snackbar is shown, the IPH is not shown.
  [[EarlGrey selectElementWithMatcher:
                 chrome_test_util::StaticTextWithAccessibilityLabelId(
                     IDS_IOS_TAB_GRID_SAVED_TAB_GROUPS)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGroupSnackBar(1)]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests the creation of a new group in selection mode.
- (void)testGroupCreationInSelectionMode {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  // Enter the selection mode.
  [[EarlGrey selectElementWithMatcher:TabGridEditButton()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabGridSelectTabsMenuButton()]
      performAction:grey_tap()];

  // Select the cell with the title `kTab1Title`.
  [[EarlGrey selectElementWithMatcher:TabGridCellAtIndex(0)]
      performAction:grey_tap()];

  // Add the tab to a new group.
  [[EarlGrey selectElementWithMatcher:TabGridEditAddToButton()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:AddTabToNewGroupButton()]
      performAction:grey_tap()];

  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupCreationView()];
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey
      waitForUIElementToDisappearWithMatcher:TabGroupCreationView()];

  // `Tab 1` tab cell no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];

  // The group with title `1 Tab` is present in the grid.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_notNil()];
}

// Tests the adding a tab to a group in selection mode.
- (void)testAddingTabToGroupInSelectionMode {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // Create a tab cell with `Tab 2` as its title.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab2Title)];
  [ChromeEarlGreyUI openTabGrid];

  // Enter the selection mode.
  [[EarlGrey selectElementWithMatcher:TabGridEditButton()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabGridSelectTabsMenuButton()]
      performAction:grey_tap()];

  // Select the cell with the title `kTab2Title`.
  [[EarlGrey selectElementWithMatcher:TabGridCellAtIndex(1)]
      performAction:grey_tap()];

  // Add the selected tab to the group with title `1 Tab`.
  [[EarlGrey selectElementWithMatcher:TabGridEditAddToButton()]
      performAction:grey_tap()];
  [[EarlGrey
      selectElementWithMatcher:ContextMenuItemWithAccessibilityLabel(
                                   l10n_util::GetPluralNSStringF(
                                       IDS_IOS_CONTENT_CONTEXT_ADDTABTOTABGROUP,
                                       1))] performAction:grey_tap()];
  NSString* title =
      l10n_util::GetPluralNSStringF(IDS_IOS_TAB_GROUP_TABS_NUMBER, 1);
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(
                                   ContextMenuItemWithAccessibilityLabel(title),
                                   grey_not(grey_accessibilityTrait(
                                       UIAccessibilityTraitNotEnabled)),
                                   grey_sufficientlyVisible(), nil)]
      performAction:grey_tap()];

  // `Tab 2` tab cell no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_nil()];

  // The group with title `1 Tab` is no longer present in the grid.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];

  // The group with title `2 Tabs` is present in the grid.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 2),
                                          2)] assertWithMatcher:grey_notNil()];
}

// Checks that all the options are displayed in the group's overflow menu.
- (void)testAppropriateOverflowMenuInGroupView {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  OpenTabGroupAtIndex(0);

  // Display the tab group overflow menu.
  [[EarlGrey selectElementWithMatcher:TabGroupOverflowMenuButton()]
      performAction:grey_tap()];

  // Check the different buttons.
  [[EarlGrey selectElementWithMatcher:RenameGroupButton()]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:UngroupButton()]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:DeleteGroupButton()]
      assertWithMatcher:grey_sufficientlyVisible()];
  [[EarlGrey selectElementWithMatcher:CloseGroupButton()]
      assertWithMatcher:grey_sufficientlyVisible()];
}

// Tests closing all tabs and groups in grid, and that the closing is reversible
// when pressing the undo button.
- (void)testCloseAllAndUndo {
  // Create a tab cell with `Tab 1` as its title.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // Create a tab cell with `Tab 2` as its title.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab2Title)];
  [ChromeEarlGreyUI openTabGrid];

  // Check that `Tab 2` and the group with title ` 1 Tab`are in the grid and
  // `Tab 1` is not.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_notNil()];

  // Close all (groups and tabs).
  [[EarlGrey selectElementWithMatcher:TabGridEditButton()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabGridEditMenuCloseAllButton()]
      performAction:grey_tap()];

  // Check that `Tab 2` and the group with title `1 Tab` are no longer in the
  // grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_nil()];

  // Check that the snackbar is dislpayed.
  [[EarlGrey selectElementWithMatcher:TabGroupSnackBar(1)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // Tap Undo button.
  [[EarlGrey selectElementWithMatcher:TabGridUndoCloseAllButton()]
      performAction:grey_tap()];

  // Check that `Tab 2` and the group with title `1 Tab` are back in the grid.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(
                                          l10n_util::GetPluralNSStringF(
                                              IDS_IOS_TAB_GROUP_TABS_NUMBER, 1),
                                          1)] assertWithMatcher:grey_notNil()];
}

// Tests opening a tab group after resetting the incognito browser (i.e. closing
// all incognito tabs).
- (void)testOpenTabGroupAfterBrowserReset {
  // Create one incognito tab then close all of them to reset the browser.
  [ChromeEarlGrey openNewIncognitoTab];
  [ChromeEarlGrey waitForIncognitoTabCount:1];
  [ChromeEarlGrey closeAllIncognitoTabs];
  [ChromeEarlGrey waitForIncognitoTabCount:0];

  [ChromeEarlGrey openNewIncognitoTab];
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  OpenTabGroupAtIndex(0);
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];

  [[EarlGrey selectElementWithMatcher:chrome_test_util::
                                          TabGridCloseButtonForCellAtIndex(0)]
      performAction:grey_tap()];
}

// Tests re-opening a group from Search in another window.
- (void)testReopenGroupFromAnotherWindow {
  if (![ChromeEarlGrey areMultipleWindowsSupported]) {
    EARL_GREY_TEST_SKIPPED(@"Multiple windows can't be opened.");
  }

  // Create a first group.
  [ChromeEarlGreyUI openTabGrid];
  OpenTabGroupCreationViewUsingLongPressForCellAtIndex(0);
  SetTabGroupCreationName(kGroup1Name);
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey
      waitForUIElementToDisappearWithMatcher:TabGroupCreationView()];

  // Create a second group.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGreyUI openTabGrid];
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridCellAtIndex(1)]
      performAction:grey_longPress()];
  [[EarlGrey
      selectElementWithMatcher:grey_text(l10n_util::GetPluralNSStringF(
                                   IDS_IOS_CONTENT_CONTEXT_ADDTABTOTABGROUP,
                                   1))] performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:AddTabToGroupSubMenuButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupCreationView()];
  SetTabGroupCreationName(kGroup2Name);
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey
      waitForUIElementToDisappearWithMatcher:TabGroupCreationView()];

  // Open a second window.
  [ChromeEarlGrey openNewWindow];
  [ChromeEarlGrey waitUntilReadyWindowWithNumber:1];
  [ChromeEarlGrey waitForForegroundWindowCount:2];

  // Search in the second window for the first group of the first window.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(1)];
  [ChromeEarlGreyUI openTabGrid];
  [[EarlGrey selectElementWithMatcher:TabGridSearchTabsButton()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabGridSearchBar()]
      performAction:grey_replaceText(@"1gr")];

  // Tap on it in the second window.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup1Name, 1)]
      performAction:grey_tap()];

  // Verify that it opens in the first window.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(0)];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupView()];
  [[EarlGrey selectElementWithMatcher:TabGroupViewTitle(kGroup1Name)]
      assertWithMatcher:grey_notNil()];

  // Tap on it again in the second window.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(1)];
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup1Name, 1)]
      performAction:grey_tap()];

  // Verify that it's still open in the first window.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(0)];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupView()];
  [[EarlGrey selectElementWithMatcher:TabGroupViewTitle(kGroup1Name)]
      assertWithMatcher:grey_notNil()];

  // Search in the second window for the second group of the first window.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(1)];
  [[EarlGrey selectElementWithMatcher:TabGridSearchBar()]
      performAction:grey_replaceText(@"2gr")];

  // Tap on it in the second window.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup2Name, 1)]
      performAction:grey_tap()];

  // Verify that it opens in the first window.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(0)];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupView()];
  [[EarlGrey selectElementWithMatcher:TabGroupViewTitle(kGroup2Name)]
      assertWithMatcher:grey_notNil()];
}

// Tests that the TabGrid is correctly updated when it was presenting a group
// before being backgrounded while incognito reauth is enabled.
- (void)testIncognitoReauth {
  [ChromeEarlGrey openNewIncognitoTab];
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  OpenTabGroupAtIndex(0);

  [ChromeEarlGrey setBoolValue:YES
             forLocalStatePref:prefs::kIncognitoAuthenticationSetting];
  [[AppLaunchManager sharedManager] backgroundAndForegroundApp];

  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::TabGridNewIncognitoTabButton()]
      assertWithMatcher:grey_not(grey_enabled())];
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridDoneButton()]
      assertWithMatcher:grey_not(grey_enabled())];
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridEditButton()]
      assertWithMatcher:grey_not(grey_enabled())];
  [[EarlGrey selectElementWithMatcher:chrome_test_util::TabGridCellAtIndex(0)]
      assertWithMatcher:grey_notVisible()];

  // Label of the button used to reauth.
  NSString* buttonLabel = l10n_util::GetNSStringF(
      IDS_IOS_INCOGNITO_REAUTH_UNLOCK_BUTTON_VOICEOVER_LABEL,
      base::SysNSStringToUTF16(BiometricAuthenticationTypeString()));
  [[EarlGrey selectElementWithMatcher:testing::ButtonWithAccessibilityLabel(
                                          buttonLabel)]
      assertWithMatcher:grey_sufficientlyVisible()];

  [ChromeEarlGrey
      resetDataForLocalStatePref:prefs::kIncognitoAuthenticationSetting];

  // Reset the app to make sure the incognito shield is removed.
  AppLaunchConfiguration config;
  config.relaunch_policy = ForceRelaunchByCleanShutdown;
  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
}

// Tests that the group view is correctly updated after backgrounding and
// foregrounding the app.
- (void)testBackgroundingGroupViewWithMultipleNTPs {
  [ChromeEarlGreyUI openTabGrid];

  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  // Open a second NTP.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGreyUI openTabGrid];

  // Move it to the group.
  AddTabAtIndexToGroupWithTitle(
      1, l10n_util::GetPluralNSStringF(IDS_IOS_TAB_GROUP_TABS_NUMBER, 1));

  // Open a third NTP.
  [ChromeEarlGrey openNewTab];
  [ChromeEarlGreyUI openTabGrid];

  // Move it to the group.
  AddTabAtIndexToGroupWithTitle(
      1, l10n_util::GetPluralNSStringF(IDS_IOS_TAB_GROUP_TABS_NUMBER, 2));

  OpenTabGroupAtIndex(0);

  // Check the UI before backgrounding the app.
  [self verifyVisibleTabsCount:3];
  [[EarlGrey
      selectElementWithMatcher:TabGroupViewTitle(l10n_util::GetPluralNSStringF(
                                   IDS_IOS_TAB_GROUP_TABS_NUMBER, 3))]
      assertWithMatcher:grey_notNil()];

  // Background then foreground the app.
  [[AppLaunchManager sharedManager] backgroundAndForegroundApp];
  [self verifyVisibleTabsCount:1];
  [[EarlGrey
      selectElementWithMatcher:TabGroupViewTitle(l10n_util::GetPluralNSStringF(
                                   IDS_IOS_TAB_GROUP_TABS_NUMBER, 1))]
      assertWithMatcher:grey_notNil()];
}

// Tests opening a tab from the group view.
- (void)testOpenTabFromGroupView {
  std::string URL1 = "chrome://version";
  std::string URL2 = "chrome://about";
  std::string content1 = "Revision";
  std::string content2 = "List of Chrome URLs";

  // Load the first website.
  [ChromeEarlGrey loadURL:GURL(URL1)];
  [ChromeEarlGrey waitForWebStateContainingText:content1];
  [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(URL1)]
      assertWithMatcher:grey_notNil()];
  NSString* versionTabTitle = [ChromeEarlGrey currentTabTitle];

  // Load the second website and this one should be the selected one.
  [ChromeEarlGreyUI openNewTab];
  [ChromeEarlGrey loadURL:GURL(URL2)];
  [ChromeEarlGrey waitForWebStateContainingText:content2];
  NSString* aboutTabTitle = [ChromeEarlGrey currentTabTitle];

  // Create and open the group with the first loaded website.
  [ChromeEarlGreyUI openTabGrid];
  CreateDefaultFirstGroupFromTabCellAtIndex(0);
  OpenTabGroupAtIndex(0);
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(aboutTabTitle)]
      assertWithMatcher:grey_nil()];

  // Open the tab (currently not the selected one) and ensure this is the same
  // website loaded previously.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForWebStateContainingText:content1];

  // Open it again as it is the selected one now.
  [ChromeEarlGreyUI openTabGrid];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForWebStateContainingText:content1];

  // Go back to tab grid and check the group view is open.
  [ChromeEarlGreyUI openTabGrid];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(aboutTabTitle)]
      assertWithMatcher:grey_nil()];

  // Go back to the tab grid.
  [[EarlGrey selectElementWithMatcher:TabGroupBackButton()]
      performAction:grey_tap()];
  [ChromeEarlGrey
      waitForUIElementToAppearWithMatcher:TabGridGroupCellAtIndex(0)];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(aboutTabTitle)]
      assertWithMatcher:grey_notNil()];
}

// Ensures inactive tabs are moved correctly when creating a group from search
// result.
- (void)testCreateGroupFromInactiveTab {
  // This test is not relevant on iPads because there is no inactive tabs in
  // iPad.
  if ([ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_SKIPPED(@"Skipped for iPad.");
  }

  std::string URL1 = "chrome://version";
  std::string content1 = "Revision";

  // Load the first website.
  [ChromeEarlGrey loadURL:GURL(URL1)];
  [ChromeEarlGrey waitForWebStateContainingText:content1];
  NSString* versionTabTitle = [ChromeEarlGrey currentTabTitle];

  GREYAssertTrue([ChromeEarlGrey mainTabCount] == 1,
                 @"Main tab count should be 1");
  GREYAssertTrue([ChromeEarlGrey incognitoTabCount] == 0,
                 @"Incognito tab count should be 0");
  GREYAssertTrue([ChromeEarlGrey inactiveTabCount] == 0,
                 @"Inactive tab count should be 0");

  AppLaunchConfiguration config = [self appConfigurationForTestCase];
  config.relaunch_policy = ForceRelaunchByCleanShutdown;
  config.additional_args.push_back(
      "--enable-features=" + std::string(kTabInactivityThreshold.name) + ":" +
      kTabInactivityThresholdParameterName + "/" +
      kTabInactivityThresholdImmediateDemoParam);
  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];

  [ChromeEarlGreyUI openTabGrid];

  // The Inactive Tabs button should be visible.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kInactiveTabsButtonAccessibilityIdentifier)]
      assertWithMatcher:grey_sufficientlyVisible()];

  // There should be one inactive tab.
  GREYAssertTrue([ChromeEarlGrey mainTabCount] == 1,
                 @"Main tab count should be 1");
  GREYAssertTrue([ChromeEarlGrey incognitoTabCount] == 0,
                 @"Incognito tab count should be 0");
  GREYAssertTrue([ChromeEarlGrey inactiveTabCount] == 1,
                 @"Inactive tab count should be 1");

  // The previously opened website should be in inactive now.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      assertWithMatcher:grey_nil()];

  // Search for the inactive tab.
  [[EarlGrey selectElementWithMatcher:TabGridSearchTabsButton()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabGridSearchBar()]
      performAction:grey_replaceText(versionTabTitle)];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      assertWithMatcher:grey_notNil()];

  // Create a group with the displayed tab.
  CreateDefaultFirstGroupFromTabCellAtIndex(0);

  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::TabGridSearchCancelButton()]
      performAction:grey_tap()];
  // The Inactive Tabs button should be no longer present in the grid.
  [[EarlGrey
      selectElementWithMatcher:grey_accessibilityID(
                                   kInactiveTabsButtonAccessibilityIdentifier)]
      assertWithMatcher:grey_notVisible()];

  GREYAssertTrue([ChromeEarlGrey mainTabCount] == 2,
                 @"Main tab count should be 2");
  GREYAssertTrue([ChromeEarlGrey incognitoTabCount] == 0,
                 @"Incognito tab count should be 0");
  GREYAssertTrue([ChromeEarlGrey inactiveTabCount] == 0,
                 @"Inactive tab count should be 0");

  // The inactive tab should be in the group now.
  OpenTabGroupAtIndex(1);
  [[EarlGrey selectElementWithMatcher:TabWithTitle(versionTabTitle)]
      assertWithMatcher:grey_notNil()];
}

// Ensures to create a group from a pinned tab and the tab is no longer pinned.
- (void)testCreateGroupFromPinnedTab {
  // This test is not relevant on iPads because there is no pinned tabs in iPad.
  if ([ChromeEarlGrey isIPadIdiom]) {
    EARL_GREY_TEST_SKIPPED(@"Skipped for iPad.");
  }

  CreatePinnedTabs(1, self.testServer);
  [ChromeEarlGreyUI openTabGrid];

  // Create a group from the pinned tab.
  [[EarlGrey
      selectElementWithMatcher:GetMatcherForPinnedCellWithTitle(@"PinnedTab0")]
      performAction:grey_longPress()];
  [[EarlGrey
      selectElementWithMatcher:
          ContextMenuItemWithAccessibilityLabel(l10n_util::GetPluralNSStringF(
              IDS_IOS_CONTENT_CONTEXT_ADDTABTONEWTABGROUP, 1))]
      performAction:grey_tap()];
  [ChromeEarlGrey waitForUIElementToAppearWithMatcher:TabGroupCreationView()];
  SetTabGroupCreationName(kGroup1Name);
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];

  // Ensure the pinned area and the pinned tab disappeared and the group cell
  // appeared.
  [[EarlGrey selectElementWithMatcher:TabGridGroupCellWithName(kGroup1Name, 1)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey
      selectElementWithMatcher:GetMatcherForPinnedCellWithTitle(@"PinnedTab0")]
      assertWithMatcher:grey_nil()];
  [[EarlGrey
      selectElementWithMatcher:grey_allOf(grey_accessibilityID(
                                              @"PinnedViewIdentifier"),
                                          grey_sufficientlyVisible(), nil)]
      assertWithMatcher:grey_nil()];
}

// Tests the group creation with a tab from another window using search result.
- (void)testCreateGroupFromTabInAnotherWindow {
  if (![ChromeEarlGrey areMultipleWindowsSupported]) {
    EARL_GREY_TEST_DISABLED(@"Multiple windows can't be opened.");
  }

  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab2Title)];

  // Opens a new window.
  [ChromeEarlGrey openNewWindow];
  [ChromeEarlGrey waitUntilReadyWindowWithNumber:1];
  [ChromeEarlGrey waitForForegroundWindowCount:2];

  // Open a link in the 2nd window.
  [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)
       inWindowWithNumber:1];
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(1)];

  // Switch back to the first window and search for the tab in 2nd window.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(0)];
  [ChromeEarlGreyUI openTabGrid];
  [[EarlGrey selectElementWithMatcher:TabGridSearchTabsButton()]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:TabGridSearchBar()]
      performAction:grey_replaceText(kTab1Title)];

  // Create a group from search result.
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      performAction:grey_longPress()];
  [[EarlGrey
      selectElementWithMatcher:
          ContextMenuItemWithAccessibilityLabel(l10n_util::GetPluralNSStringF(
              IDS_IOS_CONTENT_CONTEXT_ADDTABTONEWTABGROUP, 1))]
      performAction:grey_tap()];
  [[EarlGrey selectElementWithMatcher:CreateTabGroupCreateButton()]
      performAction:grey_tap()];
  [[EarlGrey
      selectElementWithMatcher:chrome_test_util::TabGridSearchCancelButton()]
      performAction:grey_tap()];

  // Check the tab been moved in a group in the first window and no longer
  // present in the second one.
  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(0)];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];
  OpenTabGroupAtIndex(1);
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_notNil()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_nil()];

  [EarlGrey setRootMatcherForSubsequentInteractions:WindowWithNumber(1)];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab1Title)]
      assertWithMatcher:grey_nil()];
  [[EarlGrey selectElementWithMatcher:TabWithTitle(kTab2Title)]
      assertWithMatcher:grey_nil()];

  [ChromeEarlGrey closeAllExtraWindows];
}

@end