chromium/ios/chrome/browser/mini_map/ui_bundled/mini_map_mediator_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/mini_map/ui_bundled/mini_map_mediator.h"

#import "base/ios/ios_util.h"
#import "base/test/scoped_feature_list.h"
#import "base/test/task_environment.h"
#import "components/sync_preferences/testing_pref_service_syncable.h"
#import "ios/chrome/browser/mini_map/ui_bundled/mini_map_mediator_delegate.h"
#import "ios/chrome/browser/shared/model/prefs/browser_prefs.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/web/common/features.h"
#import "testing/gmock/include/gmock/gmock.h"
#import "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"

class MiniMapMediatorTest : public PlatformTest {
 protected:
  MiniMapMediatorTest() {
    TestChromeBrowserState::Builder builder;
    builder.SetPrefService(CreatePrefService());
    browser_state_ = std::move(builder).Build();

    delegate_ = OCMStrictProtocolMock(@protocol(MiniMapMediatorDelegate));

    mediator_ =
        [[MiniMapMediator alloc] initWithPrefs:browser_state_->GetPrefs()
                                      webState:nullptr];
    mediator_.delegate = delegate_;
  }

  std::unique_ptr<sync_preferences::PrefServiceSyncable> CreatePrefService() {
    auto prefs =
        std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
    user_prefs::PrefRegistrySyncable* registry = prefs->registry();
    RegisterBrowserStatePrefs(registry);
    return prefs;
  }

  void TearDown() override {
    EXPECT_OCMOCK_VERIFY(delegate_);
    PlatformTest::TearDown();
  }

 protected:
  base::test::TaskEnvironment environment_;
  std::unique_ptr<TestChromeBrowserState> browser_state_;
  id delegate_;
  MiniMapMediator* mediator_;
};

// Tests that consent screen is not triggered if not needed.
TEST_F(MiniMapMediatorTest, TestNoConsentNeeded) {
  if (!base::ios::IsRunningOnOrLater(16, 4, 0)) {
    GTEST_SKIP() << "Feature only available on iOS16.4+";
  }
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeature(web::features::kOneTapForMaps);

  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesAccepted,
                                         false);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesEnabled, true);
  OCMExpect([delegate_ showMapWithIPH:NO]);
  [mediator_ userInitiatedMiniMapConsentRequired:NO];
}

// Tests that settings are updated correctly after user consents.
TEST_F(MiniMapMediatorTest, TestUserConsents) {
  if (!base::ios::IsRunningOnOrLater(16, 4, 0)) {
    GTEST_SKIP() << "Feature only available on iOS16.4+";
  }
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeature(web::features::kOneTapForMaps);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesAccepted,
                                         false);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesEnabled, true);
  OCMExpect([delegate_ showConsentInterstitial]);
  [mediator_ userInitiatedMiniMapConsentRequired:YES];
  OCMExpect([delegate_ showMapWithIPH:NO]);
  [mediator_ userConsented];
  environment_.RunUntilIdle();
  EXPECT_TRUE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesAccepted));
  EXPECT_TRUE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesEnabled));
}

// Tests that settings are updated correctly after user declines.
TEST_F(MiniMapMediatorTest, TestUserDeclines) {
  if (!base::ios::IsRunningOnOrLater(16, 4, 0)) {
    GTEST_SKIP() << "Feature only available on iOS16.4+";
  }
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeature(web::features::kOneTapForMaps);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesAccepted,
                                         false);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesEnabled, true);
  OCMExpect([delegate_ showConsentInterstitial]);
  [mediator_ userInitiatedMiniMapConsentRequired:YES];
  OCMExpect([delegate_ dismissConsentInterstitialWithCompletion:[OCMArg any]]);
  [mediator_ userDeclined];
  environment_.RunUntilIdle();
  EXPECT_FALSE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesAccepted));
  EXPECT_FALSE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesEnabled));
}

// Tests that consent is presented if it is forced.
TEST_F(MiniMapMediatorTest, TestUserConsentForced) {
  if (!base::ios::IsRunningOnOrLater(16, 4, 0)) {
    GTEST_SKIP() << "Feature only available on iOS16.4+";
  }
  base::test::ScopedFeatureList scoped_feature_list;
  base::FieldTrialParams feature_parameters{
      {web::features::kOneTapForMapsConsentModeParamTitle,
       web::features::kOneTapForMapsConsentModeForcedParam}};
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      web::features::kOneTapForMaps, feature_parameters);

  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesAccepted, true);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesEnabled, true);
  OCMExpect([delegate_ showConsentInterstitial]);
  [mediator_ userInitiatedMiniMapConsentRequired:YES];
  OCMExpect([delegate_ showMapWithIPH:NO]);
  [mediator_ userConsented];
  environment_.RunUntilIdle();
  EXPECT_TRUE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesAccepted));
  EXPECT_TRUE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesEnabled));
}

// Tests that consent screen is not triggered but IPH is displayed.
TEST_F(MiniMapMediatorTest, TestConsentIPH) {
  if (!base::ios::IsRunningOnOrLater(16, 4, 0)) {
    GTEST_SKIP() << "Feature only available on iOS16.4+";
  }
  base::test::ScopedFeatureList scoped_feature_list;
  base::FieldTrialParams feature_parameters{
      {web::features::kOneTapForMapsConsentModeParamTitle,
       web::features::kOneTapForMapsConsentModeIPHParam}};
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      web::features::kOneTapForMaps, feature_parameters);

  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesAccepted,
                                         false);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesEnabled, true);
  OCMExpect([delegate_ showMapWithIPH:YES]);
  [mediator_ userInitiatedMiniMapConsentRequired:YES];

  environment_.RunUntilIdle();
  EXPECT_TRUE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesAccepted));
  EXPECT_TRUE(
      browser_state_->GetPrefs()->GetBoolean(prefs::kDetectAddressesEnabled));
}

// Tests that consent screen is not triggered if not needed.
TEST_F(MiniMapMediatorTest, TestConsentDisabled) {
  if (!base::ios::IsRunningOnOrLater(16, 4, 0)) {
    GTEST_SKIP() << "Feature only available on iOS16.4+";
  }
  base::test::ScopedFeatureList scoped_feature_list;
  base::FieldTrialParams feature_parameters{
      {web::features::kOneTapForMapsConsentModeParamTitle,
       web::features::kOneTapForMapsConsentModeDisabledParam}};
  scoped_feature_list.InitAndEnableFeatureWithParameters(
      web::features::kOneTapForMaps, feature_parameters);

  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesAccepted,
                                         false);
  browser_state_->GetPrefs()->SetBoolean(prefs::kDetectAddressesEnabled, true);
  OCMExpect([delegate_ showMapWithIPH:NO]);
  [mediator_ userInitiatedMiniMapConsentRequired:NO];
}