blob: 745fc454d7593b6feebc3f661ced0b5b5589baae [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.h"
#include "base/bind_helpers.h"
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_service.h"
#include "chrome/browser/chromeos/crostini/ansible/ansible_management_test_helper.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/views/crostini/crostini_browser_test_util.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/network_service_instance.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/chromeos/devicetype_utils.h"
class CrostiniAnsibleSoftwareConfigViewBrowserTest
: public CrostiniDialogBrowserTest {
public:
CrostiniAnsibleSoftwareConfigViewBrowserTest()
: CrostiniDialogBrowserTest(true /*register_termina*/),
container_id_(crostini::kCrostiniDefaultVmName,
crostini::kCrostiniDefaultContainerName),
network_connection_tracker_(
network::TestNetworkConnectionTracker::CreateInstance()) {}
// CrostiniDialogBrowserTest:
void ShowUi(const std::string& name) override {
crostini::ShowCrostiniAnsibleSoftwareConfigView(browser()->profile());
}
CrostiniAnsibleSoftwareConfigView* ActiveView() {
return CrostiniAnsibleSoftwareConfigView::GetActiveViewForTesting();
}
protected:
void SetUpOnMainThread() override {
// NetworkConnectionTracker should be reset first.
content::SetNetworkConnectionTrackerForTesting(nullptr);
content::SetNetworkConnectionTrackerForTesting(
network_connection_tracker_.get());
test_helper_ = std::make_unique<crostini::AnsibleManagementTestHelper>(
browser()->profile());
test_helper_->SetUpAnsiblePlaybookPreference();
}
void SetConnectionType(network::mojom::ConnectionType type) {
network_connection_tracker_->SetConnectionType(type);
}
// A new Widget was created in ShowUi() or since the last VerifyUi().
bool HasView() { return VerifyUi() && ActiveView() != nullptr; }
// No new Widget was created in ShowUi() or since last VerifyUi().
bool HasNoView() {
base::RunLoop().RunUntilIdle();
return !VerifyUi() && ActiveView() == nullptr;
}
bool IsDefaultDialog() {
return !HasAcceptButton() && !HasCancelButton() && HasDefaultStrings();
}
bool IsErrorDialog() {
return HasAcceptButton() && !HasCancelButton() && HasErrorStrings();
}
bool IsErrorOfflineDialog() {
return HasAcceptButton() && HasCancelButton() && HasErrorOfflineStrings();
}
crostini::AnsibleManagementService* ansible_management_service() {
return crostini::AnsibleManagementService::GetForProfile(
browser()->profile());
}
crostini::ContainerId container_id_;
private:
bool HasAcceptButton() { return ActiveView()->GetOkButton() != nullptr; }
bool HasCancelButton() { return ActiveView()->GetCancelButton() != nullptr; }
bool HasDefaultStrings() {
return ActiveView()->GetWindowTitle() ==
l10n_util::GetStringUTF16(
IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_LABEL) &&
ActiveView()->GetSubtextLabelStringForTesting() ==
l10n_util::GetStringUTF16(
IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_SUBTEXT);
}
bool HasErrorStrings() {
return ActiveView()->GetWindowTitle() ==
l10n_util::GetStringUTF16(
IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_LABEL) &&
ActiveView()->GetSubtextLabelStringForTesting() ==
l10n_util::GetStringUTF16(
IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_SUBTEXT);
}
bool HasErrorOfflineStrings() {
return ActiveView()->GetWindowTitle() ==
l10n_util::GetStringFUTF16(
IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_OFFLINE_LABEL,
ui::GetChromeOSDeviceName()) &&
ActiveView()->GetSubtextLabelStringForTesting() ==
l10n_util::GetStringUTF16(
IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_ERROR_OFFLINE_SUBTEXT);
}
std::unique_ptr<network::TestNetworkConnectionTracker>
network_connection_tracker_;
std::unique_ptr<crostini::AnsibleManagementTestHelper> test_helper_;
};
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
InvokeUi_default) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
SuccessfulFlow) {
ShowUi("default");
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ActiveView()->OnAnsibleSoftwareConfigurationFinished(true);
EXPECT_TRUE(HasNoView());
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
UnsuccessfulFlow) {
ShowUi("default");
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
EXPECT_NE(nullptr, ActiveView());
EXPECT_TRUE(IsErrorDialog());
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
UnsuccessfulFlow_Offline) {
SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);
ShowUi("default");
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
EXPECT_NE(nullptr, ActiveView());
EXPECT_TRUE(IsErrorOfflineDialog());
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
UnsuccessfulFlow_Offline_CanRetry) {
SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);
ShowUi("default");
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
EXPECT_NE(nullptr, ActiveView());
EXPECT_TRUE(IsErrorOfflineDialog());
// Retry button clicked.
ActiveView()->AcceptDialog();
EXPECT_NE(nullptr, ActiveView());
EXPECT_TRUE(IsDefaultDialog());
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
UnsuccessfulFlow_Offline_Cancel) {
SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);
ShowUi("default");
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ActiveView()->OnAnsibleSoftwareConfigurationFinished(false);
EXPECT_NE(nullptr, ActiveView());
EXPECT_TRUE(IsErrorOfflineDialog());
// Cancel button clicked.
ActiveView()->CancelDialog();
EXPECT_TRUE(HasNoView());
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
AnsibleConfigFlow_Successful) {
ansible_management_service()->ConfigureDefaultContainer(base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ansible_management_service()->OnInstallLinuxPackageProgress(
container_id_, crostini::InstallLinuxPackageProgressStatus::SUCCEEDED,
100, /*error_message=*/{});
base::RunLoop().RunUntilIdle();
EXPECT_NE(nullptr, ActiveView());
ansible_management_service()->OnApplyAnsiblePlaybookProgress(
vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED,
/*failure_details=*/"");
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(HasNoView());
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
AnsibleConfigFlow_InstallationFailed) {
ansible_management_service()->ConfigureDefaultContainer(base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ansible_management_service()->OnInstallLinuxPackageProgress(
container_id_, crostini::InstallLinuxPackageProgressStatus::FAILED, 0,
/*error_message=*/{});
base::RunLoop().RunUntilIdle();
EXPECT_NE(nullptr, ActiveView());
EXPECT_TRUE(IsErrorDialog());
}
IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest,
AnsibleConfigFlow_ApplicationFailed) {
ansible_management_service()->ConfigureDefaultContainer(base::DoNothing());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(HasView());
EXPECT_TRUE(IsDefaultDialog());
ansible_management_service()->OnInstallLinuxPackageProgress(
container_id_, crostini::InstallLinuxPackageProgressStatus::SUCCEEDED,
100, /*error_message=*/{});
base::RunLoop().RunUntilIdle();
EXPECT_NE(nullptr, ActiveView());
ansible_management_service()->OnApplyAnsiblePlaybookProgress(
vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED,
/*failure_details=*/"");
base::RunLoop().RunUntilIdle();
EXPECT_NE(nullptr, ActiveView());
EXPECT_TRUE(IsErrorDialog());
}