chromium/ios/chrome/browser/lens_overlay/model/lens_overlay_tab_helper_unittest.mm

// Copyright 2024 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/lens_overlay/model/lens_overlay_tab_helper.h"

#import "base/memory/raw_ptr.h"
#import "base/test/scoped_feature_list.h"
#import "components/lens/lens_overlay_permission_utils.h"
#import "components/prefs/pref_service.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/commands/lens_overlay_commands.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gtest/include/gtest/gtest.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"

namespace {

class LensOverlayTabHelperTest : public PlatformTest {
 public:
  LensOverlayTabHelperTest() {
    browser_state_ = profile_manager_.AddProfileWithBuilder(
        TestChromeBrowserState::Builder());
  }

  void SetUp() override {
    PlatformTest::SetUp();

    feature_list_.InitAndEnableFeature(kEnableLensOverlay);

    GetApplicationContext()->GetLocalState()->SetInteger(
        lens::prefs::kLensOverlaySettings,
        static_cast<int>(
            lens::prefs::LensOverlaySettingsPolicyValue::kEnabled));

    web::WebState::CreateParams params(browser_state_.get());
    web_state_ = web::WebState::Create(params);

    id dispatcher = [[CommandDispatcher alloc] init];
    dispatcher_ = dispatcher;

    LensOverlayTabHelper::CreateForWebState(web_state_.get());
    helper_ = LensOverlayTabHelper::FromWebState(web_state_.get());
    ASSERT_TRUE(helper_);

    helper_->SetLensOverlayCommandsHandler(dispatcher);

    mock_commands_handler_ = OCMProtocolMock(@protocol(LensOverlayCommands));
    [dispatcher_ startDispatchingToTarget:mock_commands_handler_
                              forProtocol:@protocol(LensOverlayCommands)];
  }

 protected:
  web::WebTaskEnvironment task_environment_{
      web::WebTaskEnvironment::MainThreadType::IO};
  IOSChromeScopedTestingLocalState scoped_testing_local_state_;
  TestProfileManagerIOS profile_manager_;
  raw_ptr<ChromeBrowserState> browser_state_;
  std::unique_ptr<web::WebState> web_state_;
  raw_ptr<LensOverlayTabHelper> helper_ = nullptr;
  id handler_;
  id dispatcher_;
  id mock_commands_handler_;
  base::test::ScopedFeatureList feature_list_;
};

// Test that web state destruction causes lens UI to destroy with no animation.
TEST_F(LensOverlayTabHelperTest, ShouldDestroyUIOnWebStateDestruction) {
  helper_->SetLensOverlayShown(true);
  OCMExpect([mock_commands_handler_ destroyLensUI:NO]);
  web_state_.reset();
  EXPECT_OCMOCK_VERIFY(mock_commands_handler_);
}

// Test that destroyLensUI should not be called if the lens overlay is not
// shown.
TEST_F(LensOverlayTabHelperTest, ShouldNotDestroyUIOnWebStateDestruction) {
  [[mock_commands_handler_ reject] destroyLensUI:[OCMArg any]];
  helper_->SetLensOverlayShown(false);
  web_state_.reset();
  EXPECT_OCMOCK_VERIFY(mock_commands_handler_);
}

// Tests that a change in the web state is propagated to the commands handler.
TEST_F(LensOverlayTabHelperTest, ShouldShowTheUIWhenWebStateChanges) {
  // Given a shown lens overlay state.
  helper_->SetLensOverlayShown(true);
  // Then the Lens UI should be shown.
  OCMExpect([mock_commands_handler_ showLensUI:YES]);
  // When the tab helper is notify of a change in the web state.
  helper_->WasShown(web_state_.get());

  EXPECT_OCMOCK_VERIFY(mock_commands_handler_);
}

// Tests that a change in the web state is propagated to the commands handler.
TEST_F(LensOverlayTabHelperTest, ShouldHideTheUIWhenWebStateChanges) {
  // Given a shown lens overlay state.
  helper_->SetLensOverlayShown(true);
  // Then the Lens UI should be hidden.
  OCMExpect([mock_commands_handler_ hideLensUI:YES]);
  // When the tab helper is notify of a change in the web state.
  helper_->WasHidden(web_state_.get());

  EXPECT_OCMOCK_VERIFY(mock_commands_handler_);
}

// Tests that a change in the web state is not propagated to the commands
// handler when the lens overlay is not shown.
TEST_F(LensOverlayTabHelperTest, ShouldNotChangeUIStateWhenOverlayIsNotShown) {
  // Given a lens overlay not show.
  helper_->SetLensOverlayShown(false);
  // Then the Lens UI methods should not be called.
  OCMReject([mock_commands_handler_ showLensUI:YES]);
  OCMReject([mock_commands_handler_ hideLensUI:YES]);
  // When the tab helper is notify of a change in the web state.
  helper_->WasShown(web_state_.get());
  helper_->WasHidden(web_state_.get());

  EXPECT_OCMOCK_VERIFY(mock_commands_handler_);
}

}  // namespace