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