Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: ui/views/controls/label_unittest.cc

Issue 2422993002: views::Label: Implement context menu, keyboard shortcuts for copy/select all. (Closed)
Patch Set: Tests. Stored selection range invalidation Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« ui/views/controls/label.cc ('K') | « ui/views/controls/label.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/label.h" 5 #include "ui/views/controls/label.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
11 #include "base/memory/ptr_util.h"
11 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
12 #include "build/build_config.h" 13 #include "build/build_config.h"
13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/accessibility/ax_node_data.h" 15 #include "ui/accessibility/ax_node_data.h"
15 #include "ui/base/clipboard/clipboard.h" 16 #include "ui/base/clipboard/clipboard.h"
16 #include "ui/base/l10n/l10n_util.h" 17 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/compositor/canvas_painter.h" 18 #include "ui/compositor/canvas_painter.h"
18 #include "ui/events/base_event_utils.h" 19 #include "ui/events/base_event_utils.h"
20 #include "ui/events/test/event_generator.h"
19 #include "ui/gfx/canvas.h" 21 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/render_text.h" 22 #include "ui/gfx/render_text.h"
21 #include "ui/gfx/switches.h" 23 #include "ui/gfx/switches.h"
24 #include "ui/strings/grit/ui_strings.h"
22 #include "ui/views/border.h" 25 #include "ui/views/border.h"
23 #include "ui/views/test/focus_manager_test.h" 26 #include "ui/views/test/focus_manager_test.h"
24 #include "ui/views/test/views_test_base.h" 27 #include "ui/views/test/views_test_base.h"
25 #include "ui/views/widget/widget.h" 28 #include "ui/views/widget/widget.h"
26 29
27 using base::ASCIIToUTF16; 30 using base::ASCIIToUTF16;
28 31
29 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16) 32 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
30 33
31 namespace views { 34 namespace views {
32 35
36 namespace {
37
38 #if defined(OS_MACOSX)
39 const int kControlCommandModifier = ui::EF_COMMAND_DOWN;
40 #else
41 const int kControlCommandModifier = ui::EF_CONTROL_DOWN;
42 #endif
43
44 // All text sizing measurements (width and height) should be greater than this.
45 const int kMinTextDimension = 4;
46
47 class TestLabel : public Label {
48 public:
49 TestLabel() : Label(ASCIIToUTF16("TestLabel")) { SizeToPreferredSize(); }
50
51 int schedule_paint_count() const { return schedule_paint_count_; }
52
53 void SimulatePaint() {
54 gfx::Canvas canvas(bounds().size(), 1.0, false /* is_opaque */);
55 Paint(ui::CanvasPainter(&canvas, 1.f).context());
56 }
57
58 // View:
59 void SchedulePaintInRect(const gfx::Rect& r) override {
60 ++schedule_paint_count_;
61 Label::SchedulePaintInRect(r);
62 }
63
64 private:
65 int schedule_paint_count_ = 0;
66
67 DISALLOW_COPY_AND_ASSIGN(TestLabel);
68 };
69
70 // A test utility function to set the application default text direction.
71 void SetRTL(bool rtl) {
72 // Override the current locale/direction.
73 base::i18n::SetICUDefaultLocale(rtl ? "he" : "en");
74 EXPECT_EQ(rtl, base::i18n::IsRTL());
75 }
76
77 // Returns true if |current| is bigger than |last|. Sets |last| to |current|.
78 bool Increased(int current, int* last) {
79 bool increased = current > *last;
80 *last = current;
81 return increased;
82 }
83
84 base::string16 GetClipboardText(ui::ClipboardType clipboard_type) {
85 base::string16 clipboard_text;
86 ui::Clipboard::GetForCurrentThread()->ReadText(clipboard_type,
87 &clipboard_text);
88 return clipboard_text;
89 }
90
91 } // namespace
92
33 class LabelTest : public ViewsTestBase { 93 class LabelTest : public ViewsTestBase {
34 public: 94 public:
35 LabelTest() {} 95 LabelTest() {}
36 96
37 // ViewsTestBase overrides: 97 // ViewsTestBase overrides:
38 void SetUp() override { 98 void SetUp() override {
39 ViewsTestBase::SetUp(); 99 ViewsTestBase::SetUp();
40 100
41 Widget::InitParams params = 101 Widget::InitParams params =
42 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); 102 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 void SetUp() override { 138 void SetUp() override {
79 #if defined(OS_MACOSX) 139 #if defined(OS_MACOSX)
80 // On Mac, by default RenderTextMac is used for labels which does not 140 // On Mac, by default RenderTextMac is used for labels which does not
81 // support text selection. Instead use RenderTextHarfBuzz for selection 141 // support text selection. Instead use RenderTextHarfBuzz for selection
82 // related tests. TODO(crbug.com/661394): Remove this once Mac also uses 142 // related tests. TODO(crbug.com/661394): Remove this once Mac also uses
83 // RenderTextHarfBuzz for Labels. 143 // RenderTextHarfBuzz for Labels.
84 base::CommandLine::ForCurrentProcess()->AppendSwitch( 144 base::CommandLine::ForCurrentProcess()->AppendSwitch(
85 switches::kEnableHarfBuzzRenderText); 145 switches::kEnableHarfBuzzRenderText);
86 #endif 146 #endif
87 LabelTest::SetUp(); 147 LabelTest::SetUp();
148 event_generator_ =
karandeepb 2016/11/15 10:54:32 Since we are now using EventGenerator anyway, if i
msw 2016/11/15 20:06:45 Acknowledged.
149 base::MakeUnique<ui::test::EventGenerator>(widget()->GetNativeWindow());
88 } 150 }
89 151
90 protected: 152 protected:
91 View* GetFocusedView() { 153 View* GetFocusedView() {
92 return widget()->GetFocusManager()->GetFocusedView(); 154 return widget()->GetFocusManager()->GetFocusedView();
93 } 155 }
94 156
95 void PerformMousePress(const gfx::Point& point, int extra_flags = 0) { 157 void PerformMousePress(const gfx::Point& point, int extra_flags = 0) {
96 ui::MouseEvent pressed_event = ui::MouseEvent( 158 ui::MouseEvent pressed_event = ui::MouseEvent(
97 ui::ET_MOUSE_PRESSED, point, point, ui::EventTimeForNow(), 159 ui::ET_MOUSE_PRESSED, point, point, ui::EventTimeForNow(),
(...skipping 20 matching lines...) Expand all
118 } 180 }
119 181
120 gfx::Point GetCursorPoint(int cursor_pos) { 182 gfx::Point GetCursorPoint(int cursor_pos) {
121 return label() 183 return label()
122 ->GetRenderTextForSelectionController() 184 ->GetRenderTextForSelectionController()
123 ->GetCursorBounds(gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), 185 ->GetCursorBounds(gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD),
124 false) 186 false)
125 .origin(); 187 .origin();
126 } 188 }
127 189
128 base::string16 GetSelectedText() { 190 base::string16 GetSelectedText() { return label()->GetSelectedText(); }
129 const gfx::RenderText* render_text = 191
130 label()->GetRenderTextForSelectionController(); 192 ui::test::EventGenerator* event_generator() {
131 return render_text->GetTextFromRange(render_text->selection()); 193 return event_generator_.get();
132 } 194 };
msw 2016/11/15 20:06:45 nit: no trailing semi
karandeepb 2016/11/16 07:48:29 Done.
133 195
134 private: 196 private:
197 std::unique_ptr<ui::test::EventGenerator> event_generator_;
198
135 DISALLOW_COPY_AND_ASSIGN(LabelSelectionTest); 199 DISALLOW_COPY_AND_ASSIGN(LabelSelectionTest);
136 }; 200 };
137 201
138 namespace {
139
140 // All text sizing measurements (width and height) should be greater than this.
141 const int kMinTextDimension = 4;
142
143 class TestLabel : public Label {
144 public:
145 TestLabel() : Label(ASCIIToUTF16("TestLabel")) { SizeToPreferredSize(); }
146
147 int schedule_paint_count() const { return schedule_paint_count_; }
148
149 void SimulatePaint() {
150 gfx::Canvas canvas(bounds().size(), 1.0, false /* is_opaque */);
151 Paint(ui::CanvasPainter(&canvas, 1.f).context());
152 }
153
154 // View:
155 void SchedulePaintInRect(const gfx::Rect& r) override {
156 ++schedule_paint_count_;
157 Label::SchedulePaintInRect(r);
158 }
159
160 private:
161 int schedule_paint_count_ = 0;
162
163 DISALLOW_COPY_AND_ASSIGN(TestLabel);
164 };
165
166 // A test utility function to set the application default text direction.
167 void SetRTL(bool rtl) {
168 // Override the current locale/direction.
169 base::i18n::SetICUDefaultLocale(rtl ? "he" : "en");
170 EXPECT_EQ(rtl, base::i18n::IsRTL());
171 }
172
173 // Returns true if |current| is bigger than |last|. Sets |last| to |current|.
174 bool Increased(int current, int* last) {
175 bool increased = current > *last;
176 *last = current;
177 return increased;
178 }
179
180 base::string16 GetSelectionClipboardText() {
181 base::string16 selection_clipboard_text;
182 ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_SELECTION,
183 &selection_clipboard_text);
184 return selection_clipboard_text;
185 }
186
187 } // namespace
188
189 // Crashes on Linux only. http://crbug.com/612406 202 // Crashes on Linux only. http://crbug.com/612406
190 #if defined(OS_LINUX) 203 #if defined(OS_LINUX)
191 #define MAYBE_FontPropertySymbol DISABLED_FontPropertySymbol 204 #define MAYBE_FontPropertySymbol DISABLED_FontPropertySymbol
192 #else 205 #else
193 #define MAYBE_FontPropertySymbol FontPropertySymbol 206 #define MAYBE_FontPropertySymbol FontPropertySymbol
194 #endif 207 #endif
195 TEST_F(LabelTest, MAYBE_FontPropertySymbol) { 208 TEST_F(LabelTest, MAYBE_FontPropertySymbol) {
196 std::string font_name("symbol"); 209 std::string font_name("symbol");
197 gfx::Font font(font_name, 26); 210 gfx::Font font(font_name, 26);
198 label()->SetFontList(gfx::FontList(font)); 211 label()->SetFontList(gfx::FontList(font));
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 PerformMousePress(GetCursorPoint(5)); 906 PerformMousePress(GetCursorPoint(5));
894 PerformMouseDragTo(gfx::Point()); 907 PerformMouseDragTo(gfx::Point());
895 EXPECT_STR_EQ("Label", GetSelectedText()); 908 EXPECT_STR_EQ("Label", GetSelectedText());
896 909
897 PerformMouseDragTo(GetCursorPoint(8)); 910 PerformMouseDragTo(GetCursorPoint(8));
898 EXPECT_STR_EQ(" mo", GetSelectedText()); 911 EXPECT_STR_EQ(" mo", GetSelectedText());
899 912
900 PerformMouseDragTo(gfx::Point(200, 0)); 913 PerformMouseDragTo(gfx::Point(200, 0));
901 PerformMouseRelease(gfx::Point(200, 0)); 914 PerformMouseRelease(gfx::Point(200, 0));
902 EXPECT_STR_EQ(" mouse drag", GetSelectedText()); 915 EXPECT_STR_EQ(" mouse drag", GetSelectedText());
916
917 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
918 EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
msw 2016/11/15 20:06:45 Avoid testing the system clipboard in unit tests.
tapted 2016/11/16 02:45:19 Yah - there is http://crbug.com/623442 about this
karandeepb 2016/11/16 07:48:29 Have created https://codereview.chromium.org/24993
903 } 919 }
904 920
905 // Verify the initially selected word on a double click, remains selected on 921 // Verify the initially selected word on a double click, remains selected on
906 // mouse dragging. 922 // mouse dragging.
907 TEST_F(LabelSelectionTest, MouseDragWord) { 923 TEST_F(LabelSelectionTest, MouseDragWord) {
908 label()->SetText(ASCIIToUTF16("Label drag word")); 924 label()->SetText(ASCIIToUTF16("Label drag word"));
909 label()->SizeToPreferredSize(); 925 label()->SizeToPreferredSize();
910 ASSERT_TRUE(label()->SetSelectable(true)); 926 ASSERT_TRUE(label()->SetSelectable(true));
911 927
912 PerformClick(GetCursorPoint(8)); 928 PerformClick(GetCursorPoint(8));
(...skipping 13 matching lines...) Expand all
926 // http://crbug.com/396477. 942 // http://crbug.com/396477.
927 TEST_F(LabelSelectionTest, DISABLED_SelectionClipboard) { 943 TEST_F(LabelSelectionTest, DISABLED_SelectionClipboard) {
928 label()->SetText(ASCIIToUTF16("Label selection clipboard")); 944 label()->SetText(ASCIIToUTF16("Label selection clipboard"));
929 label()->SizeToPreferredSize(); 945 label()->SizeToPreferredSize();
930 ASSERT_TRUE(label()->SetSelectable(true)); 946 ASSERT_TRUE(label()->SetSelectable(true));
931 947
932 // Verify programmatic modification of selection, does not modify the 948 // Verify programmatic modification of selection, does not modify the
933 // selection clipboard. 949 // selection clipboard.
934 label()->SelectRange(gfx::Range(2, 5)); 950 label()->SelectRange(gfx::Range(2, 5));
935 EXPECT_STR_EQ("bel", GetSelectedText()); 951 EXPECT_STR_EQ("bel", GetSelectedText());
936 EXPECT_TRUE(GetSelectionClipboardText().empty()); 952 EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
937 953
938 // Verify text selection using the mouse updates the selection clipboard. 954 // Verify text selection using the mouse updates the selection clipboard.
939 PerformMousePress(GetCursorPoint(5)); 955 PerformMousePress(GetCursorPoint(5));
940 PerformMouseDragTo(gfx::Point()); 956 PerformMouseDragTo(gfx::Point());
941 PerformMouseRelease(gfx::Point()); 957 PerformMouseRelease(gfx::Point());
942 EXPECT_STR_EQ("Label", GetSelectedText()); 958 EXPECT_STR_EQ("Label", GetSelectedText());
943 EXPECT_STR_EQ("Label", GetSelectionClipboardText()); 959 EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
944 } 960 }
945 #endif 961 #endif
946 962
963 // Verify that keyboard shortcuts for Copy and Select All work when a selectable
964 // label is focused.
965 TEST_F(LabelSelectionTest, KeyboardActions) {
966 const base::string16 initial_text = ASCIIToUTF16("Label keyboard actions");
967 label()->SetText(initial_text);
968 label()->SizeToPreferredSize();
969 ASSERT_TRUE(label()->SetSelectable(true));
970
971 PerformClick(gfx::Point());
972 EXPECT_EQ(label(), GetFocusedView());
973
974 event_generator()->PressKey(ui::VKEY_A, kControlCommandModifier);
975 EXPECT_EQ(initial_text, GetSelectedText());
976
977 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
978 EXPECT_EQ(initial_text, GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
msw 2016/11/15 20:06:45 You'll need to modify/disable this test for the sa
karandeepb 2016/11/16 07:48:29 Have created https://codereview.chromium.org/24993
979
980 // The selection should get cleared on changing the text, but focus should not
981 // be affected.
982 const base::string16 new_text = ASCIIToUTF16("Label obscured text");
983 label()->SetText(new_text);
984 EXPECT_FALSE(label()->HasSelection());
985 EXPECT_EQ(label(), GetFocusedView());
986
987 label()->SetObscured(true);
988 event_generator()->PressKey(ui::VKEY_A, kControlCommandModifier);
989 EXPECT_EQ(new_text, GetSelectedText());
990
991 // Since the text is obscured, clipboard text should not change.
992 event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
993 EXPECT_EQ(initial_text, GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
994 }
995
996 // Verify the context menu options are enabled and disabled appropriately.
997 TEST_F(LabelSelectionTest, ContextMenuContents) {
998 label()->SetText(ASCIIToUTF16("Label context menu"));
999 label()->SizeToPreferredSize();
1000
1001 // A non-selectable label would not show a context menu and both COPY and
1002 // SELECT_ALL context menu items should be disabled for it.
1003 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY));
1004 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL));
1005
1006 // For a selectable label with no selection, only SELECT_ALL should be
1007 // enabled.
1008 ASSERT_TRUE(label()->SetSelectable(true));
1009 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY));
1010 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL));
1011
1012 // For a selectable label with a selection, both COPY and SELECT_ALL should be
msw 2016/11/15 20:06:45 nit: also check that some unhandled command (eg. p
karandeepb 2016/11/16 07:48:29 Done.
1013 // enabled.
1014 label()->SelectRange(gfx::Range(0, 4));
1015 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_COPY));
1016 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL));
1017
1018 // For an obscured selectable label, only SELECT_ALL should be enabled.
msw 2016/11/15 20:06:45 I wonder if we should disable select-all (or even
karandeepb 2016/11/16 07:48:29 Yeah I agree making obscured labels selectable doe
1019 label()->SetObscured(true);
1020 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY));
1021 EXPECT_TRUE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL));
1022
1023 // For an empty label, both COPY and SELECT_ALL should be disabled.
1024 label()->SetText(base::string16());
1025 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_COPY));
1026 EXPECT_FALSE(label()->IsCommandIdEnabled(IDS_APP_SELECT_ALL));
1027 }
1028
947 } // namespace views 1029 } // namespace views
OLDNEW
« ui/views/controls/label.cc ('K') | « ui/views/controls/label.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698