1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/files/file_util.h"
6 #include "base/path_service.h"
7 #include "base/test/scoped_feature_list.h"
8 #include "build/build_config.h"
9 #include "cc/test/pixel_comparator.h"
10 #include "content/public/browser/render_widget_host_view.h"
11 #include "content/public/common/content_paths.h"
12 #include "content/public/test/browser_test.h"
13 #include "content/public/test/browser_test_utils.h"
14 #include "content/public/test/content_browser_test.h"
15 #include "content/public/test/content_browser_test_utils.h"
16 #include "content/public/test/test_utils.h"
17 #include "content/shell/browser/shell.h"
18 #include "ui/base/ui_base_features.h"
19 
20 #if defined(OS_ANDROID)
21 #include "base/android/build_info.h"
22 #endif
23 
24 // TODO(crbug.com/958242): Move the baselines to skia gold for easier
25 //   rebaselining when all platforms are supported.
26 
27 // To rebaseline this test on all platforms:
28 // 1. Run a CQ+1 dry run.
29 // 2. Click the failing bots for android, windows, mac, and linux.
30 // 3. Find the failing interactive_ui_browsertests step.
31 // 4. Click the "Deterministic failure" link for the failing test case.
32 // 5. Copy the "Actual pixels" data url and paste into browser.
33 // 6. Save the image into your chromium checkout in content/test/data/forms/.
34 
35 namespace content {
36 
37 class FormControlsBrowserTest : public ContentBrowserTest {
38  public:
FormControlsBrowserTest()39   FormControlsBrowserTest() {
40     feature_list_.InitWithFeatures({features::kFormControlsRefresh}, {});
41   }
42 
SetUp()43   void SetUp() override {
44     EnablePixelOutput(/*force_device_scale_factor=*/1.f);
45     ContentBrowserTest::SetUp();
46   }
47 
SetUpCommandLine(base::CommandLine * command_line)48   void SetUpCommandLine(base::CommandLine* command_line) override {
49     ContentBrowserTest::SetUpCommandLine(command_line);
50 
51     // The --disable-lcd-text flag helps text render more similarly on
52     // different bots and platform.
53     command_line->AppendSwitch(switches::kDisableLCDText);
54   }
55 
RunTest(const std::string & screenshot_filename,const std::string & body_html,int screenshot_width,int screenshot_height)56   void RunTest(const std::string& screenshot_filename,
57                const std::string& body_html,
58                int screenshot_width,
59                int screenshot_height) {
60     base::ScopedAllowBlockingForTesting allow_blocking;
61 
62     ASSERT_TRUE(features::IsFormControlsRefreshEnabled());
63 
64     std::string platform_suffix;
65 #if defined(OS_MAC)
66     platform_suffix = "_mac";
67 #elif defined(OS_WIN)
68     platform_suffix = "_win";
69 #elif defined(OS_CHROMEOS)
70     platform_suffix = "_chromeos";
71 #elif defined(OS_ANDROID)
72     int sdk_int = base::android::BuildInfo::GetInstance()->sdk_int();
73     if (sdk_int == base::android::SDK_VERSION_KITKAT) {
74       platform_suffix = "_android_kitkat";
75     } else {
76       platform_suffix = "_android";
77     }
78 #endif
79 
80     base::FilePath dir_test_data;
81     ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &dir_test_data));
82     base::FilePath golden_filepath =
83         dir_test_data.AppendASCII("forms").AppendASCII(screenshot_filename +
84                                                        ".png");
85 
86     base::FilePath golden_filepath_platform =
87         golden_filepath.InsertBeforeExtensionASCII(platform_suffix);
88     if (base::PathExists(golden_filepath_platform)) {
89       golden_filepath = golden_filepath_platform;
90     }
91 
92     ASSERT_TRUE(NavigateToURL(
93         shell()->web_contents(),
94         GURL("data:text/html,<!DOCTYPE html><body>" + body_html + "</body>")));
95 
96 #if defined(OS_MAC)
97     // This fuzzy pixel comparator handles several mac behaviors:
98     // - Different font rendering after 10.14
99     // - 10.12 subpixel rendering differences: crbug.com/1037971
100     // - Slight differences in radio and checkbox rendering in 10.15
101     cc::FuzzyPixelComparator comparator(
102         /* discard_alpha */ true,
103         /* error_pixels_percentage_limit */ 9.f,
104         /* small_error_pixels_percentage_limit */ 0.f,
105         /* avg_abs_error_limit */ 20.f,
106         /* max_abs_error_limit */ 79.f,
107         /* small_error_threshold */ 0);
108 #elif defined(OS_ANDROID)
109     // Different versions of android may have slight differences in rendering.
110     // Some versions have more significant differences than others, which are
111     // tracked separately in separate baseline image files. The less significant
112     // differences are accommodated for with this fuzzy pixel comparator.
113     cc::FuzzyPixelComparator comparator(
114         /* discard_alpha */ true,
115         /* error_pixels_percentage_limit */ 6.f,
116         /* small_error_pixels_percentage_limit */ 0.f,
117         /* avg_abs_error_limit */ 2.f,
118         /* max_abs_error_limit */ 3.f,
119         /* small_error_threshold */ 0);
120 #else
121     cc::ExactPixelComparator comparator(/* disard_alpha */ true);
122 #endif
123     EXPECT_TRUE(CompareWebContentsOutputToReference(
124         shell()->web_contents(), golden_filepath,
125         gfx::Size(screenshot_width, screenshot_height), comparator));
126   }
127 
128  private:
129   base::test::ScopedFeatureList feature_list_;
130 };
131 
IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest,Checkbox)132 IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest, Checkbox) {
133   RunTest("form_controls_browsertest_checkbox",
134           "<input type=checkbox>"
135           "<input type=checkbox checked>"
136           "<input type=checkbox disabled>"
137           "<input type=checkbox checked disabled>"
138           "<input type=checkbox id=\"indeterminate\">"
139           "<script>"
140           "  document.getElementById('indeterminate').indeterminate = true"
141           "</script>",
142           /* screenshot_width */ 130,
143           /* screenshot_height */ 40);
144 }
145 
IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest,Radio)146 IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest, Radio) {
147   RunTest("form_controls_browsertest_radio",
148           "<input type=radio>"
149           "<input type=radio checked>"
150           "<input type=radio disabled>"
151           "<input type=radio checked disabled>"
152           "<input type=radio id=\"indeterminate\">"
153           "<script>"
154           "  document.getElementById('indeterminate').indeterminate = true"
155           "</script>",
156           /* screenshot_width */ 140,
157           /* screenshot_height */ 40);
158 }
159 
160 // TODO(jarhar): Add tests for other elements from
161 //   https://concrete-hardboard.glitch.me
162 
163 }  // namespace content
164