| // 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. |
| |
| #include "chrome/browser/ui/android/hats/survey_client_android.h" |
| |
| #include <memory> |
| |
| #include "base/android/callback_android.h" |
| #include "base/android/jni_android.h" |
| #include "base/android/scoped_java_ref.h" |
| #include "base/run_loop.h" |
| #include "base/test/task_environment.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/android/hats/survey_ui_delegate_android.h" |
| #include "chrome/browser/ui/android/hats/test/test_survey_utils_bridge.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/android/window_android.h" |
| |
| using base::android::ScopedJavaGlobalRef; |
| |
| namespace hats { |
| |
| namespace { |
| |
| const char kTestSurveyTrigger[] = "testing"; |
| const SurveyBitsData kTestSurveyProductSpecificBitsData{ |
| {"Test Field 1", true}, |
| {"Test Field 2", false}}; |
| const SurveyStringData kTestSurveyProductSpecificStringData{ |
| {"Test Field 3", "Test value"}}; |
| } // namespace |
| |
| // Custom implementation resenting a C++ implemented SurveyUiDelegate. |
| class TestSurveyUiDelegate : public SurveyUiDelegateAndroid { |
| public: |
| explicit TestSurveyUiDelegate(JNIEnv* env) : env_(env) {} |
| |
| ~TestSurveyUiDelegate() override = default; |
| |
| void AcceptSurvey() { |
| DCHECK(on_accepted_callback_); |
| base::android::RunRunnableAndroid(on_accepted_callback_); |
| } |
| |
| void DeclineSurvey() { |
| DCHECK(on_declined_callback_); |
| base::android::RunRunnableAndroid(on_declined_callback_); |
| } |
| |
| void ShowSurveyInvitation( |
| JNIEnv* env, |
| const JavaParamRef<jobject>& on_accepted_callback, |
| const JavaParamRef<jobject>& on_declined_callback, |
| const JavaParamRef<jobject>& on_presentation_failed_callback) override { |
| on_accepted_callback_ = on_accepted_callback; |
| on_declined_callback_ = on_declined_callback; |
| on_presentation_failed_callback_ = on_presentation_failed_callback; |
| } |
| |
| // Dismiss the survey invitation. |
| void Dismiss(JNIEnv* env) override {} |
| |
| private: |
| raw_ptr<JNIEnv> env_; |
| ScopedJavaGlobalRef<jobject> on_accepted_callback_; |
| ScopedJavaGlobalRef<jobject> on_declined_callback_; |
| ScopedJavaGlobalRef<jobject> on_presentation_failed_callback_; |
| }; |
| |
| class SurveyClientAndroidTest : public testing::Test { |
| public: |
| SurveyClientAndroidTest(const SurveyClientAndroidTest&) = delete; |
| SurveyClientAndroidTest& operator=(const SurveyClientAndroidTest&) = delete; |
| |
| protected: |
| content::BrowserTaskEnvironment task_environment_{ |
| base::test::TaskEnvironment::TimeSource::MOCK_TIME}; |
| |
| SurveyClientAndroidTest() = default; |
| |
| void SetUp() override { |
| testing::Test::SetUp(); |
| profile_manager_ = std::make_unique<TestingProfileManager>( |
| TestingBrowserProcess::GetGlobal()); |
| ASSERT_TRUE(profile_manager_->SetUp()); |
| profile_ = profile_manager_->CreateTestingProfile("test_profile"); |
| TestSurveyUtilsBridge::SetUpJavaTestSurveyFactory(); |
| } |
| |
| std::unique_ptr<SurveyClientAndroid> survey_client_; |
| std::unique_ptr<TestingProfileManager> profile_manager_; |
| raw_ptr<TestingProfile> profile_; |
| }; |
| |
| TEST_F(SurveyClientAndroidTest, CreateSurveyClientWithStaticTriggerId) { |
| std::unique_ptr<ui::WindowAndroid::ScopedWindowAndroidForTesting> window = |
| ui::WindowAndroid::CreateForTesting(); |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| std::unique_ptr<TestSurveyUiDelegate> delegate = |
| std::make_unique<TestSurveyUiDelegate>(env); |
| survey_client_ = std::make_unique<SurveyClientAndroid>( |
| kTestSurveyTrigger, delegate.get(), profile_, |
| /*supplied_trigger_id=*/std::nullopt, window->get()); |
| |
| survey_client_->LaunchSurvey(window->get(), |
| kTestSurveyProductSpecificBitsData, |
| kTestSurveyProductSpecificStringData); |
| |
| delegate->AcceptSurvey(); |
| |
| std::string last_shown_trigger = |
| TestSurveyUtilsBridge::GetLastShownSurveyTriggerId(); |
| ASSERT_FALSE(last_shown_trigger.empty()); |
| ASSERT_EQ(last_shown_trigger, kHatsNextSurveyTriggerIDTesting); |
| } |
| |
| TEST_F(SurveyClientAndroidTest, CreateSurveyClientWithDynamicTriggerId) { |
| std::unique_ptr<ui::WindowAndroid::ScopedWindowAndroidForTesting> window = |
| ui::WindowAndroid::CreateForTesting(); |
| JNIEnv* env = base::android::AttachCurrentThread(); |
| std::unique_ptr<TestSurveyUiDelegate> delegate = |
| std::make_unique<TestSurveyUiDelegate>(env); |
| |
| const std::string kSuppliedTriggerId = "SomeOtherId"; |
| survey_client_ = std::make_unique<SurveyClientAndroid>( |
| kTestSurveyTrigger, delegate.get(), profile_, |
| /*supplied_trigger_id=*/kSuppliedTriggerId, window->get()); |
| |
| survey_client_->LaunchSurvey(window->get(), |
| kTestSurveyProductSpecificBitsData, |
| kTestSurveyProductSpecificStringData); |
| |
| delegate->AcceptSurvey(); |
| |
| std::string last_shown_trigger = |
| TestSurveyUtilsBridge::GetLastShownSurveyTriggerId(); |
| ASSERT_FALSE(last_shown_trigger.empty()); |
| ASSERT_EQ(last_shown_trigger, kSuppliedTriggerId); |
| } |
| |
| } // namespace hats |