Chromium Code Reviews| Index: chrome/browser/ui/test/test_browser_dialog.cc |
| diff --git a/chrome/browser/ui/test/test_browser_dialog.cc b/chrome/browser/ui/test/test_browser_dialog.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2f0880caf115d48aa9f4cb97c7d221f50c159251 |
| --- /dev/null |
| +++ b/chrome/browser/ui/test/test_browser_dialog.cc |
| @@ -0,0 +1,112 @@ |
| +// Copyright 2016 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/test/test_browser_dialog.h" |
| + |
| +#include "base/command_line.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "chrome/browser/platform_util.h" |
| +#include "ui/base/material_design/material_design_controller.h" |
| +#include "ui/base/test/material_design_controller_test_api.h" |
| +#include "ui/base/test/user_interactive_test_case.h" |
| +#include "ui/base/ui_base_switches.h" |
| +#include "ui/views/widget/widget.h" |
| +#include "ui/views/widget/widget_observer.h" |
| + |
| +namespace { |
| + |
| +// An automatic action for WidgetCloser to post to the RunLoop. |
| +// TODO(tapted): Explore asynchronous Widget::Close() and DialogClientView:: |
| +// {Accept,Cancel}Window() approaches to test other dialog lifetimes. |
| +enum class DialogAction { |
| + INTERACTIVE, // Run interactively. |
| + CLOSE_NOW, // Call Widget::CloseNow(). |
| +}; |
| + |
| +// Helper to break out of the nested run loop that runs a test dialog. |
| +class WidgetCloser : public views::WidgetObserver { |
| + public: |
| + WidgetCloser(views::Widget* widget, DialogAction action) |
| + : widget_(widget), weak_ptr_factory_(this) { |
| + widget->AddObserver(this); |
| + if (action == DialogAction::INTERACTIVE) |
| + return; |
| + |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&WidgetCloser::CloseNow, weak_ptr_factory_.GetWeakPtr())); |
| + } |
| + |
| + // WidgetObserver: |
| + void OnWidgetDestroyed(views::Widget* widget) override { |
| + widget_->RemoveObserver(this); |
| + widget_ = nullptr; |
| + base::MessageLoop::current()->QuitNow(); |
| + } |
| + |
| + private: |
| + void CloseNow() { |
| + if (widget_) |
| + widget_->CloseNow(); |
| + } |
| + |
| + views::Widget* widget_; |
| + |
| + base::WeakPtrFactory<WidgetCloser> weak_ptr_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WidgetCloser); |
| +}; |
| + |
| +// Extracts the |name| argument for ShowDialog() from the current test case. |
| +std::string NameFromTestCase() { |
|
Paweł Hajdan Jr.
2016/12/20 16:27:15
Is this the same as TestNameWithoutDisabledPrefix
tapted
2016/12/20 23:34:47
Thanks for the pointer - there's some interesting
|
| + const std::string disabled_prefix = "DISABLED_"; |
| + std::string name = |
| + testing::UnitTest::GetInstance()->current_test_info()->name(); |
| + if (name.find(disabled_prefix) == 0) |
| + name = name.substr(disabled_prefix.size()); |
| + |
| + std::string::size_type underscore = name.find('_'); |
| + return underscore == std::string::npos ? std::string() |
| + : name.substr(underscore + 1); |
| +} |
| + |
| +} // namespace |
| + |
| +TestBrowserDialog::TestBrowserDialog() {} |
| + |
| +void TestBrowserDialog::RunDialog() { |
| +#if defined(OS_MACOSX) |
| + // The rest of this method assumes the child dialog is toolkit-views. So, for |
| + // Mac, it will only work if --secondary-ui-md is passed. Without this, a |
| + // Cocoa dialog will be created, which TestBrowserDialog doesn't support. |
| + // Force SecondaryUiMaterial() on Mac to get coverage on the bots. Leave it |
| + // optional elsewhere so that the non-MD dialog can be invoked to compare. |
| + ui::test::MaterialDesignControllerTestAPI md_test_api( |
| + ui::MaterialDesignController::GetMode()); |
| + md_test_api.SetSecondaryUiMaterial(true); |
| +#endif |
| + |
| + gfx::NativeView parent = platform_util::GetViewForWindow(DialogParent()); |
| + views::Widget::Widgets widgets_before; |
| + views::Widget::GetAllChildWidgets(parent, &widgets_before); |
| + |
| + ShowDialog(NameFromTestCase()); |
| + views::Widget::Widgets widgets_after; |
| + views::Widget::GetAllChildWidgets(parent, &widgets_after); |
| + |
| + auto added = base::STLSetDifference<std::vector<views::Widget*>>( |
| + widgets_after, widgets_before); |
| + |
| + // This can fail if no dialog was shown, if the dialog shown wasn't a toolkit- |
| + // views dialog, or if more than one child dialog was shown. |
| + ASSERT_EQ(1u, added.size()); |
| + |
| + const DialogAction action = base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + internal::kInteractiveSwitch) |
| + ? DialogAction::INTERACTIVE |
| + : DialogAction::CLOSE_NOW; |
| + |
| + WidgetCloser closer(added[0], action); |
| + ::test::RunTestInteractively(); |
| +} |