910e62b5创建于 1月15日历史提交
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/base/models/dialog_model.h"

#include <memory>
#include <string>

#include "base/functional/callback.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/test/test_dialog_model_host.h"
#include "ui/events/event.h"

namespace ui {

class DialogModelButtonTest : public testing::Test {};

TEST_F(DialogModelButtonTest, UsesParamsUniqueId) {
  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kUniqueId);
  auto host = std::make_unique<TestDialogModelHost>(
      DialogModel::Builder()
          .AddOkButton(base::DoNothing(),
                       DialogModel::Button::Params().SetId(kUniqueId))
          .Build());
  EXPECT_EQ(kUniqueId, host->GetId(TestDialogModelHost::ButtonId::kOk));
}

TEST_F(DialogModelButtonTest, UsesParamsAccelerators) {
  const Accelerator accelerator_1;
  const Accelerator accelerator_2(VKEY_Z, EF_SHIFT_DOWN | EF_CONTROL_DOWN);

  auto host = std::make_unique<TestDialogModelHost>(
      DialogModel::Builder()
          .AddOkButton(base::DoNothing(), DialogModel::Button::Params()
                                              .AddAccelerator(accelerator_1)
                                              .AddAccelerator(accelerator_2))
          .Build());
  EXPECT_THAT(host->GetAccelerators(TestDialogModelHost::ButtonId::kOk),
              testing::UnorderedElementsAre(accelerator_1, accelerator_2));
}

TEST_F(DialogModelButtonTest, UsesCallback) {
  int callback_count = 0;
  std::unique_ptr<KeyEvent> last_event;
  auto host = std::make_unique<TestDialogModelHost>(
      DialogModel::Builder()
          .AddExtraButton(base::BindLambdaForTesting([&](const Event& event) {
                            ++callback_count;
                            last_event =
                                std::make_unique<KeyEvent>(*event.AsKeyEvent());
                          }),
                          DialogModel::Button::Params().SetLabel(u"button"))
          .Build());

  KeyEvent first_event(EventType::kKeyPressed, VKEY_RETURN, EF_NONE);
  host->TriggerExtraButton(first_event);
  EXPECT_EQ(1, callback_count);
  EXPECT_EQ(first_event.key_code(), last_event->key_code());

  KeyEvent second_event(EventType::kKeyPressed, VKEY_SPACE, EF_NONE);
  host->TriggerExtraButton(second_event);
  EXPECT_EQ(2, callback_count);
  EXPECT_EQ(second_event.key_code(), last_event->key_code());
}

class DialogModelDialogButtonTest : public testing::Test {
 public:
  void DialogButtonUsesArguments(TestDialogModelHost::ButtonId button_id) {
    DialogModel::Builder builder;

    // Callback to verify that the first parameter is used.
    bool callback_called = false;
    base::OnceClosure callback = base::BindRepeating(
        [](bool* callback_called) { *callback_called = true; },
        &callback_called);

    // The presence of an accelerator in |params| will be used to verify that
    // |params| are forwarded correctly to the DialogModel::Button constructor.
    DialogModel::Button::Params params;
    const Accelerator accelerator(VKEY_Z, EF_SHIFT_DOWN | EF_CONTROL_DOWN);
    const std::u16string label = u"my cool button";
    params.AddAccelerator(accelerator);
    params.SetLabel(label);

    switch (button_id) {
      case TestDialogModelHost::ButtonId::kCancel:
        builder.AddCancelButton(std::move(callback), params);
        break;
      case TestDialogModelHost::ButtonId::kExtra:
        // Wrap the callback into a repeating callback that'll only be called
        // once so the same verification can be used for the extra button.
        builder.AddExtraButton(
            base::BindRepeating(
                [](base::OnceClosure* callback, const Event& event) {
                  std::move(*callback).Run();
                },
                &callback),
            params);
        break;
      case TestDialogModelHost::ButtonId::kOk:
        builder.AddOkButton(std::move(callback), params);
        break;
    }
    auto host = std::make_unique<TestDialogModelHost>(builder.Build());

    EXPECT_EQ(label, host->GetLabel(button_id))
        << "The label parameter wasn't used.";

    EXPECT_THAT(host->GetAccelerators(button_id),
                testing::UnorderedElementsAre(accelerator))
        << "The params parameter wasn't used.";

    // Trigger the corresponding action.
    switch (button_id) {
      case TestDialogModelHost::ButtonId::kCancel:
        TestDialogModelHost::Cancel(std::move(host));
        break;
      case TestDialogModelHost::ButtonId::kExtra:
        host->TriggerExtraButton(
            KeyEvent(EventType::kKeyPressed, VKEY_RETURN, EF_NONE));
        break;
      case TestDialogModelHost::ButtonId::kOk:
        TestDialogModelHost::Accept(std::move(host));
        break;
    }

    EXPECT_TRUE(callback_called) << "The callback parameter wasn't used.";
  }
};

TEST_F(DialogModelDialogButtonTest, OkButtonUsesArguments) {
  DialogButtonUsesArguments(TestDialogModelHost::ButtonId::kOk);
}

TEST_F(DialogModelDialogButtonTest, ExtraButtonUsesArguments) {
  DialogButtonUsesArguments(TestDialogModelHost::ButtonId::kExtra);
}

TEST_F(DialogModelDialogButtonTest, CancelButtonUsesArguments) {
  DialogButtonUsesArguments(TestDialogModelHost::ButtonId::kCancel);
}

}  // namespace ui