Index: chrome/browser/cocoa/status_bubble_mac_unittest.mm |
=================================================================== |
--- chrome/browser/cocoa/status_bubble_mac_unittest.mm (revision 28701) |
+++ chrome/browser/cocoa/status_bubble_mac_unittest.mm (working copy) |
@@ -6,14 +6,16 @@ |
#include "base/scoped_nsobject.h" |
#include "base/scoped_ptr.h" |
+#import "chrome/browser/cocoa/bubble_view.h" |
+#import "chrome/browser/cocoa/browser_test_helper.h" |
#import "chrome/browser/cocoa/cocoa_test_helper.h" |
-#include "chrome/browser/cocoa/status_bubble_mac.h" |
+#import "chrome/browser/cocoa/status_bubble_mac.h" |
#include "googleurl/src/gurl.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "testing/platform_test.h" |
#import "third_party/GTM/AppKit/GTMTheme.h" |
-@interface StatusBubbleMacTestWindowDelegate : NSObject <GTMThemeDelegate>; |
+@interface StatusBubbleMacTestWindowDelegate : NSObject <GTMThemeDelegate> |
@end |
@implementation StatusBubbleMacTestWindowDelegate |
- (GTMTheme*)gtm_themeForWindow:(NSWindow*)window { |
@@ -25,17 +27,47 @@ |
} |
@end |
+// The test delegate records all of the status bubble object's state |
+// transitions. |
+@interface StatusBubbleMacTestDelegate : NSObject { |
+ @private |
+ std::vector<StatusBubbleMac::StatusBubbleState> states_; |
+} |
+- (void)statusBubbleWillEnterState:(StatusBubbleMac::StatusBubbleState)state; |
+@end |
+@implementation StatusBubbleMacTestDelegate |
+- (void)statusBubbleWillEnterState:(StatusBubbleMac::StatusBubbleState)state { |
+ states_.push_back(state); |
+} |
+- (std::vector<StatusBubbleMac::StatusBubbleState>*)states { |
+ return &states_; |
+} |
+@end |
+ |
class StatusBubbleMacTest : public PlatformTest { |
public: |
StatusBubbleMacTest() { |
NSWindow* window = cocoa_helper_.window(); |
- bubble_.reset(new StatusBubbleMac(window, nil)); |
+ EXPECT_TRUE(window); |
+ delegate_.reset([[StatusBubbleMacTestDelegate alloc] init]); |
+ EXPECT_TRUE(delegate_.get()); |
+ bubble_.reset(new StatusBubbleMac(window, delegate_)); |
EXPECT_TRUE(bubble_.get()); |
+ |
+ // Turn off delays and transitions for test mode. This doesn't just speed |
+ // things along, it's actually required to get StatusBubbleMac to behave |
+ // synchronously, because the tests here don't know how to wait for |
+ // results. This allows these tests to be much more complete with a |
+ // minimal loss of coverage and without any heinous rearchitecting. |
+ bubble_->immediate_ = true; |
+ |
EXPECT_FALSE(bubble_->window_); // lazily creates window |
} |
bool IsVisible() { |
- return [bubble_->window_ isVisible] ? true: false; |
+ if (![bubble_->window_ isVisible]) |
+ return false; |
+ return [bubble_->window_ alphaValue] > 0.0; |
} |
NSString* GetText() { |
return bubble_->status_text_; |
@@ -43,13 +75,31 @@ |
NSString* GetURLText() { |
return bubble_->url_text_; |
} |
+ NSString* GetBubbleViewText() { |
+ BubbleView* bubbleView = [bubble_->window_ contentView]; |
+ return [bubbleView content]; |
+ } |
NSWindow* GetWindow() { |
return bubble_->window_; |
} |
NSWindow* GetParent() { |
return bubble_->parent_; |
} |
+ StatusBubbleMac::StatusBubbleState GetState() { |
+ return bubble_->state_; |
+ } |
+ void SetState(StatusBubbleMac::StatusBubbleState state) { |
+ bubble_->SetState(state); |
+ } |
+ std::vector<StatusBubbleMac::StatusBubbleState>* States() { |
+ return [delegate_ states]; |
+ } |
+ StatusBubbleMac::StatusBubbleState StateAt(int index) { |
+ return (*States())[index]; |
+ } |
CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... |
+ BrowserTestHelper browser_helper_; |
+ scoped_nsobject<StatusBubbleMacTestDelegate> delegate_; |
scoped_ptr<StatusBubbleMac> bubble_; |
}; |
@@ -74,7 +124,6 @@ |
// Hide it |
bubble_->SetStatus(L""); |
EXPECT_FALSE(IsVisible()); |
- EXPECT_FALSE(GetText()); |
} |
TEST_F(StatusBubbleMacTest, SetURL) { |
@@ -106,6 +155,253 @@ |
EXPECT_FALSE(IsVisible()); |
} |
+// Test the "main"/"backup" behavior in StatusBubbleMac::SetText(). |
+TEST_F(StatusBubbleMacTest, SetStatusAndURL) { |
+ EXPECT_FALSE(IsVisible()); |
+ bubble_->SetStatus(L"Status"); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]); |
+ bubble_->SetURL(GURL("http://www.nytimes.com/"), L""); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]); |
+ bubble_->SetURL(GURL(), L""); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]); |
+ bubble_->SetStatus(L""); |
+ EXPECT_FALSE(IsVisible()); |
+ bubble_->SetURL(GURL("http://www.nytimes.com/"), L""); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]); |
+ bubble_->SetStatus(L"Status"); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"Status"]); |
+ bubble_->SetStatus(L""); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_TRUE([GetBubbleViewText() isEqualToString:@"http://www.nytimes.com/"]); |
+ bubble_->SetURL(GURL(), L""); |
+ EXPECT_FALSE(IsVisible()); |
+} |
+ |
+// Test that the status bubble goes through the correct delay and fade states. |
+// The delay and fade duration are simulated and not actually experienced |
+// during the test because StatusBubbleMacTest sets immediate_ mode. |
+TEST_F(StatusBubbleMacTest, StateTransitions) { |
+ // First, some sanity |
+ |
+ EXPECT_FALSE(IsVisible()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ |
+ bubble_->SetStatus(L""); |
+ EXPECT_FALSE(IsVisible()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_TRUE(States()->empty()); // no change from initial kBubbleHidden state |
+ |
+ // Next, a few ordinary cases |
+ |
+ // Test StartShowing from kBubbleHidden |
+ bubble_->SetStatus(L"Status"); |
+ EXPECT_TRUE(IsVisible()); |
+ // Check GetState before checking States to make sure that all state |
+ // transitions have been flushed to States. |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, GetState()); |
+ EXPECT_EQ(3u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShowingTimer, StateAt(0)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShowingFadeIn, StateAt(1)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, StateAt(2)); |
+ |
+ // Test StartShowing from kBubbleShown with the same message |
+ States()->clear(); |
+ bubble_->SetStatus(L"Status"); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, GetState()); |
+ EXPECT_TRUE(States()->empty()); |
+ |
+ // Test StartShowing from kBubbleShown with a different message |
+ bubble_->SetStatus(L"New Status"); |
+ EXPECT_TRUE(IsVisible()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, GetState()); |
+ EXPECT_TRUE(States()->empty()); |
+ |
+ // Test StartHiding from kBubbleShown |
+ bubble_->SetStatus(L""); |
+ EXPECT_FALSE(IsVisible()); |
+ // Check GetState before checking States to make sure that all state |
+ // transitions have been flushed to States. |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(3u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidingTimer, StateAt(0)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidingFadeOut, StateAt(1)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(2)); |
+ |
+ // Test StartHiding from kBubbleHidden |
+ States()->clear(); |
+ bubble_->SetStatus(L""); |
+ EXPECT_FALSE(IsVisible()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_TRUE(States()->empty()); |
+ |
+ // Now, the edge cases |
+ |
+ // Test StartShowing from kBubbleShowingTimer |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleShowingTimer); |
+ [GetWindow() setAlphaValue:0.0]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L"Status"); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, GetState()); |
+ EXPECT_EQ(2u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShowingFadeIn, StateAt(0)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, StateAt(1)); |
+ |
+ // Test StartShowing from kBubbleShowingFadeIn |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleShowingFadeIn); |
+ [GetWindow() setAlphaValue:0.5]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L"Status"); |
+ // The actual state values can't be tested in immediate_ mode because |
+ // the window wasn't actually fading in. Without immediate_ mode, |
+ // expect kBubbleShown. |
+ bubble_->SetStatus(L""); // Go back to a deterministic state. |
+ |
+ // Test StartShowing from kBubbleHidingTimer |
+ bubble_->SetStatus(L""); |
+ SetState(StatusBubbleMac::kBubbleHidingTimer); |
+ [GetWindow() setAlphaValue:1.0]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L"Status"); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, GetState()); |
+ EXPECT_EQ(1u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, StateAt(0)); |
+ |
+ // Test StartShowing from kBubbleHidingFadeOut |
+ bubble_->SetStatus(L""); |
+ SetState(StatusBubbleMac::kBubbleHidingFadeOut); |
+ [GetWindow() setAlphaValue:0.5]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L"Status"); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, GetState()); |
+ EXPECT_EQ(2u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShowingFadeIn, StateAt(0)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleShown, StateAt(1)); |
+ |
+ // Test StartHiding from kBubbleShowingTimer |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleShowingTimer); |
+ [GetWindow() setAlphaValue:0.0]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L""); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(1u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(0)); |
+ |
+ // Test StartHiding from kBubbleShowingFadeIn |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleShowingFadeIn); |
+ [GetWindow() setAlphaValue:0.5]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L""); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(2u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidingFadeOut, StateAt(0)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(1)); |
+ |
+ // Test StartHiding from kBubbleHidingTimer |
+ bubble_->SetStatus(L""); |
+ SetState(StatusBubbleMac::kBubbleHidingTimer); |
+ [GetWindow() setAlphaValue:1.0]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L""); |
+ // The actual state values can't be tested in immediate_ mode because |
+ // the timer wasn't actually running. Without immediate_ mode, expect |
+ // kBubbleHidingFadeOut and kBubbleHidden. |
+ bubble_->SetStatus(L"Status"); // Go back to a deterministic state. |
+ |
+ // Test StartHiding from kBubbleHidingFadeOut |
+ bubble_->SetStatus(L""); |
+ SetState(StatusBubbleMac::kBubbleHidingFadeOut); |
+ [GetWindow() setAlphaValue:0.5]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->SetStatus(L""); |
+ // The actual state values can't be tested in immediate_ mode because |
+ // the window wasn't actually fading out. Without immediate_ mode, expect |
+ // kBubbleHidden. |
+ bubble_->SetStatus(L"Status"); // Go back to a deterministic state. |
+ |
+ // Test Hide from kBubbleHidden |
+ bubble_->SetStatus(L""); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->Hide(); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_TRUE(States()->empty()); |
+ |
+ // Test Hide from kBubbleShowingTimer |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleShowingTimer); |
+ [GetWindow() setAlphaValue:0.0]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->Hide(); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(1u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(0)); |
+ |
+ // Test Hide from kBubbleShowingFadeIn |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleShowingFadeIn); |
+ [GetWindow() setAlphaValue:0.5]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->Hide(); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(2u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidingFadeOut, StateAt(0)); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(1)); |
+ |
+ // Test Hide from kBubbleShown |
+ bubble_->SetStatus(L"Status"); |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->Hide(); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(1u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(0)); |
+ |
+ // Test Hide from kBubbleHidingTimer |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleHidingTimer); |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->Hide(); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(1u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(0)); |
+ |
+ // Test Hide from kBubbleHidingFadeOut |
+ bubble_->SetStatus(L"Status"); |
+ SetState(StatusBubbleMac::kBubbleHidingFadeOut); |
+ [GetWindow() setAlphaValue:0.5]; |
+ States()->clear(); |
+ EXPECT_TRUE(States()->empty()); |
+ bubble_->Hide(); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, GetState()); |
+ EXPECT_EQ(1u, States()->size()); |
+ EXPECT_EQ(StatusBubbleMac::kBubbleHidden, StateAt(0)); |
+} |
+ |
TEST_F(StatusBubbleMacTest, MouseMove) { |
// TODO(pinkerton): Not sure what to do here since it relies on |
// [NSEvent currentEvent] and the current mouse location. |