Index: chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm |
diff --git a/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..63f74695aea21a08eaf43881fe539ce94b0cf64b |
--- /dev/null |
+++ b/chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm |
@@ -0,0 +1,192 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h" |
+ |
+#include "base/memory/scoped_nsobject.h" |
+#include "base/utf_string_conversions.h" |
+#include "chrome/browser/profiles/fake_profile_info_interface.h" |
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" |
+#import "chrome/browser/ui/cocoa/hyperlink_button_cell.h" |
+#include "chrome/common/chrome_notification_types.h" |
+#include "content/common/notification_service.h" |
+#include "testing/gtest_mac.h" |
+ |
+class FakeBridge : public AvatarMenuModelObserver { |
+ public: |
+ void OnAvatarMenuModelChanged(AvatarMenuModel* model) OVERRIDE {} |
+}; |
+ |
+class AvatarMenuBubbleControllerTest : public CocoaTest { |
+ public: |
+ virtual void SetUp() { |
+ info_.reset(new FakeProfileInfo); |
+ |
+ profile1_.reset( |
+ new AvatarMenuModel::Item(0, FakeProfileInfo::GetTestImage())); |
+ profile1_->name = ASCIIToUTF16("Test 1"); |
+ info()->mock_profiles()->push_back(profile1_.get()); |
+ |
+ profile2_.reset( |
+ new AvatarMenuModel::Item(1, FakeProfileInfo::GetTestImage())); |
+ profile2_->name = ASCIIToUTF16("Test 2"); |
+ info()->mock_profiles()->push_back(profile2_.get()); |
+ |
+ bridge_ = new FakeBridge; |
+ model_ = new AvatarMenuModel(info(), bridge(), NULL); |
+ |
+ NSRect frame = [test_window() frame]; |
+ NSPoint point = NSMakePoint(NSMidX(frame), NSMidY(frame)); |
+ controller_ = |
+ [[AvatarMenuBubbleController alloc] initWithModel:model() |
+ bridge:bridge() |
+ parentWindow:test_window() |
+ anchoredAt:point]; |
+ } |
+ |
+ FakeProfileInfo* info() { return info_.get(); } |
+ AvatarMenuBubbleController* controller() { return controller_; } |
+ AvatarMenuModel* model() { return model_; } |
+ FakeBridge* bridge() { return bridge_; } |
+ |
+ private: |
+ scoped_ptr<AvatarMenuModel::Item> profile1_; |
+ scoped_ptr<AvatarMenuModel::Item> profile2_; |
+ |
+ scoped_ptr<FakeProfileInfo> info_; |
+ |
+ // Weak; releases self. |
+ AvatarMenuBubbleController* controller_; |
+ |
+ // Weak; owned by |controller_|. |
+ AvatarMenuModel* model_; |
+ FakeBridge* bridge_; |
+}; |
+ |
+TEST_F(AvatarMenuBubbleControllerTest, InitialLayout) { |
+ [controller() showWindow:nil]; |
+ |
+ // Two profiles means two item views and the new button. |
+ NSView* contents = [[controller() window] contentView]; |
+ EXPECT_EQ(3U, [[contents subviews] count]); |
+ |
+ // Loop over the itmes and match the viewController views to subviews. |
+ NSMutableArray* subviews = |
+ [NSMutableArray arrayWithArray:[contents subviews]]; |
+ for (AvatarMenuItemController* viewController in [controller() items]) { |
+ for (NSView* subview in subviews) { |
+ if ([viewController view] == subview) { |
+ [subviews removeObject:subview]; |
+ break; |
+ } |
+ } |
+ } |
+ |
+ // The one remaining subview should be the new user button. |
+ EXPECT_EQ(1U, [subviews count]); |
+ |
+ NSButton* newUser = [subviews lastObject]; |
+ ASSERT_TRUE([newUser isKindOfClass:[NSButton class]]); |
+ |
+ EXPECT_EQ(@selector(newProfile:), [newUser action]); |
+ EXPECT_EQ(controller(), [newUser target]); |
+ EXPECT_TRUE([[newUser cell] isKindOfClass:[HyperlinkButtonCell class]]); |
+ |
+ [controller() close]; |
+} |
+ |
+TEST_F(AvatarMenuBubbleControllerTest, PerformLayout) { |
+ [controller() showWindow:nil]; |
+ |
+ NSView* contents = [[controller() window] contentView]; |
+ EXPECT_EQ(3U, [[contents subviews] count]); |
+ |
+ scoped_nsobject<NSMutableArray> oldItems([[controller() items] copy]); |
+ |
+ // Now create a new profile and notify the delegate. |
+ AvatarMenuModel::Item profile3(2, FakeProfileInfo::GetTestImage()); |
+ profile3.name = ASCIIToUTF16("Test 3"); |
+ info()->mock_profiles()->push_back(&profile3); |
+ |
+ NotificationService::current()->Notify( |
+ chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED, |
+ NotificationService::AllSources(), |
+ NotificationService::NoDetails()); |
+ |
+ // Testing the bridge is not worth the effort... |
+ [controller() performLayout]; |
+ |
+ EXPECT_EQ(4U, [[contents subviews] count]); |
+ |
+ // Make sure that none of the old items exit. |
+ NSArray* newItems = [controller() items]; |
+ for (AvatarMenuItemController* oldVC in oldItems.get()) { |
+ EXPECT_FALSE([newItems containsObject:oldVC]); |
+ EXPECT_FALSE([[contents subviews] containsObject:[oldVC view]]); |
+ } |
+ |
+ [controller() close]; |
+} |
+ |
+TEST_F(AvatarMenuBubbleControllerTest, HighlightForEventType) { |
+ scoped_nsobject<AvatarMenuItemController> item( |
+ [[AvatarMenuItemController alloc] initWithModelIndex:0 |
+ menuController:nil]); |
+ NSTextField* field = [item nameField]; |
+ // Test non-active states first. |
+ [[item activeView] setHidden:YES]; |
+ |
+ NSColor* startColor = [NSColor controlTextColor]; |
+ NSColor* upColor = nil; |
+ NSColor* downColor = nil; |
+ NSColor* enterColor = nil; |
+ NSColor* exitColor = nil; |
+ |
+ EXPECT_NSEQ(startColor, field.textColor); |
+ |
+ // The controller does this in |-performLayout|. |
+ [item highlightForEventType:NSLeftMouseUp]; |
+ EXPECT_NSNE(startColor, field.textColor); |
+ startColor = field.textColor; |
+ |
+ [item highlightForEventType:NSLeftMouseDown]; |
+ downColor = field.textColor; |
+ |
+ [item highlightForEventType:NSMouseEntered]; |
+ enterColor = field.textColor; |
+ |
+ [item highlightForEventType:NSMouseExited]; |
+ exitColor = field.textColor; |
+ |
+ [item highlightForEventType:NSLeftMouseUp]; |
+ upColor = field.textColor; |
+ |
+ // Use transitivity to determine that all colors for each state are correct. |
+ EXPECT_NSEQ(startColor, upColor); |
+ EXPECT_NSEQ(upColor, exitColor); |
+ EXPECT_NSEQ(downColor, enterColor); |
+ EXPECT_NSNE(enterColor, exitColor); |
+ |
+ // Make the item "active" and re-test. |
+ [[item activeView] setHidden:NO]; |
+ [item highlightForEventType:NSLeftMouseUp]; |
+ EXPECT_NSNE(startColor, field.textColor); |
+ upColor = field.textColor; |
+ |
+ [item highlightForEventType:NSLeftMouseDown]; |
+ EXPECT_NSNE(downColor, field.textColor); |
+ downColor = field.textColor; |
+ |
+ [item highlightForEventType:NSMouseEntered]; |
+ EXPECT_NSNE(enterColor, field.textColor); |
+ enterColor = field.textColor; |
+ |
+ [item highlightForEventType:NSMouseExited]; |
+ EXPECT_NSNE(exitColor, field.textColor); |
+ exitColor = field.textColor; |
+ |
+ EXPECT_NSEQ(upColor, exitColor); |
+ EXPECT_NSEQ(downColor, enterColor); |
+ EXPECT_NSNE(upColor, downColor); |
+} |