chromium/ios/chrome/browser/ui/sharing/qr_generator/qr_generator_coordinator_unittest.mm

// Copyright 2020 The Chromium Authors
// 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/sharing/qr_generator/qr_generator_coordinator.h"

#import "base/apple/foundation_util.h"
#import "base/test/task_environment.h"
#import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/chrome/browser/shared/public/commands/bookmarks_commands.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/commands/help_commands.h"
#import "ios/chrome/browser/shared/public/commands/qr_generation_commands.h"
#import "ios/chrome/browser/ui/sharing/qr_generator/qr_generator_view_controller.h"
#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
#import "ios/chrome/common/ui/elements/popover_label_view_controller.h"
#import "ios/chrome/test/scoped_key_window.h"
#import "net/base/apple/url_conversions.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "url/gurl.h"

class QRGeneratorCoordinatorTest : public PlatformTest {
 protected:
  QRGeneratorCoordinatorTest() {
    browser_state_ = TestChromeBrowserState::Builder().Build();
    browser_ = std::make_unique<TestBrowser>(browser_state_.get());
    base_view_controller_ = [[UIViewController alloc] init];
    [scoped_key_window_.Get() setRootViewController:base_view_controller_];
  }

  void SetUp() override {
    mock_qr_generation_commands_handler_ =
        OCMStrictProtocolMock(@protocol(QRGenerationCommands));

    [browser_->GetCommandDispatcher()
        startDispatchingToTarget:OCMStrictProtocolMock(
                                     @protocol(BookmarksCommands))
                     forProtocol:@protocol(BookmarksCommands)];
    [browser_->GetCommandDispatcher()
        startDispatchingToTarget:OCMStrictProtocolMock(@protocol(HelpCommands))
                     forProtocol:@protocol(HelpCommands)];

    coordinator_ = [[QRGeneratorCoordinator alloc]
        initWithBaseViewController:base_view_controller_
                           browser:browser_.get()
                             title:@"Does not matter"
                               URL:GURL("https://www.google.com/")
                           handler:(id<QRGenerationCommands>)
                                       mock_qr_generation_commands_handler_];
  }

  base::test::TaskEnvironment task_environment_;
  std::unique_ptr<TestChromeBrowserState> browser_state_;
  std::unique_ptr<TestBrowser> browser_;
  id mock_qr_generation_commands_handler_;
  ScopedKeyWindow scoped_key_window_;
  UIViewController* base_view_controller_;
  QRGeneratorCoordinator* coordinator_;
};

// Tests that a Done button gets added to the navigation bar, and its action
// dispatches the right command.
TEST_F(QRGeneratorCoordinatorTest, Done_DispatchesCommand) {
  // Set-up mocked handler.
  [[mock_qr_generation_commands_handler_ expect] hideQRCode];

  // Check and start coordinator.
  ASSERT_EQ(base_view_controller_, coordinator_.baseViewController);
  ASSERT_FALSE(base_view_controller_.presentedViewController);

  [coordinator_ start];

  ASSERT_TRUE(base_view_controller_.presentedViewController);
  ASSERT_TRUE([base_view_controller_.presentedViewController
      isKindOfClass:[QRGeneratorViewController class]]);

  QRGeneratorViewController* viewController =
      base::apple::ObjCCastStrict<QRGeneratorViewController>(
          base_view_controller_.presentedViewController);

  // Mimick click on done button.
  [viewController.actionHandler confirmationAlertDismissAction];

  // Callback should've gotten invoked.
  [mock_qr_generation_commands_handler_ verify];

  // Set-up mocks for "stop" function.
  id baseViewControllerMock = OCMPartialMock(base_view_controller_);
  [[baseViewControllerMock expect] dismissViewControllerAnimated:YES
                                                      completion:nil];

  [coordinator_ stop];

  // View controller dismissal must have gone through the root view controller.
  [baseViewControllerMock verify];
}

// Tests that tje primary action, share, intializes the activity service
// coordinator properly.
TEST_F(QRGeneratorCoordinatorTest, ShareAction) {
  [coordinator_ start];

  QRGeneratorViewController* viewController =
      base::apple::ObjCCastStrict<QRGeneratorViewController>(
          base_view_controller_.presentedViewController);

  id vcPartialMock = OCMPartialMock(viewController);
  [[vcPartialMock expect]
      presentViewController:[OCMArg checkWithBlock:^BOOL(
                                        UIViewController* givenVC) {
        return [givenVC isKindOfClass:[UIActivityViewController class]];
      }]
                   animated:YES
                 completion:nil];

  // Mimic tap on share button.
  [viewController.actionHandler confirmationAlertPrimaryAction];

  [vcPartialMock verify];
}

// Tests that a popover is properly created and shown when the user taps on
// the learn more button.
TEST_F(QRGeneratorCoordinatorTest, LearnMore) {
  [coordinator_ start];

  QRGeneratorViewController* viewController =
      base::apple::ObjCCastStrict<QRGeneratorViewController>(
          base_view_controller_.presentedViewController);

  __block PopoverLabelViewController* popoverViewController;
  id vcPartialMock = OCMPartialMock(viewController);
  [[vcPartialMock expect]
      presentViewController:[OCMArg checkWithBlock:^BOOL(
                                        UIViewController* givenVC) {
        if ([givenVC isKindOfClass:[PopoverLabelViewController class]]) {
          popoverViewController =
              base::apple::ObjCCastStrict<PopoverLabelViewController>(givenVC);
          return YES;
        }
        return NO;
      }]
                   animated:YES
                 completion:nil];

  // Mimic tap on help button.
  [viewController.actionHandler confirmationAlertLearnMoreAction];

  [vcPartialMock verify];
  EXPECT_TRUE(popoverViewController);

  EXPECT_EQ(viewController.helpButton,
            popoverViewController.popoverPresentationController.barButtonItem);
  EXPECT_EQ(UIPopoverArrowDirectionUp,
            popoverViewController.popoverPresentationController
                .permittedArrowDirections);
}