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