#include <optional>
#include <string>
#include <utility>
#include "ash/system/mahi/mahi_constants.h"
#include "ash/system/mahi/mahi_panel_view.h"
#include "ash/system/mahi/mahi_panel_widget.h"
#include "ash/system/mahi/mahi_ui_controller.h"
#include "ash/system/mahi/test/mock_mahi_manager.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/pixel/ash_pixel_differ.h"
#include "ash/test/pixel/ash_pixel_test_helper.h"
#include "base/functional/callback.h"
#include "base/test/scoped_feature_list.h"
#include "chromeos/components/mahi/public/cpp/mahi_manager.h"
#include "chromeos/constants/chromeos_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/display/display.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/view.h"
#include "ui/views/view_utils.h"
#include "ui/views/widget/unique_widget_ptr.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace {
using chromeos::MahiResponseStatus;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::Values;
std::string ErrorStatusToString(MahiResponseStatus status) {
switch (status) {
case chromeos::MahiResponseStatus::kCantFindOutputData:
return "CantFindOutputData";
case chromeos::MahiResponseStatus::kContentExtractionError:
return "ContentExtractionError";
case chromeos::MahiResponseStatus::kInappropriate:
return "Inappropriate";
case chromeos::MahiResponseStatus::kUnknownError:
return "UnknownError";
case chromeos::MahiResponseStatus::kQuotaLimitHit:
return "QuotaLimitHit";
case chromeos::MahiResponseStatus::kResourceExhausted:
return "ResourceExhausted";
case chromeos::MahiResponseStatus::kRestrictedCountry:
return "RestrictedCountry";
case chromeos::MahiResponseStatus::kUnsupportedLanguage:
return "UnsupportedLanguage";
case chromeos::MahiResponseStatus::kLowQuota:
case chromeos::MahiResponseStatus::kSuccess:
NOTREACHED();
}
}
}
class MahiErrorStatusViewPixelTestBase : public AshTestBase {
protected:
explicit MahiErrorStatusViewPixelTestBase(MahiResponseStatus response_status,
bool enable_system_blur)
: response_status_(response_status),
enable_system_blur_(enable_system_blur) {}
void ShowMahiPanel() {
mahi_panel_widget_ = MahiPanelWidget::CreateAndShowPanelWidget(
GetPrimaryDisplay().id(), gfx::Rect(),
ui_controller());
mahi_panel_widget_->Show();
}
views::Widget* mahi_panel_widget() { return mahi_panel_widget_.get(); }
MockMahiManager& mock_mahi_manager() { return mock_mahi_manager_; }
MahiUiController* ui_controller() { return &ui_controller_; }
std::optional<pixel_test::InitParams> CreatePixelTestInitParams()
const override {
pixel_test::InitParams init_params;
init_params.system_blur_enabled = enable_system_blur_;
return init_params;
}
void SetUp() override {
scoped_feature_list_.InitWithFeatures(
{chromeos::features::kMahi,
chromeos::features::kFeatureManagementMahi},
{});
AshTestBase::SetUp();
ON_CALL(mock_mahi_manager_, GetContentTitle)
.WillByDefault(Return(u"content title"));
}
void TearDown() override {
mahi_panel_widget_.reset();
AshTestBase::TearDown();
}
MahiResponseStatus response_status_;
const bool enable_system_blur_;
base::test::ScopedFeatureList scoped_feature_list_;
NiceMock<MockMahiManager> mock_mahi_manager_;
MahiUiController ui_controller_;
chromeos::ScopedMahiManagerSetter scoped_setter_{&mock_mahi_manager_};
views::UniqueWidgetPtr mahi_panel_widget_;
};
class MahiErrorStatusViewPixelTest
: public MahiErrorStatusViewPixelTestBase,
public testing::WithParamInterface<
std::tuple<MahiResponseStatus, /*enable_system_blur*/ bool>> {
public:
MahiErrorStatusViewPixelTest()
: MahiErrorStatusViewPixelTestBase(
std::get<0>(GetParam()),
std::get<1>(GetParam())) {}
};
INSTANTIATE_TEST_SUITE_P(
All,
MahiErrorStatusViewPixelTest,
testing::Combine(Values(MahiResponseStatus::kCantFindOutputData,
MahiResponseStatus::kContentExtractionError,
MahiResponseStatus::kInappropriate,
MahiResponseStatus::kQuotaLimitHit,
MahiResponseStatus::kResourceExhausted,
MahiResponseStatus::kRestrictedCountry,
MahiResponseStatus::kUnsupportedLanguage,
MahiResponseStatus::kUnknownError),
testing::Bool()));
TEST_P(MahiErrorStatusViewPixelTest, Basics) {
ON_CALL(mock_mahi_manager(), GetSummary)
.WillByDefault([&](chromeos::MahiManager::MahiSummaryCallback callback) {
std::move(callback).Run(u"fake summary", response_status_);
});
ShowMahiPanel();
views::View* const error_status_view =
mahi_panel_widget()->GetContentsView()->GetViewByID(
mahi_constants::ViewId::kErrorStatusView);
ASSERT_TRUE(error_status_view);
EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
GenerateScreenshotName(ErrorStatusToString(response_status_)),
pixel_test_helper()->IsSystemBlurEnabled() ? 10 : 0,
error_status_view));
}
TEST_P(MahiErrorStatusViewPixelTest, QuestionAnswerView) {
ON_CALL(mock_mahi_manager(), AnswerQuestion)
.WillByDefault(
[&](const std::u16string& question, bool current_panel_content,
chromeos::MahiManager::MahiAnswerQuestionCallback callback) {
std::move(callback).Run(u"answer", response_status_);
});
ShowMahiPanel();
views::View* const mahi_contents_view =
mahi_panel_widget()->GetContentsView();
auto* const question_textfield =
views::AsViewClass<views::Textfield>(mahi_contents_view->GetViewByID(
mahi_constants::ViewId::kQuestionTextfield));
ASSERT_TRUE(question_textfield);
question_textfield->SetText(u"fake inappropriate question");
auto* const send_button = mahi_contents_view->GetViewByID(
mahi_constants::ViewId::kAskQuestionSendButton);
ASSERT_TRUE(send_button);
send_button->SetEnabled(true);
LeftClickOn(send_button);
EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
GenerateScreenshotName(ErrorStatusToString(response_status_)),
pixel_test_helper()->IsSystemBlurEnabled() ? 8 : 0,
mahi_contents_view->GetViewByID(mahi_constants::ViewId::kScrollView)));
}
}