chromium/chrome/browser/ui/views/tabs/tab_strip_unittest.cc

// Copyright 2012 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/views/tabs/tab_strip.h"

#include <memory>
#include <string>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/timer/timer.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/tabs/features.h"
#include "chrome/browser/ui/tabs/tab_renderer_data.h"
#include "chrome/browser/ui/tabs/tab_style.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/frame/browser_root_view.h"
#include "chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h"
#include "chrome/browser/ui/views/tabs/tab.h"
#include "chrome/browser/ui/views/tabs/tab_group_header.h"
#include "chrome/browser/ui/views/tabs/tab_group_highlight.h"
#include "chrome/browser/ui/views/tabs/tab_group_underline.h"
#include "chrome/browser/ui/views/tabs/tab_group_views.h"
#include "chrome/browser/ui/views/tabs/tab_icon.h"
#include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
#include "chrome/browser/ui/views/tabs/tab_strip_observer.h"
#include "chrome/browser/ui/views/tabs/tab_style_views.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/views/chrome_views_test_base.h"
#include "components/tab_groups/tab_group_id.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/pointer/touch_ui_controller.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/base_event_utils.h"
#include "ui/gfx/animation/animation_test_api.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/test/ax_event_counter.h"
#include "ui/views/test/views_test_utils.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/view_observer.h"
#include "ui/views/view_targeter.h"
#include "ui/views/view_utils.h"
#include "ui/views/widget/widget.h"

namespace {

struct TabStripUnittestParams {};

constexpr TabStripUnittestParams kTabStripUnittestParams[] =;
}  // namespace

class TestTabStripObserver : public TabStripObserver {};

// TabStripTestBase contains no test cases.
class TabStripTestBase : public ChromeViewsTestBase {};

// TabStripTest contains tests that will run with all permutations of touch ui
// and scrolling enabled and disabled.
class TabStripTest
    : public TabStripTestBase,
      public testing::WithParamInterface<TabStripUnittestParams> {};

TEST_P(TabStripTest, GetModelCount) {}

TEST_P(TabStripTest, AccessibilityEvents) {}

TEST_P(TabStripTest, IsValidModelIndex) {}

TEST_P(TabStripTest, tab_count) {}

TEST_P(TabStripTest, AddTabAt) {}

TEST_P(TabStripTest, MoveTab) {}

// Verifies child views are deleted after an animation completes.
TEST_P(TabStripTest, RemoveTab) {}

// Tests that the tab close buttons of non-active tabs are hidden when
// the tab sizes are shrunk into small sizes.
TEST_P(TabStripTest, TabCloseButtonVisibility) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_P(TabStripTest, CloseButtonHiddenWhenLockedForOnTask) {
  controller_->SetLockedForOnTask(true);

  controller_->AddTab(0, TabActive::kInactive);
  controller_->AddTab(1, TabActive::kActive);
  controller_->AddTab(2, TabActive::kInactive);
  ASSERT_EQ(3, tab_strip_->GetTabCount());

  Tab* const tab0 = tab_strip_->tab_at(0);
  ASSERT_FALSE(tab0->IsActive());
  EXPECT_FALSE(tab0->showing_close_button_);

  Tab* const tab1 = tab_strip_->tab_at(1);
  ASSERT_TRUE(tab1->IsActive());
  EXPECT_FALSE(tab1->showing_close_button_);

  Tab* tab2 = tab_strip_->tab_at(2);
  ASSERT_FALSE(tab2->IsActive());
  EXPECT_FALSE(tab2->showing_close_button_);

  // Switch tabs and confirm close button remains hidden for all opened tabs.
  tab_strip_->SelectTab(tab2, dummy_event_);
  ASSERT_TRUE(tab2->IsActive());
  EXPECT_FALSE(tab0->showing_close_button_);
  EXPECT_FALSE(tab1->showing_close_button_);
  EXPECT_FALSE(tab2->showing_close_button_);

  // Closing a tab should not alter tab close button visibility either.
  tab_strip_->CloseTab(tab2, CLOSE_TAB_FROM_MOUSE);
  tab2 = nullptr;
  EXPECT_FALSE(tab0->showing_close_button_);
  EXPECT_FALSE(tab1->showing_close_button_);
}
#endif

// The cached widths are private, but if they give incorrect results it can
// cause subtle errors in other tests. Therefore it's prudent to test them.
TEST_P(TabStripTest, CachedWidthsReportCorrectSize) {}

// The active tab should always be at least as wide as its minimum width.
// http://crbug.com/587688
TEST_P(TabStripTest, ActiveTabWidthWhenTabsAreTiny) {}

// Inactive tabs shouldn't shrink during mouse-based tab closure.
// http://crbug.com/850190
TEST_P(TabStripTest, InactiveTabWidthWhenTabsAreTiny) {}

// When dragged tabs are moving back to their position, changes to ideal bounds
// should be respected. http://crbug.com/848016
TEST_P(TabStripTest, ResetBoundsForDraggedTabs) {}

// The "blocked" attention indicator should only show for background tabs.
TEST_P(TabStripTest, TabNeedsAttentionBlocked) {}

// The generic "wants attention" version should always show.
TEST_P(TabStripTest, TabNeedsAttentionGeneric) {}

// Closing tab should be targeted during event dispatching.
TEST_P(TabStripTest, EventsOnClosingTab) {}

// TODO (crbug.com/1520595): Disabled for now due to test failing when CR2023
// enabled.
TEST_P(TabStripTest, DISABLED_ChangingLayoutTypeResizesTabs) {}

// Regression test for a crash when closing a tab under certain conditions. If
// the first tab in a group was animating closed, attempting to close the next
// tab could result in a crash. This was due to TabStripLayoutHelper mistakenly
// mapping the next tab's model index to the closing tab's slot. See
// https://crbug.com/1138748 for a related crash.
TEST_P(TabStripTest, CloseTabInGroupWhilePreviousTabAnimatingClosed) {}

TEST_P(TabStripTest, HeaderOnCollapseChangeAccessibilityProperties) {}

namespace {

struct SizeChangeObserver : public views::ViewObserver {};

}  // namespace

// When dragged tabs' bounds are modified through TabDragContext, both tab strip
// and its parent view must get re-laid out http://crbug.com/1151092.
TEST_P(TabStripTest, RelayoutAfterDraggedTabBoundsUpdate) {}

TEST_P(TabStripTest, PreferredWidthDuringDrag) {}

TEST_P(TabStripTest, TabIconActiveState) {}

// TabStripTestWithScrollingDisabled contains tests that will run with scrolling
// disabled.
// TODO(http://crbug.com/951078) Remove these tests as well as tests in
// TabStripTest with scrolling disabled once tab scrolling is fully launched.
class TabStripTestWithScrollingDisabled
    : public TabStripTestBase,
      public testing::WithParamInterface<bool> {};

TEST_P(TabStripTestWithScrollingDisabled, VisibilityInOverflow) {}

TEST_P(TabStripTestWithScrollingDisabled, GroupedTabSlotOverflowVisibility) {}

INSTANTIATE_TEST_SUITE_P();

INSTANTIATE_TEST_SUITE_P();