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

Side by Side Diff: ui/views/cocoa/bridged_native_widget_unittest.mm

Issue 329463002: MacViews: Implement text input. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More changes for tapted. Created 6 years, 6 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #import "ui/views/cocoa/bridged_native_widget.h" 5 #import "ui/views/cocoa/bridged_native_widget.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
10 #import "testing/gtest_mac.h" 12 #import "testing/gtest_mac.h"
11 #import "ui/gfx/test/ui_cocoa_test_helper.h" 13 #import "ui/gfx/test/ui_cocoa_test_helper.h"
12 #import "ui/views/cocoa/bridged_content_view.h" 14 #import "ui/views/cocoa/bridged_content_view.h"
15 #include "ui/views/controls/textfield/textfield.h"
13 #include "ui/views/ime/input_method.h" 16 #include "ui/views/ime/input_method.h"
14 #include "ui/views/view.h" 17 #include "ui/views/view.h"
15 18
19 using base::ASCIIToUTF16;
20 using base::SysNSStringToUTF8;
21 using base::SysNSStringToUTF16;
22 using base::SysUTF8ToNSString;
23
24 #define EXPECT_EQ_RANGE(a, b) \
25 EXPECT_EQ(a.location, b.location); \
26 EXPECT_EQ(a.length, b.length);
27
28 namespace {
29
30 // Empty range shortcut for readibility.
31 NSRange EmptyRange() {
32 return NSMakeRange(NSNotFound, 0);
33 }
34
35 } // namespace
36
16 namespace views { 37 namespace views {
17 38
18 class BridgedNativeWidgetTest : public ui::CocoaTest { 39 class BridgedNativeWidgetTest : public ui::CocoaTest {
19 public: 40 public:
20 BridgedNativeWidgetTest(); 41 BridgedNativeWidgetTest();
21 virtual ~BridgedNativeWidgetTest(); 42 virtual ~BridgedNativeWidgetTest();
22 43
44 // Install a textfield in the view hierarchy and make it the text input
45 // client.
46 void InstallTextField(const std::string& text);
47
48 // Returns the current text as std::string.
49 std::string GetText();
50
23 // testing::Test: 51 // testing::Test:
24 virtual void SetUp() OVERRIDE; 52 virtual void SetUp() OVERRIDE;
25 virtual void TearDown() OVERRIDE; 53 virtual void TearDown() OVERRIDE;
26 54
27 protected: 55 protected:
28 // TODO(tapted): Make this a EventCountView from widget_unittest.cc. 56 // TODO(tapted): Make this a EventCountView from widget_unittest.cc.
29 scoped_ptr<views::View> view_; 57 scoped_ptr<views::View> view_;
30 scoped_ptr<BridgedNativeWidget> bridge_; 58 scoped_ptr<BridgedNativeWidget> bridge_;
59 BridgedContentView* ns_view_; // Weak. Owned by bridge_.
31 60
32 private: 61 private:
33 DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTest); 62 DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTest);
34 }; 63 };
35 64
36 BridgedNativeWidgetTest::BridgedNativeWidgetTest() { 65 BridgedNativeWidgetTest::BridgedNativeWidgetTest() {
37 } 66 }
38 67
39 BridgedNativeWidgetTest::~BridgedNativeWidgetTest() { 68 BridgedNativeWidgetTest::~BridgedNativeWidgetTest() {
40 } 69 }
41 70
71 void BridgedNativeWidgetTest::InstallTextField(const std::string& text) {
72 Textfield* textfield = new Textfield();
73 textfield->SetText(ASCIIToUTF16(text));
74 view_->AddChildView(textfield);
75 [ns_view_ setTextInputClient:textfield];
76 }
77
78 std::string BridgedNativeWidgetTest::GetText() {
79 NSRange range = NSMakeRange(0, NSUIntegerMax);
80 NSAttributedString* text =
81 [ns_view_ attributedSubstringForProposedRange:range actualRange:NULL];
82 return SysNSStringToUTF8([text string]);
83 }
84
42 void BridgedNativeWidgetTest::SetUp() { 85 void BridgedNativeWidgetTest::SetUp() {
43 ui::CocoaTest::SetUp(); 86 ui::CocoaTest::SetUp();
44 87
45 view_.reset(new views::View); 88 view_.reset(new views::View);
46 bridge_.reset(new BridgedNativeWidget(NULL)); 89 bridge_.reset(new BridgedNativeWidget(NULL));
47 base::scoped_nsobject<NSWindow> window([test_window() retain]); 90 base::scoped_nsobject<NSWindow> window([test_window() retain]);
48 91
49 EXPECT_FALSE([window delegate]); 92 EXPECT_FALSE([window delegate]);
50 bridge_->Init(window); 93 bridge_->Init(window);
51 94
52 // The delegate should exist before setting the root view. 95 // The delegate should exist before setting the root view.
53 EXPECT_TRUE([window delegate]); 96 EXPECT_TRUE([window delegate]);
54 bridge_->SetRootView(view_.get()); 97 bridge_->SetRootView(view_.get());
98 ns_view_ = bridge_->ns_view();
55 99
56 [test_window() makePretendKeyWindowAndSetFirstResponder:bridge_->ns_view()]; 100 [test_window() makePretendKeyWindowAndSetFirstResponder:bridge_->ns_view()];
57 } 101 }
58 102
59 void BridgedNativeWidgetTest::TearDown() { 103 void BridgedNativeWidgetTest::TearDown() {
60 [test_window() clearPretendKeyWindowAndFirstResponder]; 104 [test_window() clearPretendKeyWindowAndFirstResponder];
61 105
62 bridge_.reset(); 106 bridge_.reset();
63 view_.reset(); 107 view_.reset();
64 108
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 // Make sure a resize actually occurs. 148 // Make sure a resize actually occurs.
105 EXPECT_NE(kTestNewWidth, view_->width()); 149 EXPECT_NE(kTestNewWidth, view_->width());
106 EXPECT_NE(kTestNewHeight, view_->height()); 150 EXPECT_NE(kTestNewHeight, view_->height());
107 151
108 [test_window() setFrame:NSMakeRect(0, 0, kTestNewWidth, kTestNewHeight) 152 [test_window() setFrame:NSMakeRect(0, 0, kTestNewWidth, kTestNewHeight)
109 display:NO]; 153 display:NO];
110 EXPECT_EQ(kTestNewWidth, view_->width()); 154 EXPECT_EQ(kTestNewWidth, view_->width());
111 EXPECT_EQ(kTestNewHeight, view_->height()); 155 EXPECT_EQ(kTestNewHeight, view_->height());
112 } 156 }
113 157
114 TEST_F(BridgedNativeWidgetTest, CreateInputMethod) { 158 TEST_F(BridgedNativeWidgetTest, CreateInputMethodShouldNotReturnNull) {
115 scoped_ptr<views::InputMethod> input_method(bridge_->CreateInputMethod()); 159 scoped_ptr<views::InputMethod> input_method(bridge_->CreateInputMethod());
116 EXPECT_TRUE(input_method); 160 EXPECT_TRUE(input_method);
117 } 161 }
118 162
119 TEST_F(BridgedNativeWidgetTest, GetHostInputMethod) { 163 TEST_F(BridgedNativeWidgetTest, GetHostInputMethodShouldNotReturnNull) {
120 EXPECT_TRUE(bridge_->GetHostInputMethod()); 164 EXPECT_TRUE(bridge_->GetHostInputMethod());
121 } 165 }
122 166
167 // Test getting complete string using text input protocol.
168 TEST_F(BridgedNativeWidgetTest, TextInput_GetCompleteString) {
169 const std::string kTestString = "foo bar baz";
170 InstallTextField(kTestString);
171
172 NSRange range = NSMakeRange(0, kTestString.size());
173 NSRange actual_range;
174 NSAttributedString* text =
175 [ns_view_ attributedSubstringForProposedRange:range
176 actualRange:&actual_range];
177 EXPECT_EQ(kTestString, SysNSStringToUTF8([text string]));
178 EXPECT_EQ_RANGE(range, actual_range);
179 }
180
181 // Test getting middle substring using text input protocol.
182 TEST_F(BridgedNativeWidgetTest, TextInput_GetMiddleSubstring) {
183 const std::string kTestString = "foo bar baz";
184 InstallTextField(kTestString);
185
186 NSRange range = NSMakeRange(4, 3);
187 NSRange actual_range;
188 NSAttributedString* text =
189 [ns_view_ attributedSubstringForProposedRange:range
190 actualRange:&actual_range];
191 EXPECT_EQ("bar", SysNSStringToUTF8([text string]));
192 EXPECT_EQ_RANGE(range, actual_range);
193 }
194
195 // Test getting ending substring using text input protocol.
196 TEST_F(BridgedNativeWidgetTest, TextInput_GetEndingSubstring) {
197 const std::string kTestString = "foo bar baz";
198 InstallTextField(kTestString);
199
200 NSRange range = NSMakeRange(8, 100);
201 NSRange actual_range;
202 NSAttributedString* text =
203 [ns_view_ attributedSubstringForProposedRange:range
204 actualRange:&actual_range];
205 EXPECT_EQ("baz", SysNSStringToUTF8([text string]));
206 EXPECT_EQ(range.location, actual_range.location);
207 EXPECT_EQ(3U, actual_range.length);
208 }
209
210 // Test getting empty substring using text input protocol.
211 TEST_F(BridgedNativeWidgetTest, TextInput_GetEmptySubstring) {
212 const std::string kTestString = "foo bar baz";
213 InstallTextField(kTestString);
214
215 NSRange range = EmptyRange();
216 NSRange actual_range;
217 NSAttributedString* text =
218 [ns_view_ attributedSubstringForProposedRange:range
219 actualRange:&actual_range];
220 EXPECT_EQ("", SysNSStringToUTF8([text string]));
221 EXPECT_EQ_RANGE(range, actual_range);
222 }
223
224 // Test inserting text using text input protocol.
225 TEST_F(BridgedNativeWidgetTest, TextInput_InsertText) {
226 const std::string kTestString = "foo";
227 InstallTextField(kTestString);
228
229 [ns_view_ insertText:SysUTF8ToNSString(kTestString)
230 replacementRange:EmptyRange()];
231 gfx::Range range(0, kTestString.size());
232 base::string16 text;
233 EXPECT_TRUE([ns_view_ textInputClient]->GetTextFromRange(range, &text));
234 EXPECT_EQ(ASCIIToUTF16(kTestString), text);
235 }
236
237 // Test replacing text using text input protocol.
238 TEST_F(BridgedNativeWidgetTest, TextInput_ReplaceText) {
239 const std::string kTestString = "foo bar";
240 InstallTextField(kTestString);
241
242 [ns_view_ insertText:@"baz" replacementRange:NSMakeRange(4, 3)];
243 EXPECT_EQ("foo baz", GetText());
244 }
245
246 // Test IME composition using text input protocol.
247 TEST_F(BridgedNativeWidgetTest, TextInput_Compose) {
248 const std::string kTestString = "foo ";
249 InstallTextField(kTestString);
250
251 EXPECT_FALSE([ns_view_ hasMarkedText]);
252 EXPECT_EQ_RANGE(EmptyRange(), [ns_view_ markedRange]);
253
254 // Start composition.
255 NSString* compositionText = @"bar";
256 NSUInteger compositionLength = [compositionText length];
257 [ns_view_ setMarkedText:compositionText
258 selectedRange:NSMakeRange(0, 2)
259 replacementRange:EmptyRange()];
260 EXPECT_TRUE([ns_view_ hasMarkedText]);
261 EXPECT_EQ_RANGE(NSMakeRange(kTestString.size(), compositionLength),
262 [ns_view_ markedRange]);
263 EXPECT_EQ_RANGE(NSMakeRange(kTestString.size(), 2), [ns_view_ selectedRange]);
264
265 // Confirm composition.
266 [ns_view_ unmarkText];
267 EXPECT_FALSE([ns_view_ hasMarkedText]);
268 EXPECT_EQ_RANGE(EmptyRange(), [ns_view_ markedRange]);
269 EXPECT_EQ("foo bar", GetText());
270 EXPECT_EQ_RANGE(NSMakeRange(GetText().size(), 0), [ns_view_ selectedRange]);
271 }
272
273 // Test moving the caret left and right using text input protocol.
274 TEST_F(BridgedNativeWidgetTest, TextInput_MoveLeftRight) {
275 InstallTextField("foo");
276 EXPECT_EQ_RANGE(NSMakeRange(3, 0), [ns_view_ selectedRange]);
277
278 // Move right not allowed, out of range.
279 [ns_view_ doCommandBySelector:@selector(moveRight:)];
280 EXPECT_EQ_RANGE(NSMakeRange(3, 0), [ns_view_ selectedRange]);
281
282 // Move left.
283 [ns_view_ doCommandBySelector:@selector(moveLeft:)];
284 EXPECT_EQ_RANGE(NSMakeRange(2, 0), [ns_view_ selectedRange]);
285
286 // Move right.
287 [ns_view_ doCommandBySelector:@selector(moveRight:)];
288 EXPECT_EQ_RANGE(NSMakeRange(3, 0), [ns_view_ selectedRange]);
289 }
290
291 // Test backward delete using text input protocol.
292 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteBackward) {
293 InstallTextField("a");
294 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]);
295
296 // Delete one character.
297 [ns_view_ doCommandBySelector:@selector(deleteBackward:)];
298 EXPECT_EQ("", GetText());
299 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]);
300
301 // Try to delete again on an empty string.
302 [ns_view_ doCommandBySelector:@selector(deleteBackward:)];
303 EXPECT_EQ("", GetText());
304 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]);
305 }
306
307 // Test forward delete using text input protocol.
308 TEST_F(BridgedNativeWidgetTest, TextInput_DeleteForward) {
309 InstallTextField("a");
310 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]);
311
312 // At the end of the string, can't delete forward.
313 [ns_view_ doCommandBySelector:@selector(deleteForward:)];
314 EXPECT_EQ("a", GetText());
315 EXPECT_EQ_RANGE(NSMakeRange(1, 0), [ns_view_ selectedRange]);
316
317 // Should succeed after moving left first.
318 [ns_view_ doCommandBySelector:@selector(moveLeft:)];
319 [ns_view_ doCommandBySelector:@selector(deleteForward:)];
320 EXPECT_EQ("", GetText());
321 EXPECT_EQ_RANGE(NSMakeRange(0, 0), [ns_view_ selectedRange]);
322 }
323
123 } // namespace views 324 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698