chromium/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_groups_panel_mediator_unittest.mm

// Copyright 2024 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/ui/tab_switcher/tab_grid/tab_groups/tab_groups_panel_mediator.h"

#import "base/test/metrics/user_action_tester.h"
#import "components/saved_tab_groups/fake_tab_group_sync_service.h"
#import "components/saved_tab_groups/mock_tab_group_sync_service.h"
#import "components/saved_tab_groups/saved_tab_group.h"
#import "components/saved_tab_groups/saved_tab_group_test_utils.h"
#import "components/saved_tab_groups/types.h"
#import "ios/chrome/browser/shared/model/browser/browser_list.h"
#import "ios/chrome/browser/shared/model/browser/browser_list_factory.h"
#import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/chrome/browser/shared/model/web_state_list/tab_group.h"
#import "ios/chrome/browser/shared/model/web_state_list/test/fake_web_state_list_delegate.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mode_holder.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_group_sync_service_observer_bridge.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_groups_panel_consumer.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_groups_panel_item.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/tab_grid_toolbars_configuration.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/toolbars/test/fake_tab_grid_toolbars_mediator.h"
#import "ios/web/public/test/fakes/fake_web_state.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gtest_mac.h"
#import "testing/platform_test.h"

namespace {

using ::testing::_;
using ::testing::Return;
using ::testing::SaveArg;

const char* kSelectTabGroupsUMA = "MobileTabGridSelectTabGroups";

}  // namespace

@interface FakeTabGroupsPanelConsumer : NSObject <TabGroupsPanelConsumer>
@property(nonatomic, readonly, copy) NSArray<TabGroupsPanelItem*>* items;
@property(nonatomic, readonly) NSUInteger populateItemsCallCount;
@property(nonatomic, readonly) NSUInteger reconfigureItemCallCount;
@end

@implementation FakeTabGroupsPanelConsumer

#pragma mark TabGroupsPanelConsumer

- (void)populateItems:(NSArray<TabGroupsPanelItem*>*)items {
  _items = [items copy];
  _populateItemsCallCount++;
}

- (void)reconfigureItem:(TabGroupsPanelItem*)item {
  _reconfigureItemCallCount++;
}

- (void)dismissModals {
}

@end

class TabGroupsPanelMediatorTest : public PlatformTest {
 protected:
  TabGroupsPanelMediatorTest() : web_state_list_(&web_state_list_delegate_) {
    browser_state_ = TestChromeBrowserState::Builder().Build();
    // Create a regular browser.
    browser_ = std::make_unique<TestBrowser>(browser_state_.get());
    browser_list_ =
        BrowserListFactory::GetForBrowserState(browser_state_.get());
    browser_list_->AddBrowser(browser_.get());
    mode_holder_ = [[TabGridModeHolder alloc] init];
  }

  web::WebTaskEnvironment task_environment_;
  std::unique_ptr<TestBrowser> browser_;
  std::unique_ptr<TestChromeBrowserState> browser_state_;
  raw_ptr<BrowserList> browser_list_;
  FakeWebStateListDelegate web_state_list_delegate_;
  WebStateList web_state_list_;
  ::testing::NiceMock<tab_groups::MockTabGroupSyncService>
      tab_group_sync_service_;
  TabGridModeHolder* mode_holder_;
};

// Tests that the service observation starts and stops when the mediator is
// released.
TEST_F(TabGroupsPanelMediatorTest, StartStopObserving_Released) {
  // Use a strict mock.
  tab_groups::MockTabGroupSyncService strict_tab_group_sync_service;
  // Expect the observation start.
  EXPECT_CALL(strict_tab_group_sync_service, AddObserver(_)).Times(1);
  __unused TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&strict_tab_group_sync_service
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];

  // Expect the observation end when the mediator is released.
  EXPECT_CALL(strict_tab_group_sync_service, RemoveObserver(_)).Times(1);
  mediator = nil;
}

// Tests that the service observation starts and stops when the mediator is
// released.
TEST_F(TabGroupsPanelMediatorTest, StartStopObserving_Disconnect) {
  // Use a strict mock.
  tab_groups::MockTabGroupSyncService strict_tab_group_sync_service;
  // Expect the observation start.
  EXPECT_CALL(strict_tab_group_sync_service, AddObserver(_)).Times(1);
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&strict_tab_group_sync_service
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];

  {
    EXPECT_CALL(strict_tab_group_sync_service, RemoveObserver(_)).Times(1);
    [mediator disconnect];
  }
}

// Tests that the UMA for selecting the Tab Groups panel is correctly recorded.
TEST_F(TabGroupsPanelMediatorTest, RecordUMAWhenSelected) {
  base::UserActionTester user_action_tester;
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];

  EXPECT_EQ(0, user_action_tester.GetActionCount(kSelectTabGroupsUMA));

  // Select a different page.
  [mediator currentlySelectedGrid:NO];
  EXPECT_EQ(0, user_action_tester.GetActionCount(kSelectTabGroupsUMA));

  // Select Tab Groups.
  [mediator currentlySelectedGrid:YES];
  EXPECT_EQ(1, user_action_tester.GetActionCount(kSelectTabGroupsUMA));

  // Unselect Tab Groups.
  [mediator currentlySelectedGrid:NO];
  EXPECT_EQ(1, user_action_tester.GetActionCount(kSelectTabGroupsUMA));
}

// Tests that when the panel not the selected one, no toolbar delegate is set,
// no toolbar config is returned.
TEST_F(TabGroupsPanelMediatorTest, NotSelected_NoToolbarsDelegateOrConfig) {
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  FakeTabGridToolbarsMediator* toolbars_mutator =
      [[FakeTabGridToolbarsMediator alloc] init];
  mediator.toolbarsMutator = toolbars_mutator;

  [mediator currentlySelectedGrid:NO];

  EXPECT_EQ(toolbars_mutator.delegate, nil);
  EXPECT_EQ(toolbars_mutator.configuration, nil);
}

// Tests that when the panel is disabled by policy, the toolbars config is the
// disabled one.
TEST_F(TabGroupsPanelMediatorTest, DisabledByPolicy_DisabledToolbarsConfig) {
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:YES
                      browserList:browser_list_];
  FakeTabGridToolbarsMediator* toolbars_mutator =
      [[FakeTabGridToolbarsMediator alloc] init];
  mediator.toolbarsMutator = toolbars_mutator;

  [mediator currentlySelectedGrid:YES];

  EXPECT_EQ(toolbars_mutator.delegate,
            static_cast<id<TabGridToolbarsGridDelegate>>(mediator));
  EXPECT_NE(toolbars_mutator.configuration, nil);
  EXPECT_EQ(TabGridPageTabGroups, toolbars_mutator.configuration.page);

  // All buttons are disabled.
  EXPECT_FALSE(toolbars_mutator.configuration.doneButton);

  EXPECT_FALSE(toolbars_mutator.configuration.selectAllButton);
  EXPECT_EQ(0u, toolbars_mutator.configuration.selectedItemsCount);
  EXPECT_FALSE(toolbars_mutator.configuration.closeSelectedTabsButton);
  EXPECT_FALSE(toolbars_mutator.configuration.shareButton);
  EXPECT_FALSE(toolbars_mutator.configuration.addToButton);

  EXPECT_FALSE(toolbars_mutator.configuration.closeAllButton);
  EXPECT_FALSE(toolbars_mutator.configuration.newTabButton);
  EXPECT_FALSE(toolbars_mutator.configuration.searchButton);
  EXPECT_FALSE(toolbars_mutator.configuration.selectTabsButton);
  EXPECT_FALSE(toolbars_mutator.configuration.undoButton);
  EXPECT_FALSE(toolbars_mutator.configuration.deselectAllButton);
  EXPECT_FALSE(toolbars_mutator.configuration.cancelSearchButton);
}

// Tests that when the panel is selected and not disabled by policy, the
// toolbars delegate and config are set accordingly. Since there are no tab in
// the Regular Tabs page, the Done button is still disabled.
TEST_F(TabGroupsPanelMediatorTest,
       EnabledByPolicyAndSelectedButNoRegularTab_DoneButtonDisabled) {
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  FakeTabGridToolbarsMediator* toolbars_mutator =
      [[FakeTabGridToolbarsMediator alloc] init];
  mediator.toolbarsMutator = toolbars_mutator;

  [mediator currentlySelectedGrid:YES];

  EXPECT_EQ(toolbars_mutator.delegate,
            static_cast<id<TabGridToolbarsGridDelegate>>(mediator));
  EXPECT_NE(toolbars_mutator.configuration, nil);
  EXPECT_EQ(TabGridPageTabGroups, toolbars_mutator.configuration.page);

  // Done button is disabled.
  EXPECT_FALSE(toolbars_mutator.configuration.doneButton);

  // All other buttons are disabled.
  EXPECT_FALSE(toolbars_mutator.configuration.selectAllButton);
  EXPECT_EQ(0u, toolbars_mutator.configuration.selectedItemsCount);
  EXPECT_FALSE(toolbars_mutator.configuration.closeSelectedTabsButton);
  EXPECT_FALSE(toolbars_mutator.configuration.shareButton);
  EXPECT_FALSE(toolbars_mutator.configuration.addToButton);

  EXPECT_FALSE(toolbars_mutator.configuration.closeAllButton);
  EXPECT_FALSE(toolbars_mutator.configuration.newTabButton);
  EXPECT_FALSE(toolbars_mutator.configuration.searchButton);
  EXPECT_FALSE(toolbars_mutator.configuration.selectTabsButton);
  EXPECT_FALSE(toolbars_mutator.configuration.undoButton);
  EXPECT_FALSE(toolbars_mutator.configuration.deselectAllButton);
  EXPECT_FALSE(toolbars_mutator.configuration.cancelSearchButton);
}

// Tests that when the panel is selected and not disabled by policy, the
// toolbars delegate and config are set accordingly. Since there is a Regular
// tab, the Done button is finally enabled.
TEST_F(TabGroupsPanelMediatorTest,
       EnabledByPolicyAndSelectedWithRegularTab_DoneButtonEnabled) {
  // Add a web state in a local scope. Otherwise, the NiceMock for the sync
  // service reports an uninteresting call to RemoveObserver (??).
  {
    auto web_state = std::make_unique<web::FakeWebState>();
    web_state_list_.InsertWebState(std::move(web_state));
  }
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  FakeTabGridToolbarsMediator* toolbars_mutator =
      [[FakeTabGridToolbarsMediator alloc] init];
  mediator.toolbarsMutator = toolbars_mutator;

  [mediator currentlySelectedGrid:YES];

  EXPECT_EQ(toolbars_mutator.delegate,
            static_cast<id<TabGridToolbarsGridDelegate>>(mediator));
  EXPECT_NE(toolbars_mutator.configuration, nil);
  EXPECT_EQ(TabGridPageTabGroups, toolbars_mutator.configuration.page);

  // Done button is enabled.
  EXPECT_TRUE(toolbars_mutator.configuration.doneButton);

  // All other buttons are disabled.
  EXPECT_FALSE(toolbars_mutator.configuration.selectAllButton);
  EXPECT_EQ(0u, toolbars_mutator.configuration.selectedItemsCount);
  EXPECT_FALSE(toolbars_mutator.configuration.closeSelectedTabsButton);
  EXPECT_FALSE(toolbars_mutator.configuration.shareButton);
  EXPECT_FALSE(toolbars_mutator.configuration.addToButton);

  EXPECT_FALSE(toolbars_mutator.configuration.closeAllButton);
  EXPECT_FALSE(toolbars_mutator.configuration.newTabButton);
  EXPECT_FALSE(toolbars_mutator.configuration.searchButton);
  EXPECT_FALSE(toolbars_mutator.configuration.selectTabsButton);
  EXPECT_FALSE(toolbars_mutator.configuration.undoButton);
  EXPECT_FALSE(toolbars_mutator.configuration.deselectAllButton);
  EXPECT_FALSE(toolbars_mutator.configuration.cancelSearchButton);
}

// Tests that setting a consumer before the service initialization doesn't
// populate the consumer
TEST_F(TabGroupsPanelMediatorTest,
       SetConsumerDoesntPopulatesFromUninitializedService) {
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  // Prepare a consumer.
  FakeTabGroupsPanelConsumer* consumer =
      [[FakeTabGroupsPanelConsumer alloc] init];
  EXPECT_NSEQ(consumer.items, nil);
  EXPECT_EQ(consumer.populateItemsCallCount, 0u);
  // Set a saved tab group.
  tab_groups::SavedTabGroup group = tab_groups::test::CreateTestSavedTabGroup();
  std::vector<tab_groups::SavedTabGroup> groups = {group};
  EXPECT_CALL(tab_group_sync_service_, GetAllGroups())
      .WillRepeatedly(Return(groups));

  mediator.consumer = consumer;

  EXPECT_NSEQ(consumer.items, nil);
  EXPECT_EQ(consumer.populateItemsCallCount, 0u);
}

// Tests that setting a consumer after the service initialization populates it
// with data from the service's GetAllGroups API.
TEST_F(TabGroupsPanelMediatorTest,
       SetConsumerPopulatesFromInitializedAndNonEmptyService) {
  tab_groups::TabGroupSyncService::Observer* observer = nullptr;
  EXPECT_CALL(tab_group_sync_service_, AddObserver(_))
      .WillOnce(SaveArg<0>(&observer));
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  EXPECT_NE(observer, nullptr);
  // Prepare a consumer.
  FakeTabGroupsPanelConsumer* consumer =
      [[FakeTabGroupsPanelConsumer alloc] init];
  EXPECT_NSEQ(consumer.items, nil);
  EXPECT_EQ(consumer.populateItemsCallCount, 0u);
  // Set a saved tab group.
  tab_groups::SavedTabGroup group = tab_groups::test::CreateTestSavedTabGroup();
  std::vector<tab_groups::SavedTabGroup> groups = {group};
  EXPECT_CALL(tab_group_sync_service_, GetAllGroups())
      .WillRepeatedly(Return(groups));
  // Initialize the service.
  observer->OnInitialized();

  // Set the consumer.
  mediator.consumer = consumer;

  EXPECT_EQ(consumer.items.count, 1u);
  EXPECT_EQ(consumer.populateItemsCallCount, 1u);
}

// Tests that setting a consumer populates it with data from the service's
// GetAllGroups API.
TEST_F(TabGroupsPanelMediatorTest,
       SetConsumerPopulatesFromInitializedEmptyService) {
  tab_groups::TabGroupSyncService::Observer* observer = nullptr;
  EXPECT_CALL(tab_group_sync_service_, AddObserver(_))
      .WillOnce(SaveArg<0>(&observer));
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  EXPECT_NE(observer, nullptr);
  // Prepare a consumer.
  FakeTabGroupsPanelConsumer* consumer =
      [[FakeTabGroupsPanelConsumer alloc] init];
  EXPECT_NSEQ(consumer.items, nil);
  EXPECT_EQ(consumer.populateItemsCallCount, 0u);
  // Set no saved tab group.
  std::vector<tab_groups::SavedTabGroup> groups = {};
  EXPECT_CALL(tab_group_sync_service_, GetAllGroups())
      .WillRepeatedly(Return(groups));
  // Initialize the service.
  observer->OnInitialized();

  // Set the consumer.
  mediator.consumer = consumer;

  EXPECT_EQ(consumer.items.count, 0u);
  EXPECT_EQ(consumer.populateItemsCallCount, 1u);
}

// Tests that when the sync service is initialized, the consumer is repopulated
// with data from the service's GetAllGroups API.
TEST_F(TabGroupsPanelMediatorTest,
       ServiceInitialized_RequeriesGroupsAndPopulates) {
  tab_groups::TabGroupSyncService::Observer* observer = nullptr;
  EXPECT_CALL(tab_group_sync_service_, AddObserver(_))
      .WillOnce(SaveArg<0>(&observer));
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  EXPECT_NE(observer, nullptr);
  // Set no saved tab group.
  std::vector<tab_groups::SavedTabGroup> groups = {};
  EXPECT_CALL(tab_group_sync_service_, GetAllGroups())
      .WillRepeatedly(Return(groups));
  // Set a consumer.
  FakeTabGroupsPanelConsumer* consumer =
      [[FakeTabGroupsPanelConsumer alloc] init];
  mediator.consumer = consumer;
  EXPECT_NSEQ(consumer.items, nil);
  EXPECT_EQ(consumer.populateItemsCallCount, 0u);
  // Set a saved tab group.
  tab_groups::SavedTabGroup group = tab_groups::test::CreateTestSavedTabGroup();
  groups = {group};
  EXPECT_CALL(tab_group_sync_service_, GetAllGroups())
      .WillRepeatedly(Return(groups));

  observer->OnInitialized();

  EXPECT_EQ(consumer.items.count, 1u);
  EXPECT_EQ(consumer.populateItemsCallCount, 1u);
}

// Tests that the groups pushed to the consumer are sorted with the most recent
// first.
TEST_F(TabGroupsPanelMediatorTest, PopulatesSortedGroups) {
  tab_groups::TabGroupSyncService::Observer* observer = nullptr;
  EXPECT_CALL(tab_group_sync_service_, AddObserver(_))
      .WillOnce(SaveArg<0>(&observer));
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  EXPECT_NE(observer, nullptr);
  // Set a consumer.
  FakeTabGroupsPanelConsumer* consumer =
      [[FakeTabGroupsPanelConsumer alloc] init];
  mediator.consumer = consumer;
  // Set 2 saved tab group with the oldest first.
  tab_groups::SavedTabGroup group_1 = tab_groups::test::CreateTestSavedTabGroup(
      base::Time::Now() - base::Days(2));
  tab_groups::SavedTabGroup group_2 =
      tab_groups::test::CreateTestSavedTabGroup(base::Time::Now());
  std::vector<tab_groups::SavedTabGroup> groups = {group_1, group_2};
  EXPECT_CALL(tab_group_sync_service_, GetAllGroups())
      .WillRepeatedly(Return(groups));
  observer->OnInitialized();

  EXPECT_EQ(consumer.items.count, 2u);
  EXPECT_EQ(consumer.items[0].savedTabGroupID, group_2.saved_guid());
  EXPECT_EQ(consumer.items[1].savedTabGroupID, group_1.saved_guid());
}

// Tests that the consumer is asked to reconfigure an item when the observer
// notifies a group update.
TEST_F(TabGroupsPanelMediatorTest, UpdateGroup) {
  tab_groups::TabGroupSyncService::Observer* observer = nullptr;
  EXPECT_CALL(tab_group_sync_service_, AddObserver(_))
      .WillOnce(SaveArg<0>(&observer));
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:&tab_group_sync_service_
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];
  EXPECT_NE(observer, nullptr);
  // Set a consumer.
  FakeTabGroupsPanelConsumer* consumer =
      [[FakeTabGroupsPanelConsumer alloc] init];
  mediator.consumer = consumer;
  // Set a saved tab group.
  tab_groups::SavedTabGroup group = tab_groups::test::CreateTestSavedTabGroup();
  std::vector<tab_groups::SavedTabGroup> groups = {group};
  EXPECT_CALL(tab_group_sync_service_, GetAllGroups())
      .WillRepeatedly(Return(groups));
  observer->OnInitialized();
  EXPECT_EQ(consumer.items.count, 1u);
  EXPECT_EQ(consumer.reconfigureItemCallCount, 0u);

  observer->OnTabGroupUpdated(group, tab_groups::TriggerSource::REMOTE);

  EXPECT_EQ(consumer.items.count, 1u);
  EXPECT_EQ(consumer.reconfigureItemCallCount, 1u);
}

// Tests that a group which doesn't exist locally is deleted from the tab group
// sync service.
TEST_F(TabGroupsPanelMediatorTest, DeleteRemoteGroup) {
  auto sync_service = std::make_unique<tab_groups::FakeTabGroupSyncService>();
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:sync_service.get()
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];

  // Set a saved tab group.
  tab_groups::SavedTabGroup group = tab_groups::test::CreateTestSavedTabGroup();
  sync_service->AddGroup(group);
  EXPECT_TRUE(sync_service->GetGroup(group.saved_guid()).has_value());

  TabGroupsPanelItem* item = [[TabGroupsPanelItem alloc] init];
  item.savedTabGroupID = group.saved_guid();
  [mediator deleteSyncedTabGroup:item.savedTabGroupID];

  EXPECT_FALSE(sync_service->GetGroup(group.saved_guid()).has_value());
}

// Tests that a group which exists locally is deleted from the tab group sync
// service.
TEST_F(TabGroupsPanelMediatorTest, DeleteLocalGroup) {
  auto sync_service = std::make_unique<tab_groups::FakeTabGroupSyncService>();
  TabGroupsPanelMediator* mediator = [[TabGroupsPanelMediator alloc]
      initWithTabGroupSyncService:sync_service.get()
              regularWebStateList:&web_state_list_
                    faviconLoader:nullptr
                 disabledByPolicy:NO
                      browserList:browser_list_];

  // Create a web state.
  auto fake_web_state = std::make_unique<web::FakeWebState>();
  browser_->GetWebStateList()->InsertWebState(
      std::move(fake_web_state),
      WebStateList::InsertionParams::Automatic().Activate());

  // Create a tab group.
  tab_groups::TabGroupId tab_group_id = tab_groups::TabGroupId::GenerateNew();
  tab_groups::TabGroupVisualData visual_data = tab_groups::TabGroupVisualData(
      u"Test Group", tab_groups::TabGroupColorId::kGrey);
  const TabGroup* tab_group =
      browser_->GetWebStateList()->CreateGroup({0}, visual_data, tab_group_id);

  // Set a saved tab group with a local ID of the tab group created above.
  tab_groups::SavedTabGroup group = tab_groups::test::CreateTestSavedTabGroup();
  group.SetLocalGroupId(tab_group->tab_group_id());
  sync_service->AddGroup(group);
  EXPECT_EQ(1u, browser_->GetWebStateList()->GetGroups().size());
  EXPECT_EQ(1, browser_->GetWebStateList()->count());

  TabGroupsPanelItem* item = [[TabGroupsPanelItem alloc] init];
  item.savedTabGroupID = group.saved_guid();
  [mediator deleteSyncedTabGroup:item.savedTabGroupID];

  // Check if the number of groups and tabs is 0.
  EXPECT_EQ(0u, browser_->GetWebStateList()->GetGroups().size());
  EXPECT_EQ(0, browser_->GetWebStateList()->count());
}