- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / location_bar / autocomplete_text_field_editor_unittest.mm
1 // Copyright (c) 2011 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 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
6
7 #include "base/mac/scoped_nsobject.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_util.h"
10 #include "chrome/app/chrome_command_ids.h"  // IDC_*
11 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
12 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_unittest_helper.h"
13 #include "grit/generated_resources.h"
14 #include "testing/gmock/include/gmock/gmock-matchers.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #import "testing/gtest_mac.h"
17 #include "testing/platform_test.h"
18 #import "third_party/ocmock/OCMock/OCMock.h"
19 #include "third_party/ocmock/gtest_support.h"
20 #import "third_party/ocmock/ocmock_extensions.h"
21 #import "ui/base/test/cocoa_test_event_utils.h"
22
23 using ::testing::Return;
24 using ::testing::ReturnArg;
25 using ::testing::StrictMock;
26 using ::testing::A;
27
28 namespace {
29
30 // TODO(shess): Very similar to AutocompleteTextFieldTest.  Maybe
31 // those can be shared.
32
33 class AutocompleteTextFieldEditorTest : public CocoaTest {
34  public:
35   virtual void SetUp() {
36     CocoaTest::SetUp();
37     NSRect frame = NSMakeRect(0, 0, 50, 30);
38     base::scoped_nsobject<AutocompleteTextField> field(
39         [[AutocompleteTextField alloc] initWithFrame:frame]);
40     field_ = field.get();
41     [field_ setStringValue:@"Testing"];
42     [[test_window() contentView] addSubview:field_];
43
44     // Arrange for |field_| to get the right field editor.
45     window_delegate_.reset(
46         [[AutocompleteTextFieldWindowTestDelegate alloc] init]);
47     [test_window() setDelegate:window_delegate_.get()];
48
49     // Get the field editor setup.
50     [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
51     editor_ = static_cast<AutocompleteTextFieldEditor*>([field_ currentEditor]);
52
53     EXPECT_TRUE(editor_);
54     EXPECT_TRUE([editor_ isKindOfClass:[AutocompleteTextFieldEditor class]]);
55   }
56
57   AutocompleteTextFieldEditor* editor_;
58   AutocompleteTextField* field_;
59   base::scoped_nsobject<AutocompleteTextFieldWindowTestDelegate>
60       window_delegate_;
61 };
62
63 // Disabled because it crashes sometimes. http://crbug.com/49522
64 // Can't rename DISABLED_ because the TEST_VIEW macro prepends.
65 //     http://crbug.com/53621
66 #if 0
67 TEST_VIEW(AutocompleteTextFieldEditorTest, field_);
68 #endif
69
70 // Test that control characters are stripped from insertions.
71 TEST_F(AutocompleteTextFieldEditorTest, InsertStripsControlChars) {
72   // Sets a string in the field.
73   NSString* test_string = @"astring";
74   [field_ setStringValue:test_string];
75   [editor_ selectAll:nil];
76
77   [editor_ insertText:@"t"];
78   EXPECT_NSEQ(@"t", [field_ stringValue]);
79
80   [editor_ insertText:@"h"];
81   EXPECT_NSEQ(@"th", [field_ stringValue]);
82
83   // TAB doesn't get inserted.
84   [editor_ insertText:[NSString stringWithFormat:@"%c", 7]];
85   EXPECT_NSEQ(@"th", [field_ stringValue]);
86
87   // Newline doesn't get inserted.
88   [editor_ insertText:[NSString stringWithFormat:@"%c", 12]];
89   EXPECT_NSEQ(@"th", [field_ stringValue]);
90
91   // Multi-character strings get through.
92   [editor_ insertText:[NSString stringWithFormat:@"i%cs%c", 8, 127]];
93   EXPECT_NSEQ(@"this", [field_ stringValue]);
94
95   // Attempting to insert newline when everything is selected clears
96   // the field.
97   [editor_ selectAll:nil];
98   [editor_ insertText:[NSString stringWithFormat:@"%c", 12]];
99   EXPECT_NSEQ(@"", [field_ stringValue]);
100 }
101
102 // Test that |delegate| can provide page action menus.
103 TEST_F(AutocompleteTextFieldEditorTest, PageActionMenus) {
104   // The event just needs to be something the mock can recognize.
105   NSEvent* event = cocoa_test_event_utils::MouseEventAtPoint(NSZeroPoint,
106                                                              NSRightMouseDown,
107                                                              0);
108
109   // Trivial menu which we can recognize and which doesn't look like
110   // the default editor context menu.
111   base::scoped_nsobject<id> menu([[NSMenu alloc] initWithTitle:@"Menu"]);
112   [menu addItemWithTitle:@"Go Fish"
113                   action:@selector(goFish:)
114            keyEquivalent:@""];
115
116   // So that we don't have to mock the observer.
117   [editor_ setEditable:NO];
118
119   // The delegate's intercept point gets called, and results are
120   // propagated back.
121   {
122     id delegate = [OCMockObject mockForClass:[AutocompleteTextField class]];
123     [[[delegate stub] andReturnBool:YES]
124       isKindOfClass:[AutocompleteTextField class]];
125     [[[delegate expect] andReturn:menu.get()] decorationMenuForEvent:event];
126     [[[delegate expect] andReturn:nil] undoManagerForTextView:editor_];
127     [editor_ setDelegate:delegate];
128     NSMenu* contextMenu = [editor_ menuForEvent:event];
129     EXPECT_OCMOCK_VERIFY(delegate);
130     [editor_ setDelegate:nil];
131
132     EXPECT_EQ(contextMenu, menu.get());
133   }
134
135   // If the delegate does not return any menu, the default menu is
136   // returned.
137   {
138     id delegate = [OCMockObject mockForClass:[AutocompleteTextField class]];
139     [[[delegate stub] andReturnBool:YES]
140       isKindOfClass:[AutocompleteTextField class]];
141     [[[delegate expect] andReturn:nil] decorationMenuForEvent:event];
142     [[[delegate expect] andReturn:nil] undoManagerForTextView:editor_];
143     [editor_ setDelegate:delegate];
144     NSMenu* contextMenu = [editor_ menuForEvent:event];
145     EXPECT_OCMOCK_VERIFY(delegate);
146     [editor_ setDelegate:nil];
147
148     EXPECT_NE(contextMenu, menu.get());
149     NSArray* items = [contextMenu itemArray];
150     ASSERT_GT([items count], 0U);
151     EXPECT_EQ(@selector(cut:), [[items objectAtIndex:0] action])
152         << "action is: " << sel_getName([[items objectAtIndex:0] action]);
153   }
154 }
155
156 // Base class for testing AutocompleteTextFieldObserver messages.
157 class AutocompleteTextFieldEditorObserverTest
158     : public AutocompleteTextFieldEditorTest {
159  public:
160   virtual void SetUp() {
161     AutocompleteTextFieldEditorTest::SetUp();
162     [field_ setObserver:&field_observer_];
163   }
164
165   virtual void TearDown() {
166     // Clear the observer so that we don't show output for
167     // uninteresting messages to the mock (for instance, if |field_| has
168     // focus at the end of the test).
169     [field_ setObserver:NULL];
170
171     AutocompleteTextFieldEditorTest::TearDown();
172   }
173
174   StrictMock<MockAutocompleteTextFieldObserver> field_observer_;
175 };
176
177 // Test that the field editor is linked in correctly.
178 TEST_F(AutocompleteTextFieldEditorTest, FirstResponder) {
179   EXPECT_EQ(editor_, [field_ currentEditor]);
180   EXPECT_TRUE([editor_ isDescendantOf:field_]);
181   EXPECT_EQ([editor_ delegate], field_);
182   EXPECT_EQ([editor_ observer], [field_ observer]);
183 }
184
185 // Test drawing, mostly to ensure nothing leaks or crashes.
186 TEST_F(AutocompleteTextFieldEditorTest, Display) {
187   [field_ display];
188   [editor_ display];
189 }
190
191 // Test setting gray text, mostly to ensure nothing leaks or crashes.
192 TEST_F(AutocompleteTextFieldEditorTest, GrayText) {
193   [editor_ display];
194   EXPECT_FALSE([editor_ needsDisplay]);
195   [field_ setGrayTextAutocompletion:@"foo" textColor:[NSColor redColor]];
196   EXPECT_TRUE([editor_ needsDisplay]);
197   [editor_ display];
198 }
199
200 // Test that -paste: is correctly delegated to the observer.
201 TEST_F(AutocompleteTextFieldEditorObserverTest, Paste) {
202   EXPECT_CALL(field_observer_, OnPaste());
203   [editor_ paste:nil];
204 }
205
206 // Test that -copy: is correctly delegated to the observer.
207 TEST_F(AutocompleteTextFieldEditorObserverTest, Copy) {
208   EXPECT_CALL(field_observer_, CanCopy())
209       .WillOnce(Return(true));
210   EXPECT_CALL(field_observer_, CopyToPasteboard(A<NSPasteboard*>()))
211       .Times(1);
212   [editor_ copy:nil];
213 }
214
215 // Test that -showURL: is correctly delegated to the observer.
216 TEST_F(AutocompleteTextFieldEditorObserverTest, ShowURL) {
217   EXPECT_CALL(field_observer_, ShowURL()).Times(1);
218   [editor_ showURL:nil];
219 }
220
221 // Test that -cut: is correctly delegated to the observer and clears
222 // the text field.
223 TEST_F(AutocompleteTextFieldEditorObserverTest, Cut) {
224   // Sets a string in the field.
225   NSString* test_string = @"astring";
226   EXPECT_CALL(field_observer_, OnDidBeginEditing());
227   EXPECT_CALL(field_observer_, OnBeforeChange());
228   EXPECT_CALL(field_observer_, OnDidChange());
229   EXPECT_CALL(field_observer_, SelectionRangeForProposedRange(A<NSRange>()))
230       .WillRepeatedly(ReturnArg<0>());
231   [editor_ setString:test_string];
232   [editor_ selectAll:nil];
233
234   // Calls cut.
235   EXPECT_CALL(field_observer_, CanCopy())
236       .WillOnce(Return(true));
237   EXPECT_CALL(field_observer_, CopyToPasteboard(A<NSPasteboard*>()))
238       .Times(1);
239   [editor_ cut:nil];
240
241   // Check if the field is cleared.
242   ASSERT_EQ([[editor_ textStorage] length], 0U);
243 }
244
245 // Test that -pasteAndGo: is correctly delegated to the observer.
246 TEST_F(AutocompleteTextFieldEditorObserverTest, PasteAndGo) {
247   EXPECT_CALL(field_observer_, OnPasteAndGo());
248   [editor_ pasteAndGo:nil];
249 }
250
251 // Test that the menu is constructed correctly.
252 TEST_F(AutocompleteTextFieldEditorObserverTest, Menu) {
253   EXPECT_CALL(field_observer_, GetPasteActionStringId()).
254       WillOnce(Return(IDS_PASTE_AND_GO));
255   EXPECT_CALL(field_observer_, ShouldEnableShowURL()).
256       WillOnce(Return(true));
257
258   NSMenu* menu = [editor_ menuForEvent:nil];
259   NSArray* items = [menu itemArray];
260   ASSERT_EQ([items count], 7U);
261   // TODO(shess): Check the titles, too?
262   NSUInteger i = 0;  // Use an index to make future changes easier.
263   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(cut:));
264   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(copy:));
265   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(paste:));
266   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(pasteAndGo:));
267   EXPECT_TRUE([[items objectAtIndex:i++] isSeparatorItem]);
268   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(showURL:));
269   EXPECT_EQ([[items objectAtIndex:i] tag], IDC_EDIT_SEARCH_ENGINES);
270   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(commandDispatch:));
271 }
272
273 // Test that the menu is constructed correctly when field isn't
274 // editable.
275 TEST_F(AutocompleteTextFieldEditorObserverTest, CanPasteAndGoMenuNotEditable) {
276   [field_ setEditable:NO];
277   [editor_ setEditable:NO];
278
279   // Never call this when not editable.
280   EXPECT_CALL(field_observer_, GetPasteActionStringId()).Times(0);
281
282   NSMenu* menu = [editor_ menuForEvent:nil];
283   NSArray* items = [menu itemArray];
284   ASSERT_EQ([items count], 3U);
285   // TODO(shess): Check the titles, too?
286   NSUInteger i = 0;  // Use an index to make future changes easier.
287   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(cut:));
288   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(copy:));
289   EXPECT_EQ([[items objectAtIndex:i++] action], @selector(paste:));
290 }
291
292 // Test that the menu validation works as expected when CanPasteAndGo().
293 TEST_F(AutocompleteTextFieldEditorObserverTest, CanPasteAndGoValidate) {
294   EXPECT_CALL(field_observer_, GetPasteActionStringId())
295       .WillOnce(Return(IDS_PASTE_AND_GO));
296   EXPECT_CALL(field_observer_, CanPasteAndGo()).WillOnce(Return(true));
297   EXPECT_CALL(field_observer_, ShouldEnableShowURL())
298       .WillOnce(Return(false));
299
300   NSMenu* menu = [editor_ menuForEvent:nil];
301   NSArray* items = [menu itemArray];
302   ASSERT_EQ([items count], 6U);
303   for (NSUInteger i = 0; i < [items count]; ++i) {
304     NSMenuItem* item = [items objectAtIndex:i];
305     if ([item action] == @selector(pasteAndGo:)) {
306       EXPECT_TRUE([editor_ validateMenuItem:item]);
307       break;
308     }
309   }
310 }
311
312 // Test that the menu validation works as expected when !CanPasteAndGo().
313 TEST_F(AutocompleteTextFieldEditorObserverTest, CannotPasteAndGoValidate) {
314   EXPECT_CALL(field_observer_, GetPasteActionStringId())
315       .WillOnce(Return(IDS_PASTE_AND_GO));
316   EXPECT_CALL(field_observer_, CanPasteAndGo()).WillOnce(Return(false));
317   EXPECT_CALL(field_observer_, ShouldEnableShowURL())
318       .WillOnce(Return(false));
319
320   NSMenu* menu = [editor_ menuForEvent:nil];
321   NSArray* items = [menu itemArray];
322   ASSERT_EQ([items count], 6U);
323   for (NSUInteger i = 0; i < [items count]; ++i) {
324     NSMenuItem* item = [items objectAtIndex:i];
325     if ([item action] == @selector(pasteAndGo:)) {
326       EXPECT_FALSE([editor_ validateMenuItem:item]);
327       break;
328     }
329   }
330 }
331
332 // Test that the menu validation works as expected when ShouldEnableShowURL().
333 TEST_F(AutocompleteTextFieldEditorObserverTest, ShouldEnableShowURLValidate) {
334   EXPECT_CALL(field_observer_, GetPasteActionStringId())
335       .WillOnce(Return(IDS_PASTE_AND_GO));
336   EXPECT_CALL(field_observer_, ShouldEnableShowURL())
337       .WillRepeatedly(Return(true));
338
339   NSMenu* menu = [editor_ menuForEvent:nil];
340   NSArray* items = [menu itemArray];
341   ASSERT_EQ([items count], 7U);
342   for (NSUInteger i = 0; i < [items count]; ++i) {
343     NSMenuItem* item = [items objectAtIndex:i];
344     if ([item action] == @selector(showURL:)) {
345       EXPECT_TRUE([editor_ validateMenuItem:item]);
346       break;
347     }
348   }
349 }
350
351 }  // namespace