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
3 // found in the LICENSE file.
5 #import <Cocoa/Cocoa.h>
7 #include "base/mac/scoped_nsobject.h"
8 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
9 #import "chrome/browser/ui/cocoa/styled_text_field.h"
10 #import "chrome/browser/ui/cocoa/styled_text_field_cell.h"
11 #import "chrome/browser/ui/cocoa/styled_text_field_test_helper.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #import "testing/gtest_mac.h"
17 // Width of the field so that we don't have to ask |field_| for it all
19 static const CGFloat kWidth(300.0);
21 class StyledTextFieldTest : public CocoaTest {
23 StyledTextFieldTest() {
24 // Make sure this is wide enough to play games with the cell
26 NSRect frame = NSMakeRect(0, 0, kWidth, 30);
28 base::scoped_nsobject<StyledTextFieldTestCell> cell(
29 [[StyledTextFieldTestCell alloc] initTextCell:@"Testing"]);
31 [cell_ setEditable:YES];
32 [cell_ setBordered:YES];
34 base::scoped_nsobject<StyledTextField> field(
35 [[StyledTextField alloc] initWithFrame:frame]);
37 [field_ setCell:cell_];
39 [[test_window() contentView] addSubview:field_];
42 // Helper to return the field-editor frame being used w/in |field_|.
43 NSRect EditorFrame() {
44 EXPECT_TRUE([field_ currentEditor]);
45 EXPECT_EQ([[field_ subviews] count], 1U);
46 if ([[field_ subviews] count] > 0) {
47 return [[[field_ subviews] objectAtIndex:0] frame];
49 // Return something which won't work so the caller can soldier
55 StyledTextField* field_;
56 StyledTextFieldTestCell* cell_;
59 // Basic view tests (AddRemove, Display).
60 TEST_VIEW(StyledTextFieldTest, field_);
62 // Test that we get the same cell from -cell and
63 // -styledTextFieldCell.
64 TEST_F(StyledTextFieldTest, Cell) {
65 StyledTextFieldCell* cell = [field_ styledTextFieldCell];
66 EXPECT_EQ(cell, [field_ cell]);
67 EXPECT_TRUE(cell != nil);
70 // Test that becoming first responder sets things up correctly.
71 TEST_F(StyledTextFieldTest, FirstResponder) {
72 EXPECT_EQ(nil, [field_ currentEditor]);
73 EXPECT_EQ([[field_ subviews] count], 0U);
74 [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
75 EXPECT_FALSE(nil == [field_ currentEditor]);
76 EXPECT_EQ([[field_ subviews] count], 1U);
77 EXPECT_TRUE([[field_ currentEditor] isDescendantOf:field_]);
80 TEST_F(StyledTextFieldTest, AvailableDecorationWidth) {
81 // A fudge factor to account for how much space the border takes up.
82 // The test shouldn't be too dependent on the field's internals, but
83 // it also shouldn't let deranged cases fall through the cracks
84 // (like nothing available with no text, or everything available
86 const CGFloat kBorderWidth = 20.0;
88 // With no contents, almost the entire width is available for
90 [field_ setStringValue:@""];
91 CGFloat availableWidth = [field_ availableDecorationWidth];
92 EXPECT_LE(availableWidth, kWidth);
93 EXPECT_GT(availableWidth, kWidth - kBorderWidth);
95 // With minor contents, most of the remaining width is available for
97 NSDictionary* attributes =
98 [NSDictionary dictionaryWithObject:[field_ font]
99 forKey:NSFontAttributeName];
100 NSString* string = @"Hello world";
101 const NSSize size([string sizeWithAttributes:attributes]);
102 [field_ setStringValue:string];
103 availableWidth = [field_ availableDecorationWidth];
104 EXPECT_LE(availableWidth, kWidth - size.width);
105 EXPECT_GT(availableWidth, kWidth - size.width - kBorderWidth);
107 // With huge contents, nothing at all is left for decorations.
108 string = @"A long string which is surely wider than field_ can hold.";
109 [field_ setStringValue:string];
110 availableWidth = [field_ availableDecorationWidth];
111 EXPECT_LT(availableWidth, 0.0);
114 // Test drawing, mostly to ensure nothing leaks or crashes.
115 TEST_F(StyledTextFieldTest, Display) {
118 // Test focused drawing.
119 [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
123 // Test that the field editor gets the same bounds when focus is delivered by
124 // the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded.
125 TEST_F(StyledTextFieldTest, ResetFieldEditorBase) {
126 // Capture the editor frame resulting from the standard focus machinery.
127 [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
128 const NSRect baseEditorFrame(EditorFrame());
130 // Setting a hint should result in a strictly smaller editor frame.
131 EXPECT_EQ(0, [cell_ leftMargin]);
132 EXPECT_EQ(0, [cell_ rightMargin]);
133 [cell_ setLeftMargin:10];
134 [field_ resetFieldEditorFrameIfNeeded];
135 EXPECT_NSNE(baseEditorFrame, EditorFrame());
136 EXPECT_TRUE(NSContainsRect(baseEditorFrame, EditorFrame()));
138 // Resetting the margin and using -resetFieldEditorFrameIfNeeded should result
139 // in the same frame as the standard focus machinery.
140 [cell_ setLeftMargin:0];
141 [field_ resetFieldEditorFrameIfNeeded];
142 EXPECT_NSEQ(baseEditorFrame, EditorFrame());
145 // Test that the field editor gets the same bounds when focus is delivered by
146 // the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded.
147 TEST_F(StyledTextFieldTest, ResetFieldEditorLeftMargin) {
148 const CGFloat kLeftMargin = 20;
150 // Start the cell off with a non-zero left margin.
151 [cell_ setLeftMargin:kLeftMargin];
152 [cell_ setRightMargin:0];
154 // Capture the editor frame resulting from the standard focus machinery.
155 [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
156 const NSRect baseEditorFrame(EditorFrame());
158 // Clearing the margin should result in a strictly larger editor frame.
159 [cell_ setLeftMargin:0];
160 [field_ resetFieldEditorFrameIfNeeded];
161 EXPECT_NSNE(baseEditorFrame, EditorFrame());
162 EXPECT_TRUE(NSContainsRect(EditorFrame(), baseEditorFrame));
164 // Setting the same margin and using -resetFieldEditorFrameIfNeeded should
165 // result in the same frame as the standard focus machinery.
166 [cell_ setLeftMargin:kLeftMargin];
167 [field_ resetFieldEditorFrameIfNeeded];
168 EXPECT_NSEQ(baseEditorFrame, EditorFrame());
171 // Test that the field editor gets the same bounds when focus is delivered by
172 // the standard focusing machinery, or by -resetFieldEditorFrameIfNeeded.
173 TEST_F(StyledTextFieldTest, ResetFieldEditorRightMargin) {
174 const CGFloat kRightMargin = 20;
176 // Start the cell off with a non-zero right margin.
177 [cell_ setLeftMargin:0];
178 [cell_ setRightMargin:kRightMargin];
180 // Capture the editor frame resulting from the standard focus machinery.
181 [test_window() makePretendKeyWindowAndSetFirstResponder:field_];
182 const NSRect baseEditorFrame(EditorFrame());
184 // Clearing the margin should result in a strictly larger editor frame.
185 [cell_ setRightMargin:0];
186 [field_ resetFieldEditorFrameIfNeeded];
187 EXPECT_NSNE(baseEditorFrame, EditorFrame());
188 EXPECT_TRUE(NSContainsRect(EditorFrame(), baseEditorFrame));
190 // Setting the same margin and using -resetFieldEditorFrameIfNeeded should
191 // result in the same frame as the standard focus machinery.
192 [cell_ setRightMargin:kRightMargin];
193 [field_ resetFieldEditorFrameIfNeeded];
194 EXPECT_NSEQ(baseEditorFrame, EditorFrame());