chromium/ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator_unittest.mm

// Copyright 2023 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/ntp/ui_bundled/feed_menu_coordinator.h"

#import "base/apple/foundation_util.h"
#import "base/test/scoped_feature_list.h"
#import "components/feed/core/v2/public/ios/pref_names.h"
#import "components/prefs/pref_service.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.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/features/features.h"
#import "ios/chrome/browser/signin/model/authentication_service.h"
#import "ios/chrome/browser/signin/model/authentication_service_factory.h"
#import "ios/chrome/browser/signin/model/fake_authentication_service_delegate.h"
#import "ios/chrome/browser/signin/model/fake_system_identity.h"
#import "ios/chrome/browser/signin/model/fake_system_identity_manager.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
#import "ios/chrome/test/scoped_key_window.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gtest_mac.h"
#import "testing/platform_test.h"
#import "ui/base/l10n/l10n_util_mac.h"
#import "ui/strings/grit/ui_strings.h"

namespace {

// Contains the attributes of a UIAction that will be checked.
struct ExpectedAction {
  int title;

  // Expects the attributes of `action` to match this `ExpectedAction`.
  void ExpectMatch(UIAction* action) {
    NSString* expected_title = l10n_util::GetNSString(this->title);
    EXPECT_NSEQ(action.title, expected_title);
  }
};

}  // namespace

// Test fixture for testing FeedMenuCoordinator class.
class FeedMenuCoordinatorTest : public PlatformTest {
 protected:
  FeedMenuCoordinatorTest() {
    TestChromeBrowserState::Builder test_cbs_builder;
    test_cbs_builder.AddTestingFactory(
        AuthenticationServiceFactory::GetInstance(),
        AuthenticationServiceFactory::GetDefaultFactory());
    browser_state_ = std::move(test_cbs_builder).Build();
    browser_ = std::make_unique<TestBrowser>(browser_state_.get());
    AuthenticationServiceFactory::CreateAndInitializeForBrowserState(
        browser_state_.get(),
        std::make_unique<FakeAuthenticationServiceDelegate>());

    base_view_controller_ = [[UIViewController alloc] init];
    [scoped_key_window_.Get() setRootViewController:base_view_controller_];
    button_ = [[UIButton alloc] init];
    [base_view_controller_.view addSubview:button_];
    CreateCoordinator();
    [coordinator_ start];
  }

  ~FeedMenuCoordinatorTest() override { [coordinator_ stop]; }

  // Creates an instance of the coordinator.
  void CreateCoordinator() {
    coordinator_ = [[FeedMenuCoordinator alloc]
        initWithBaseViewController:base_view_controller_
                           browser:browser_.get()];
  }

  // Enables or disables the feed in prefs.
  void SetFeedEnabled(bool enabled) {
    PrefService* prefs = browser_state_->GetPrefs();
    prefs->SetBoolean(feed::prefs::kArticlesListVisible, enabled);
  }

  // Fakes a sign-in with a fake identity.
  void SignInFakeIdentity() {
    FakeSystemIdentity* identity = [FakeSystemIdentity fakeIdentity1];
    FakeSystemIdentityManager* system_identity_manager =
        FakeSystemIdentityManager::FromSystemIdentityManager(
            GetApplicationContext()->GetSystemIdentityManager());
    system_identity_manager->AddIdentity(identity);
    AuthenticationService* auth_service =
        AuthenticationServiceFactory::GetForBrowserState(browser_state_.get());
    auth_service->SignIn(identity,
                         signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN);
  }

  // Expects that the action attributes match the given `items`.
  void ExpectActions(std::vector<ExpectedAction> expected) {
    NSArray<UIAction*>* actions =
        static_cast<NSArray<UIAction*>*>(button_.menu.children);
    ASSERT_EQ(actions.count, expected.size());
    int index = 0;
    for (UIAction* action in actions) {
      expected[index].ExpectMatch(action);
      index++;
    }
  }

  web::WebTaskEnvironment task_environment_;
  IOSChromeScopedTestingLocalState scoped_testing_local_state_;
  std::unique_ptr<TestChromeBrowserState> browser_state_;
  std::unique_ptr<TestBrowser> browser_;
  base::test::ScopedFeatureList scoped_feature_list_;
  ScopedKeyWindow scoped_key_window_;
  UIViewController* base_view_controller_;
  UIButton* button_;
  FeedMenuCoordinator* coordinator_;
};

#pragma mark - Tests

// Tests the menu actions when the feed is turned on.
TEST_F(FeedMenuCoordinatorTest, FeedOn) {
  SetFeedEnabled(true);
  [coordinator_ configureManagementMenu:button_];
  ExpectActions({{IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM},
                 {IDS_IOS_DISCOVER_FEED_MENU_LEARN_MORE_ITEM}});
}

// Tests the menu actions when the feed is turned off.
TEST_F(FeedMenuCoordinatorTest, FeedOff) {
  SetFeedEnabled(false);
  [coordinator_ configureManagementMenu:button_];
  ExpectActions({{IDS_IOS_DISCOVER_FEED_MENU_TURN_ON_ITEM},
                 {IDS_IOS_DISCOVER_FEED_MENU_LEARN_MORE_ITEM}});
}

// Tests the menu actions when the user is signed-in.
TEST_F(FeedMenuCoordinatorTest, SignedIn) {
  SetFeedEnabled(true);
  SignInFakeIdentity();
  [coordinator_ configureManagementMenu:button_];
  ExpectActions({{IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM},
                 {IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ITEM},
                 {IDS_IOS_DISCOVER_FEED_MENU_LEARN_MORE_ITEM}});
}