Index: ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm |
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8bebde7863078f195870d89695698f8f6e7d39c0 |
--- /dev/null |
+++ b/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm |
@@ -0,0 +1,211 @@ |
+// Copyright 2015 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 "ios/chrome/browser/ui/dialogs/dialog_presenter.h" |
+ |
+#import "base/mac/scoped_nsobject.h" |
+#include "base/time/time.h" |
+#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" |
+#include "ios/web/public/test/test_web_state.h" |
+#include "ios/web/public/web_state/web_state_observer.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "testing/gtest_mac.h" |
+#include "testing/platform_test.h" |
+#include "url/gurl.h" |
+ |
+namespace { |
+// TestWebState subclass that supports the WebStateDestroyed() callback for a |
+// single observer. |
+class DialogPresenterTestWebState : public web::TestWebState { |
+ public: |
+ DialogPresenterTestWebState() : web::TestWebState(), observer_(nullptr) {} |
+ ~DialogPresenterTestWebState() override { |
+ if (observer_) |
+ observer_->WebStateDestroyed(); |
+ } |
+ |
+ protected: |
+ // WebState overrides. |
+ void AddObserver(web::WebStateObserver* observer) override { |
+ // Currently, only one observer is supported. |
+ ASSERT_EQ(observer_, nullptr); |
+ observer_ = observer; |
+ } |
+ |
+ private: |
+ web::WebStateObserver* observer_; |
+}; |
+} // namespace |
+ |
+@interface TestDialogPresenterDelegate : NSObject<DialogPresenterDelegate> { |
+ std::vector<web::WebState*> _presentedWebStates; |
+} |
+// The web states for the dialogs that have been presented. |
+@property(nonatomic, readonly) std::vector<web::WebState*> presentedWebStates; |
+@end |
+ |
+@implementation TestDialogPresenterDelegate |
+@synthesize presenting = _presenting; |
+ |
+- (std::vector<web::WebState*>)presentedWebStates { |
+ return _presentedWebStates; |
+} |
+ |
+- (void)dialogPresenter:(DialogPresenter*)presenter |
+ willShowDialogForWebState:(web::WebState*)webState { |
+ _presentedWebStates.push_back(webState); |
+} |
+ |
+@end |
+ |
+class DialogPresenterTest : public PlatformTest { |
+ protected: |
+ DialogPresenterTest() |
+ : delegate_([[TestDialogPresenterDelegate alloc] init]), |
+ viewController_([[UIViewController alloc] init]), |
+ presenter_([[DialogPresenter alloc] initWithDelegate:delegate_ |
+ presentingViewController:viewController_]) { |
+ [presenter_ setActive:YES]; |
+ } |
+ ~DialogPresenterTest() override { |
+ [[presenter_ presentedDialogCoordinator] stop]; |
+ } |
+ |
+ TestDialogPresenterDelegate* delegate() { return delegate_; } |
+ UIViewController* viewController() { return viewController_; } |
+ DialogPresenter* presenter() { return presenter_; } |
+ |
+ private: |
+ base::scoped_nsobject<TestDialogPresenterDelegate> delegate_; |
+ base::scoped_nsobject<UIViewController> viewController_; |
+ base::scoped_nsobject<DialogPresenter> presenter_; |
+}; |
+ |
+// Tests that a dialog was successfully shown and that the delegate was notified |
+// with the correct context. |
+TEST_F(DialogPresenterTest, SimpleTest) { |
+ DialogPresenterTestWebState webState; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"" |
+ requestURL:GURL() |
+ webState:&webState |
+ completionHandler:nil]; |
+ EXPECT_EQ(1U, delegate().presentedWebStates.size()); |
+ EXPECT_EQ(&webState, delegate().presentedWebStates.front()); |
+} |
+ |
+// Tests that multiple JavaScript dialogs are queued |
+TEST_F(DialogPresenterTest, QueueTest) { |
+ // Tests that the dialog for |webState1| has been shown. |
+ DialogPresenterTestWebState webState1; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"" |
+ requestURL:GURL() |
+ webState:&webState1 |
+ completionHandler:nil]; |
+ EXPECT_EQ(1U, delegate().presentedWebStates.size()); |
+ EXPECT_EQ(&webState1, delegate().presentedWebStates.front()); |
+ // Attempt to present another dialog for |webState2|, and verify that only |
+ // |webState2| has been shown. |
+ DialogPresenterTestWebState webState2; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"" |
+ requestURL:GURL() |
+ webState:&webState2 |
+ completionHandler:nil]; |
+ EXPECT_EQ(1U, delegate().presentedWebStates.size()); |
+ EXPECT_EQ(&webState1, delegate().presentedWebStates.front()); |
+ // Dismiss the dialog for |webState1| and call the confirm handler to trigger |
+ // showing the dialog for |webState2|. |
+ [presenter().presentedDialogCoordinator stop]; |
+ [presenter() |
+ buttonWasTappedForCoordinator:presenter().presentedDialogCoordinator]; |
+ EXPECT_EQ(2U, delegate().presentedWebStates.size()); |
+ EXPECT_EQ(&webState1, delegate().presentedWebStates.front()); |
+ EXPECT_EQ(&webState2, delegate().presentedWebStates.back()); |
+} |
+ |
+// Tests that cancelling a queued JavaScript dialog will call its completion |
+// handler. |
+TEST_F(DialogPresenterTest, CancelTest) { |
+ // Show a dialog for |webState1| and enqueue a dialog for |webState2|. |
+ DialogPresenterTestWebState webState1; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"" |
+ requestURL:GURL() |
+ webState:&webState1 |
+ completionHandler:nil]; |
+ DialogPresenterTestWebState webState2; |
+ __block BOOL completion_called = NO; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"" |
+ requestURL:GURL() |
+ webState:&webState2 |
+ completionHandler:^() { |
+ completion_called = YES; |
+ }]; |
+ EXPECT_EQ(1U, delegate().presentedWebStates.size()); |
+ EXPECT_EQ(&webState1, delegate().presentedWebStates.front()); |
+ // Cancel the dialog for |webState2| and verify that |completion_called| was |
+ // reset. |
+ [presenter() cancelDialogForWebState:&webState2]; |
+ EXPECT_TRUE(completion_called); |
+} |
+ |
+// Tests that if the delegate is presenting, the alert is showed only when |
+// notified. |
+TEST_F(DialogPresenterTest, DelegatePresenting) { |
+ // Tests that the dialog is not shown if the delegate is presenting. |
+ DialogPresenterTestWebState webState1; |
+ delegate().presenting = YES; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"" |
+ requestURL:GURL() |
+ webState:&webState1 |
+ completionHandler:nil]; |
+ EXPECT_EQ(0U, delegate().presentedWebStates.size()); |
+ [presenter() tryToPresent]; |
+ EXPECT_EQ(0U, delegate().presentedWebStates.size()); |
+ |
+ // The delegate is not presenting anymore, the dialog is not shown yet. |
+ delegate().presenting = NO; |
+ EXPECT_EQ(0U, delegate().presentedWebStates.size()); |
+ |
+ // Notify the presenter that it can present. |
+ [presenter() tryToPresent]; |
+ EXPECT_EQ(1U, delegate().presentedWebStates.size()); |
+ EXPECT_EQ(&webState1, delegate().presentedWebStates.front()); |
+} |
+ |
+// Tests that cancelling all queued JavaScript dialogs will call all completion |
+// handlers. |
+TEST_F(DialogPresenterTest, CancelAllTest) { |
+ // Show a dialog for |context1| and enqueue a dialog for |context2| and |
+ // |context3|. |
+ DialogPresenterTestWebState webState1; |
+ __block BOOL completion1_called = NO; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"1" |
+ requestURL:GURL() |
+ webState:&webState1 |
+ completionHandler:^() { |
+ completion1_called = YES; |
+ }]; |
+ DialogPresenterTestWebState webState2; |
+ __block BOOL completion2_called = NO; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"2" |
+ requestURL:GURL() |
+ webState:&webState2 |
+ completionHandler:^() { |
+ completion2_called = YES; |
+ }]; |
+ DialogPresenterTestWebState webState3; |
+ __block BOOL completion3_called = NO; |
+ [presenter() runJavaScriptAlertPanelWithMessage:@"3" |
+ requestURL:GURL() |
+ webState:&webState3 |
+ completionHandler:^() { |
+ completion3_called = YES; |
+ }]; |
+ EXPECT_EQ(1U, delegate().presentedWebStates.size()); |
+ EXPECT_EQ(&webState1, delegate().presentedWebStates.front()); |
+ // Cancel all dialogs and verify that all |completion_called| were called. |
+ [presenter() cancelAllDialogs]; |
+ EXPECT_TRUE(completion1_called); |
+ EXPECT_TRUE(completion2_called); |
+ EXPECT_TRUE(completion3_called); |
+} |