Home | History | Annotate | Download | only in cocoa
      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