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

#include "chrome/browser/ui/tabs/vertical_tab_strip_state_controller.h"

#include "base/feature_list.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_element_identifiers.h"
#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
#include "chrome/browser/ui/tabs/features.h"
#include "chrome/browser/ui/toasts/api/toast_id.h"
#include "chrome/browser/ui/toasts/toast_controller.h"
#include "chrome/browser/ui/toasts/toast_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/browser_widget.h"
#include "chrome/browser/ui/views/frame/system_menu_model_builder.h"
#include "chrome/browser/ui/views/test/tab_strip_interactive_test_mixin.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/interaction/interactive_browser_test.h"
#include "chrome/test/user_education/interactive_feature_promo_test.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_test.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/test/ui_controls.h"
#include "ui/base/unowned_user_data/user_data_factory.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/scoped_animation_duration_scale_mode.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/interaction/interactive_views_test.h"
#include "ui/views/test/widget_test.h"

namespace base::test {

class FakeImmersiveModeController : public ImmersiveModeController {
 public:
  explicit FakeImmersiveModeController(ui::UnownedUserDataHost& host)
      : ImmersiveModeController(host) {}
  ~FakeImmersiveModeController() override = default;

  void Init(BrowserView* browser_view) override {
    browser_view_ = browser_view;
  }
  void SetEnabled(bool enabled) override {
    enabled_ = enabled;
#if BUILDFLAG(IS_MAC)
    if (browser_view_ && browser_view_->overlay_widget()) {
      if (enabled_) {
        browser_view_->overlay_widget()->Show();
      } else {
        browser_view_->overlay_widget()->Hide();
      }
    }
#endif
    if (enabled_) {
      for (Observer& observer : observers_) {
        observer.OnImmersiveFullscreenEntered();
      }
    } else {
      for (Observer& observer : observers_) {
        observer.OnImmersiveFullscreenExited();
      }
    }
  }
  bool IsEnabled() const override { return enabled_; }
  bool IsRevealed() const override { return false; }
  int GetTopContainerVerticalOffset(
      const gfx::Size& top_container_size) const override {
    return 0;
  }
  std::unique_ptr<ImmersiveRevealedLock> GetRevealedLock(
      AnimateReveal animate_reveal) override {
    return nullptr;
  }
  void OnFindBarVisibleBoundsChanged(
      const gfx::Rect& new_visible_bounds_in_screen) override {}
  bool ShouldStayImmersiveAfterExitingFullscreen() override { return true; }
  int GetMinimumContentOffset() const override { return 0; }
  int GetExtraInfobarOffset() const override { return 0; }
  void OnContentFullscreenChanged(bool is_content_fullscreen) override {}
  void AddObserver(Observer* observer) override {
    ImmersiveModeController::AddObserver(observer);
  }
  void RemoveObserver(Observer* observer) override {
    ImmersiveModeController::RemoveObserver(observer);
  }

 private:
  raw_ptr<BrowserView> browser_view_ = nullptr;
  bool enabled_ = false;
};

class VerticalTabStripInteractiveUiTest : public InteractiveBrowserTest {
 public:
  VerticalTabStripInteractiveUiTest() = default;
  ~VerticalTabStripInteractiveUiTest() override = default;

  void SetUp() override {
    scoped_feature_list_.InitAndEnableFeature(tabs::kVerticalTabsExpandOnHover);
    override_ =
        BrowserWindowFeatures::GetUserDataFactoryForTesting()
            .AddOverrideForTesting<FakeImmersiveModeController>(
                base::BindRepeating(
                    &VerticalTabStripInteractiveUiTest::CreateFakeController,
                    base::Unretained(this)));
    InteractiveBrowserTest::SetUp();
  }

  bool SystemMenuContainsStringId(int message_id) {
    ui::MenuModel* menu_model = BrowserView::GetBrowserViewForBrowser(browser())
                                    ->browser_widget()
                                    ->GetSystemMenuModel();
    for (size_t i = 0; i < menu_model->GetItemCount(); i++) {
      if (l10n_util::GetStringUTF16(message_id) == menu_model->GetLabelAt(i)) {
        return true;
      }
    }
    return false;
  }

  void PostRunTestOnMainThread() override {
    fake_controller_ = nullptr;
    InteractiveBrowserTest::PostRunTestOnMainThread();
  }

 protected:
  std::unique_ptr<FakeImmersiveModeController> CreateFakeController(
      BrowserWindowInterface& owner) {
    auto controller = std::make_unique<FakeImmersiveModeController>(
        owner.GetUnownedUserDataHost());
    fake_controller_ = controller.get();
    return controller;
  }

  raw_ptr<FakeImmersiveModeController> fake_controller_ = nullptr;

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
  std::optional<ui::UserDataFactory::ScopedOverride> override_;
};

#if BUILDFLAG(IS_MAC)
constexpr int kSwitchToVerticalTabStringId = IDS_SWITCH_TO_VERTICAL_TAB_MAC;
constexpr int kSwitchToHorizontalTabStringId = IDS_SWITCH_TO_HORIZONTAL_TAB_MAC;
#else
constexpr int kSwitchToVerticalTabStringId = IDS_SWITCH_TO_VERTICAL_TAB;
constexpr int kSwitchToHorizontalTabStringId = IDS_SWITCH_TO_HORIZONTAL_TAB;
#endif

// Unable to programmatically click System Context Menu Items in Windows.
#if BUILDFLAG(IS_WIN)
#define MAYBE_VerifyTabsToTheSideButton DISABLED_VerifyTabsToTheSideButton
#else
#define MAYBE_VerifyTabsToTheSideButton VerifyTabsToTheSideButton
#endif
// This test checks that we can click the show tabs to the side button
IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       MAYBE_VerifyTabsToTheSideButton) {
  EXPECT_TRUE(SystemMenuContainsStringId(kSwitchToVerticalTabStringId));

  RunTestSequence(
      WaitForShow(kTabStripFrameGrabHandleElementId),
      EnsurePresent(kTabStripFrameGrabHandleElementId),
      MoveMouseTo(kTabStripFrameGrabHandleElementId),
      ClickMouse(ui_controls::RIGHT),
      WaitForShow(SystemMenuModelBuilder::kToggleVerticalTabsElementId),
      SelectMenuItem(SystemMenuModelBuilder::kToggleVerticalTabsElementId),
      WaitForShow(kVerticalTabStripCollapseButtonElementId));

  EXPECT_TRUE(SystemMenuContainsStringId(kSwitchToHorizontalTabStringId));
}

// Unable to programmatically click System Context Menu Items in Windows.
#if BUILDFLAG(IS_WIN)
#define MAYBE_VerifyTabsToTheTopButton DISABLED_VerifyTabsToTheTopButton
#else
#define MAYBE_VerifyTabsToTheTopButton VerifyTabsToTheTopButton
#endif
// This test checks that we can click the show tabs at the top button
IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       MAYBE_VerifyTabsToTheTopButton) {
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(true);

  EXPECT_TRUE(SystemMenuContainsStringId(kSwitchToHorizontalTabStringId));

  RunScheduledLayouts();

  RunTestSequence(
      WaitForShow(kVerticalTabStripTopContainerElementId),
      EnsurePresent(kVerticalTabStripTopContainerElementId),
      MoveMouseTo(kVerticalTabStripTopContainerElementId),
      ClickMouse(ui_controls::RIGHT),
      WaitForShow(SystemMenuModelBuilder::kToggleVerticalTabsElementId),
      SelectMenuItem(SystemMenuModelBuilder::kToggleVerticalTabsElementId),
      WaitForShow(kTabStripFrameGrabHandleElementId));

  EXPECT_TRUE(SystemMenuContainsStringId(kSwitchToVerticalTabStringId));
}

// Unable to programmatically click System Context Menu Items in Windows.
#if BUILDFLAG(IS_WIN)
#define MAYBE_EnablingExpandOnHoverSystemContextMenu \
  DISABLED_EnablingExpandOnHoverSystemContextMenu
#else
#define MAYBE_EnablingExpandOnHoverSystemContextMenu \
  EnablingExpandOnHoverSystemContextMenu
#endif
// This test checks that we can enable the expand on hover behavior via the
// system context menu.
IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       MAYBE_EnablingExpandOnHoverSystemContextMenu) {
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(true);
  tabs::VerticalTabStripStateController::From(browser())
      ->SetExpandOnHoverEnabled(false);

  EXPECT_TRUE(
      SystemMenuContainsStringId(IDS_VERTICAL_TABS_ENABLE_EXPAND_ON_HOVER));

  RunScheduledLayouts();

  RunTestSequence(
      WaitForShow(kVerticalTabStripTopContainerElementId),
      EnsurePresent(kVerticalTabStripTopContainerElementId),
      MoveMouseTo(kVerticalTabStripTopContainerElementId),
      ClickMouse(ui_controls::RIGHT),
      WaitForShow(
          SystemMenuModelBuilder::kToggleVerticalTabsExpandOnHoverElementId),
      SelectMenuItem(
          SystemMenuModelBuilder::kToggleVerticalTabsExpandOnHoverElementId));

  EXPECT_TRUE(
      SystemMenuContainsStringId(IDS_VERTICAL_TABS_DISABLE_EXPAND_ON_HOVER));
}

// Unable to programmatically click System Context Menu Items in Windows.
#if BUILDFLAG(IS_WIN)
#define MAYBE_DisablingExpandOnHoverSystemContextMenu \
  DISABLED_DisablingExpandOnHoverSystemContextMenu
#else
#define MAYBE_DisablingExpandOnHoverSystemContextMenu \
  DisablingExpandOnHoverSystemContextMenu
#endif
// This test checks that we can disable the expand on hover behavior via the
// system context menu.
IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       MAYBE_DisablingExpandOnHoverSystemContextMenu) {
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(true);

  EXPECT_TRUE(
      SystemMenuContainsStringId(IDS_VERTICAL_TABS_DISABLE_EXPAND_ON_HOVER));

  RunScheduledLayouts();

  RunTestSequence(
      WaitForShow(kVerticalTabStripTopContainerElementId),
      EnsurePresent(kVerticalTabStripTopContainerElementId),
      MoveMouseTo(kVerticalTabStripTopContainerElementId),
      ClickMouse(ui_controls::RIGHT),
      WaitForShow(
          SystemMenuModelBuilder::kToggleVerticalTabsExpandOnHoverElementId),
      SelectMenuItem(
          SystemMenuModelBuilder::kToggleVerticalTabsExpandOnHoverElementId));

  EXPECT_TRUE(
      SystemMenuContainsStringId(IDS_VERTICAL_TABS_ENABLE_EXPAND_ON_HOVER));
}

// Unable to programmatically click System Context Menu Items in Windows.
#if BUILDFLAG(IS_WIN)
#define MAYBE_ToggleCollapseSystemContextMenu \
  DISABLED_ToggleCollapseSystemContextMenu
#else
#define MAYBE_ToggleCollapseSystemContextMenu ToggleCollapseSystemContextMenu
#endif
// This test checks that we can toggle the collapse state via the system context
// menu.
IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       MAYBE_ToggleCollapseSystemContextMenu) {
  gfx::ScopedAnimationDurationScaleMode disable_animations(
      gfx::ScopedAnimationDurationScaleMode::ZERO_DURATION);

  auto* controller = tabs::VerticalTabStripStateController::From(browser());
  controller->SetVerticalTabsEnabled(true);

  EXPECT_TRUE(SystemMenuContainsStringId(IDS_COLLAPSE_VERTICAL_TABS));

  RunScheduledLayouts();

  RunTestSequence(
      WaitForShow(kVerticalTabStripTopContainerElementId),
      EnsurePresent(kVerticalTabStripTopContainerElementId),
      MoveMouseTo(kVerticalTabStripTopContainerElementId),
      ClickMouse(ui_controls::RIGHT),
      WaitForShow(SystemMenuModelBuilder::kToggleVerticalTabsCollapseElementId),
      SelectMenuItem(
          SystemMenuModelBuilder::kToggleVerticalTabsCollapseElementId),
      WaitForEvent(kTabStripRegionElementId,
                   kVerticalTabStripCollapsedCustomEventId));

  EXPECT_TRUE(SystemMenuContainsStringId(IDS_EXPAND_VERTICAL_TABS));
}

class VerticalTabStripMenuInteractiveUiTest
    : public InteractiveFeaturePromoTest {
 public:
  VerticalTabStripMenuInteractiveUiTest()
      : InteractiveFeaturePromoTest(
            UseDefaultTrackerAllowingPromos({tabs::kVerticalTabsNewBadge})) {}
  ~VerticalTabStripMenuInteractiveUiTest() override = default;
};

IN_PROC_BROWSER_TEST_F(VerticalTabStripMenuInteractiveUiTest,
                       ShowBadgeInContextMenuToggle) {
  BrowserWidget* const browser_widget =
      BrowserView::GetBrowserViewForBrowser(browser())->browser_widget();
  ui::MenuModel* menu = browser_widget->GetSystemMenuModel();
  size_t command_index = 0u;
  ui::MenuModel::GetModelAndIndexForCommandId(IDC_TOGGLE_VERTICAL_TABS, &menu,
                                              &command_index);
  tabs::VerticalTabStripStateController* const vertical_tabs_controller =
      tabs::VerticalTabStripStateController::From(browser());
  ASSERT_FALSE(vertical_tabs_controller->ShouldDisplayVerticalTabs());

  // The badge should show while using the horizontal tab strip.
  std::optional<ui::NewBadgeType> badge_type =
      menu->GetNewBadgeTypeAt(command_index);
  ASSERT_TRUE(badge_type.has_value());
  EXPECT_EQ(badge_type.value(), ui::NewBadgeType::kNew);

  // While using the vertical tab strip, the badge should be hidden.
  vertical_tabs_controller->SetVerticalTabsEnabled(true);
  menu = browser_widget->GetSystemMenuModel();
  std::optional<ui::NewBadgeType> badge_type_in_vertical_tabs =
      menu->GetNewBadgeTypeAt(command_index);
  EXPECT_FALSE(badge_type_in_vertical_tabs.has_value());

  // Switching back to the horizontal tab strip should show the badge
  // again.
  vertical_tabs_controller->SetVerticalTabsEnabled(false);
  menu = browser_widget->GetSystemMenuModel();
  std::optional<ui::NewBadgeType> badge_type_in_horizontal_tabs =
      menu->GetNewBadgeTypeAt(command_index);
  ASSERT_TRUE(badge_type_in_horizontal_tabs.has_value());
  EXPECT_EQ(badge_type_in_horizontal_tabs.value(), ui::NewBadgeType::kNew);
}

IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       ImmersiveFullscreenSwitchShowToast) {
  // Enter immersive fullscreen
  ui_test_utils::ToggleFullscreenModeAndWait(browser());
  ASSERT_TRUE(browser()->GetWindow()->IsFullscreen());
  fake_controller_->SetEnabled(true);

  // Get ToastController
  ToastController* const toast_controller =
      browser()->GetFeatures().toast_controller();
  ASSERT_NE(toast_controller, nullptr);
  EXPECT_FALSE(toast_controller->IsShowingToast());

  // Try to enable vertical tabs
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(true);

  // Stop the timer so it doesn't auto-dismiss during test execution.
  toast_controller->GetToastCloseTimerForTesting()->Stop();

  // Verify that vertical tabs are NOT enabled because we are in immersive
  // fullscreen (state is locked)
  EXPECT_FALSE(tabs::VerticalTabStripStateController::From(browser())
                   ->ShouldDisplayVerticalTabs());

  // Verify that toast is showing and has the correct ID
  EXPECT_TRUE(toast_controller->IsShowingToast());
  EXPECT_EQ(toast_controller->GetCurrentToastId(),
            ToastId::kTabStripSwitchDelayedVertical);

  // Click the action button on the toast to exit fullscreen.
  ui_test_utils::FullscreenWaiter waiter(
      browser(), ui_test_utils::FullscreenWaiter::kNoFullscreen);
  RunTestSequence(WaitForShow(toasts::ToastView::kToastActionButton),
                  PressButton(toasts::ToastView::kToastActionButton),
                  WaitForHide(toasts::ToastView::kToastViewId),
                  Do([&waiter]() { waiter.Wait(); }));

  // Verify we exited fullscreen and vertical tabs are now enabled!
  fake_controller_->SetEnabled(false);
  EXPECT_FALSE(browser()->GetWindow()->IsFullscreen());
  EXPECT_TRUE(tabs::VerticalTabStripStateController::From(browser())
                  ->ShouldDisplayVerticalTabs());
}

IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       ImmersiveFullscreenSwitchShowHorizontalToast) {
  // Enable vertical tabs first
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(true);
  ASSERT_TRUE(tabs::VerticalTabStripStateController::From(browser())
                  ->ShouldDisplayVerticalTabs());

  // Enter immersive fullscreen
  ui_test_utils::ToggleFullscreenModeAndWait(browser());
  ASSERT_TRUE(browser()->GetWindow()->IsFullscreen());
  fake_controller_->SetEnabled(true);

  // Get ToastController
  ToastController* const toast_controller =
      browser()->GetFeatures().toast_controller();
  ASSERT_NE(toast_controller, nullptr);
  EXPECT_FALSE(toast_controller->IsShowingToast());

  // Try to disable vertical tabs
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(false);

  // Stop the timer so it doesn't auto-dismiss during test execution.
  toast_controller->GetToastCloseTimerForTesting()->Stop();

  // Verify that vertical tabs are STILL enabled because state is locked
  EXPECT_TRUE(tabs::VerticalTabStripStateController::From(browser())
                  ->ShouldDisplayVerticalTabs());

  // Verify that horizontal toast is showing
  EXPECT_TRUE(toast_controller->IsShowingToast());
  EXPECT_EQ(toast_controller->GetCurrentToastId(),
            ToastId::kTabStripSwitchDelayedHorizontal);

  // Click action button to exit fullscreen
  ui_test_utils::FullscreenWaiter waiter(
      browser(), ui_test_utils::FullscreenWaiter::kNoFullscreen);
  RunTestSequence(WaitForShow(toasts::ToastView::kToastActionButton),
                  PressButton(toasts::ToastView::kToastActionButton),
                  WaitForHide(toasts::ToastView::kToastViewId),
                  Do([&waiter]() { waiter.Wait(); }));

  // Verify we exited fullscreen and vertical tabs are now disabled!
  fake_controller_->SetEnabled(false);
  EXPECT_FALSE(browser()->GetWindow()->IsFullscreen());
  EXPECT_FALSE(tabs::VerticalTabStripStateController::From(browser())
                   ->ShouldDisplayVerticalTabs());
}

IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       ImmersiveFullscreenSwitchShowHorizontalToastRepeatedly) {
  // Enable vertical tabs first
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(true);
  ASSERT_TRUE(tabs::VerticalTabStripStateController::From(browser())
                  ->ShouldDisplayVerticalTabs());

  // Enter immersive fullscreen
  ui_test_utils::ToggleFullscreenModeAndWait(browser());
  ASSERT_TRUE(browser()->GetWindow()->IsFullscreen());
  fake_controller_->SetEnabled(true);

  // Try to disable vertical tabs
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(false);

  // Stop the timer so it doesn't auto-dismiss during test execution.
  ToastController* const toast_controller =
      browser()->GetFeatures().toast_controller();
  toast_controller->GetToastCloseTimerForTesting()->Stop();

  // Verify that vertical tabs are STILL enabled because state is locked
  EXPECT_TRUE(tabs::VerticalTabStripStateController::From(browser())
                  ->ShouldDisplayVerticalTabs());

  // Verify that horizontal toast is showing
  EXPECT_TRUE(toast_controller->IsShowingToast());
  EXPECT_EQ(toast_controller->GetCurrentToastId(),
            ToastId::kTabStripSwitchDelayedHorizontal);

  // Dismiss toast and wait for it to hide
  views::test::WidgetDestroyedWaiter destroyed_waiter(
      toast_controller->GetToastWidgetForTesting());
  RunTestSequence(WaitForShow(toasts::ToastView::kToastCloseButton),
                  PressButton(toasts::ToastView::kToastCloseButton),
                  WaitForHide(toasts::ToastView::kToastViewId),
                  Do([&destroyed_waiter]() { destroyed_waiter.Wait(); }));
  EXPECT_FALSE(toast_controller->IsShowingToast());

  // Try to disable vertical tabs again
  tabs::VerticalTabStripStateController::From(browser())
      ->SetVerticalTabsEnabled(false);

  // Stop the timer so it doesn't auto-dismiss during test execution
  toast_controller->GetToastCloseTimerForTesting()->Stop();

  // Verify that vertical tabs are STILL enabled
  EXPECT_TRUE(tabs::VerticalTabStripStateController::From(browser())
                  ->ShouldDisplayVerticalTabs());

  // Verify that horizontal toast is showing again
  EXPECT_TRUE(toast_controller->IsShowingToast());
  EXPECT_EQ(toast_controller->GetCurrentToastId(),
            ToastId::kTabStripSwitchDelayedHorizontal);

  // Click action button to exit fullscreen
  ui_test_utils::FullscreenWaiter waiter(
      browser(), ui_test_utils::FullscreenWaiter::kNoFullscreen);
  RunTestSequence(WaitForShow(toasts::ToastView::kToastActionButton),
                  PressButton(toasts::ToastView::kToastActionButton),
                  WaitForHide(toasts::ToastView::kToastViewId),
                  Do([&waiter]() { waiter.Wait(); }));

  // Verify we exited fullscreen and vertical tabs are now disabled
  fake_controller_->SetEnabled(false);
  EXPECT_FALSE(browser()->GetWindow()->IsFullscreen());
  EXPECT_FALSE(tabs::VerticalTabStripStateController::From(browser())
                   ->ShouldDisplayVerticalTabs());
}

IN_PROC_BROWSER_TEST_F(VerticalTabStripInteractiveUiTest,
                       KeyboardShortcutTogglesCollapse) {
  base::UserActionTester user_action_tester;
  tabs::VerticalTabStripStateController* const controller =
      tabs::VerticalTabStripStateController::From(browser());
  controller->SetVerticalTabsEnabled(true);

  gfx::ScopedAnimationDurationScaleMode disable_animations(
      gfx::ScopedAnimationDurationScaleMode::ZERO_DURATION);

  RunScheduledLayouts();

  RunTestSequence(
      // Wait for the vertical tab strip UI to be fully shown and active.
      WaitForShow(kVerticalTabStripCollapseButtonElementId),

      // Ensure vertical tabs are enabled and expanded initially.
      CheckResult([controller]() { return controller->IsCollapsed(); }, false),

      // Send the accelerator.
      SendKeyPress(kBrowserViewElementId, ui::VKEY_L,
                   ui::EF_SHIFT_DOWN | ui::EF_PLATFORM_ACCELERATOR),

      // Wait for the collapsed event.
      WaitForEvent(kTabStripRegionElementId,
                   kVerticalTabStripCollapsedCustomEventId),

      // Verify it is collapsed.
      CheckResult([controller]() { return controller->IsCollapsed(); }, true),

      // Verify the metric was logged.
      Do([&user_action_tester]() {
        EXPECT_EQ(1,
                  user_action_tester.GetActionCount(
                      "VerticalTabs_TabStrip_KeyboardShortcutToggleCollapsed"));
      }),

      // Send the accelerator again.
      SendKeyPress(kBrowserViewElementId, ui::VKEY_L,
                   ui::EF_SHIFT_DOWN | ui::EF_PLATFORM_ACCELERATOR),

      // Wait for the expansion to complete.
      Do([controller]() {
        EXPECT_TRUE(base::test::RunUntil(
            [controller]() { return !controller->IsCollapsed(); }));
      }),

      // Verify it is expanded again.
      CheckResult([controller]() { return controller->IsCollapsed(); }, false),

      // Verify the metric was logged.
      Do([&user_action_tester]() {
        EXPECT_EQ(
            1, user_action_tester.GetActionCount(
                   "VerticalTabs_TabStrip_KeyboardShortcutToggleUncollapsed"));
      }));
}

}  // namespace base::test
