1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/files/file_util.h"
6 #include "base/path_service.h"
7 #include "build/build_config.h"
8 #include "build/chromeos_buildflags.h"
9 #include "cc/test/pixel_comparator.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/common/chrome_paths.h"
12 #include "chrome/test/base/in_process_browser_test.h"
13 #include "chrome/test/base/interactive_test_utils.h"
14 #include "chrome/test/base/ui_test_utils.h"
15 #include "content/public/browser/render_widget_host_view.h"
16 #include "content/public/common/content_switches.h"
17 #include "content/public/test/browser_test.h"
18 #include "content/public/test/browser_test_utils.h"
19 #include "ui/base/ui_base_features.h"
20 #include "ui/base/ui_base_switches.h"
22 // TODO(crbug.com/958242): Move the baselines to skia gold for easier
23 // rebaselining when all platforms are supported
25 // To rebaseline this test on all platforms:
26 // 1. Run a CQ+1 dry run.
27 // 2. Click the failing bots for android, windows, mac, and linux.
28 // 3. Find the failing interactive_ui_tests step.
29 // 4. Click the "Deterministic failure" link for the failing test case.
30 // 5. Copy the "Actual pixels" data url and paste into browser.
31 // 6. Save the image into your chromium checkout in
32 // chrome/test/data/focus_rings.
35 // Mac has subtle rendering differences between different versions of MacOS, so
36 // we account for them with these fuzzy pixel comparators. These two comparators
37 // are used in different tests in order to keep the matching somewhat strict.
38 const auto mac_strict_comparator = cc::FuzzyPixelComparator()
40 .SetErrorPixelsPercentageLimit(3.f)
41 .SetAvgAbsErrorLimit(20.f)
42 .SetAbsErrorLimit(49);
43 const auto mac_loose_comparator = cc::FuzzyPixelComparator()
45 .SetErrorPixelsPercentageLimit(8.7f)
46 .SetAvgAbsErrorLimit(20.f)
47 .SetAbsErrorLimit(43);
50 // The ChromeRefresh2023 trybot has very slightly different rendering output
51 // than normal linux bots. It is currently unclear if this is due to the flag or
52 // some configuration on the bot. In addition, this bot does not get run on CQ+1
53 // so having a separate golden file to rebaseline is not good enough. This fuzzy
54 // comparator accounts for this and still make sure that the output is sane.
55 // TODO(http://crbug.com/1443584): Remove this fuzzy matcher when
56 // ChromeRefresh2023 is enabled by default.
57 const auto cr23_comparator = cc::FuzzyPixelComparator()
59 .SetErrorPixelsPercentageLimit(3.f)
60 .SetAvgAbsErrorLimit(20.f)
61 .SetAbsErrorLimit(49);
63 const auto exact_comparator = cc::AlphaDiscardingExactPixelComparator();
65 class FocusRingBrowserTest : public InProcessBrowserTest {
67 void SetUp() override {
68 EnablePixelOutput(/*force_device_scale_factor=*/1.f);
69 InProcessBrowserTest::SetUp();
72 void SetUpCommandLine(base::CommandLine* command_line) override {
73 // The --disable-lcd-text flag helps text render more similarly on
74 // different bots and platform.
75 command_line->AppendSwitch(switches::kDisableLCDText);
77 // This is required to allow dark mode to be used on some platforms.
78 command_line->AppendSwitch(switches::kForceDarkMode);
81 void RunTest(const std::string& screenshot_filename,
82 const std::string& body_html,
84 int screenshot_height,
85 const cc::PixelComparator& comparator) {
86 base::ScopedAllowBlockingForTesting allow_blocking;
88 base::FilePath dir_test_data;
89 ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &dir_test_data));
91 std::string platform_suffix;
93 platform_suffix = "_mac";
94 #elif BUILDFLAG(IS_WIN)
95 platform_suffix = "_win";
96 #elif BUILDFLAG(IS_LINUX)
97 platform_suffix = "_linux";
98 #elif BUILDFLAG(IS_CHROMEOS_ASH)
99 platform_suffix = "_chromeos";
102 base::FilePath golden_filepath =
103 dir_test_data.AppendASCII("focus_rings")
104 .AppendASCII(screenshot_filename + ".png");
106 base::FilePath golden_filepath_platform =
107 golden_filepath.InsertBeforeExtensionASCII(platform_suffix);
108 if (base::PathExists(golden_filepath_platform)) {
109 golden_filepath = golden_filepath_platform;
112 content::WebContents* web_contents =
113 browser()->tab_strip_model()->GetActiveWebContents();
114 ASSERT_TRUE(content::NavigateToURL(
115 web_contents, GURL("data:text/html,<!DOCTYPE html>" + body_html)));
116 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
118 EXPECT_TRUE(CompareWebContentsOutputToReference(
119 web_contents, golden_filepath,
120 gfx::Size(screenshot_width, screenshot_height), comparator));
124 // TODO(crbug.com/1222757): Flaky on Mac.
125 #if BUILDFLAG(IS_MAC)
126 #define MAYBE_Checkbox DISABLED_Checkbox
128 #define MAYBE_Checkbox Checkbox
130 IN_PROC_BROWSER_TEST_F(FocusRingBrowserTest, MAYBE_Checkbox) {
131 #if BUILDFLAG(IS_MAC)
132 auto* comparator = &mac_strict_comparator;
134 const cc::PixelComparator* comparator = &exact_comparator;
135 if (features::IsChromeRefresh2023()) {
136 comparator = &cr23_comparator;
139 RunTest("focus_ring_browsertest_checkbox",
140 "<input type=checkbox autofocus>"
141 "<input type=checkbox>",
142 /* screenshot_width */ 60,
143 /* screenshot_height */ 40, *comparator);
146 // TODO(crbug.com/1222757): Flaky on Mac.
147 #if BUILDFLAG(IS_MAC)
148 #define MAYBE_Radio DISABLED_Radio
150 #define MAYBE_Radio Radio
152 IN_PROC_BROWSER_TEST_F(FocusRingBrowserTest, MAYBE_Radio) {
153 #if BUILDFLAG(IS_MAC)
154 auto* comparator = &mac_loose_comparator;
156 const cc::PixelComparator* comparator = &exact_comparator;
157 if (features::IsChromeRefresh2023()) {
158 comparator = &cr23_comparator;
161 RunTest("focus_ring_browsertest_radio",
162 "<input type=radio autofocus>"
163 "<input type=radio>",
164 /* screenshot_width */ 60,
165 /* screenshot_height */ 40, *comparator);
168 // TODO(crbug.com/1222757): Flaky on Mac.
169 #if BUILDFLAG(IS_MAC)
170 #define MAYBE_Button DISABLED_Button
172 #define MAYBE_Button Button
174 IN_PROC_BROWSER_TEST_F(FocusRingBrowserTest, MAYBE_Button) {
175 #if BUILDFLAG(IS_MAC)
176 auto* comparator = &mac_strict_comparator;
178 const cc::PixelComparator* comparator = &exact_comparator;
179 if (features::IsChromeRefresh2023()) {
180 comparator = &cr23_comparator;
183 RunTest("focus_ring_browsertest_button",
184 "<button autofocus style=\"width:40px;height:20px;\"></button>"
187 "<button style=\"width:40px;height:20px;\"></button>",
188 /* screenshot_width */ 80,
189 /* screenshot_height */ 80, *comparator);
192 // TODO(crbug.com/1222757): Flaky on Mac.
193 #if BUILDFLAG(IS_MAC)
194 #define MAYBE_Anchor DISABLED_Anchor
196 #define MAYBE_Anchor Anchor
198 IN_PROC_BROWSER_TEST_F(FocusRingBrowserTest, MAYBE_Anchor) {
199 #if BUILDFLAG(IS_MAC)
200 auto* comparator = &mac_strict_comparator;
202 const cc::PixelComparator* comparator = &exact_comparator;
203 if (features::IsChromeRefresh2023()) {
204 comparator = &cr23_comparator;
207 RunTest("focus_ring_browsertest_anchor",
208 "<div style='text-align: center; width: 80px;'>"
209 " <a href='foo' autofocus>---- ---<br>---</a>"
212 "<div style='text-align: center; width: 80px;'>"
213 " <a href='foo'>---- ---<br>---</a>"
215 /* screenshot_width */ 90,
216 /* screenshot_height */ 130, *comparator);
219 // TODO(crbug.com/1222757): Flaky on Mac.
220 #if BUILDFLAG(IS_MAC)
221 #define MAYBE_DarkModeButton DISABLED_DarkModeButton
223 #define MAYBE_DarkModeButton DarkModeButton
225 IN_PROC_BROWSER_TEST_F(FocusRingBrowserTest, MAYBE_DarkModeButton) {
226 #if BUILDFLAG(IS_MAC)
227 auto* comparator = &mac_strict_comparator;
229 const cc::PixelComparator* comparator = &exact_comparator;
230 if (features::IsChromeRefresh2023()) {
231 comparator = &cr23_comparator;
234 RunTest("focus_ring_browsertest_dark_mode_button",
235 "<meta name=\"color-scheme\" content=\"dark\">"
236 "<button autofocus style=\"width:40px;height:20px;\"></button>"
239 "<button style=\"width:40px;height:20px;\"></button>",
240 /* screenshot_width */ 80,
241 /* screenshot_height */ 80, *comparator);