910e62b5创建于 1月15日历史提交
// 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/test/chromedriver/fedcm_commands.h"

#include "chrome/test/chromedriver/chrome/fedcm_tracker.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/stub_devtools_client.h"
#include "chrome/test/chromedriver/chrome/stub_web_view.h"
#include "chrome/test/chromedriver/chrome/web_view.h"
#include "chrome/test/chromedriver/session.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

class MockResponseWebView : public StubWebView {
 public:
  explicit MockResponseWebView(DevToolsClient* client)
      : StubWebView("1"), tracker_(client) {}
  ~MockResponseWebView() override = default;

  Status SendCommandAndGetResult(
      const std::string& command,
      const base::Value::Dict& params,
      std::unique_ptr<base::Value>* result) override {
    last_command_ = command;
    return Status(kOk);
  }

  Status GetFedCmTracker(FedCmTracker** out_tracker) override {
    *out_tracker = &tracker_;
    return Status(kOk);
  }

  void SendEvent(DevToolsClient* client) {
    base::Value::Dict dict;
    dict.Set("dialogId", "0");
    dict.Set("title", "Title");
    dict.Set("dialogType", "AccountChooser");
    base::Value::Dict account;
    account.Set("accountId", "123");
    account.Set("email", "foo@bar.com");
    account.Set("name", "Foo Bar");
    account.Set("givenName", "Foo");
    account.Set("pictureUrl", "https://pics/pic.jpg");
    account.Set("idpConfigUrl", "https://idp.example/fedcm.json");
    account.Set("idpLoginUrl", "https://idp.example/login");
    account.Set("loginState", "SignIn");

    base::Value::List accounts;
    accounts.Append(std::move(account));
    dict.Set("accounts", std::move(accounts));

    tracker_.OnEvent(client, "FedCm.dialogShown", dict);
  }

  const std::string& GetLastCommand() const { return last_command_; }

  bool IsDetached() const override { return false; }

  Status CallFunctionWithTimeout(
      const std::string& frame,
      const std::string& function,
      const base::Value::List& args,
      const base::TimeDelta& timeout,
      const CallFunctionOptions& options,
      std::unique_ptr<base::Value>* result) override {
    return Status{kOk};
  }

 private:
  FedCmTracker tracker_;
  std::string last_command_;
};

class FedCmCommandsTest : public testing::Test {
 public:
  FedCmCommandsTest() = default;

 protected:
  Session session{"id"};
  StubDevToolsClient client;
  MockResponseWebView web_view{&client};
};

}  // namespace

TEST_F(FedCmCommandsTest, ExecuteCancelDialog) {
  base::Value::Dict params;
  std::unique_ptr<base::Value> value;

  Status status =
      ExecuteCancelDialog(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kNoSuchAlert, status.code());

  web_view.SendEvent(&client);

  status = ExecuteCancelDialog(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kOk, status.code());

  EXPECT_EQ("FedCm.dismissDialog", web_view.GetLastCommand());
}

TEST_F(FedCmCommandsTest, ExecuteSelectAccount) {
  base::Value::Dict params;
  std::unique_ptr<base::Value> value;

  Status status =
      ExecuteSelectAccount(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kNoSuchAlert, status.code());

  web_view.SendEvent(&client);

  // No account index
  status = ExecuteSelectAccount(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kInvalidArgument, status.code());

  params.Set("accountIndex", 0);
  status = ExecuteSelectAccount(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kOk, status.code());

  EXPECT_EQ("FedCm.selectAccount", web_view.GetLastCommand());
}

TEST_F(FedCmCommandsTest, ExecuteGetAccounts) {
  base::Value::Dict params;
  std::unique_ptr<base::Value> value;

  Status status =
      ExecuteGetAccounts(&session, &web_view, params, &value, nullptr);
  ASSERT_EQ(kNoSuchAlert, status.code());

  web_view.SendEvent(&client);

  status = ExecuteGetAccounts(&session, &web_view, params, &value, nullptr);
  ASSERT_EQ(kOk, status.code());
  base::Value::List* response = value->GetIfList();
  ASSERT_TRUE(response);
  ASSERT_EQ(1u, response->size());
  base::Value::Dict* account = response->front().GetIfDict();
  ASSERT_TRUE(account);
  std::string* accountId = account->FindString("accountId");
  ASSERT_TRUE(accountId);
  EXPECT_EQ(*accountId, "123");
  std::string* email = account->FindString("email");
  ASSERT_TRUE(email);
  EXPECT_EQ(*email, "foo@bar.com");
  std::string* name = account->FindString("name");
  ASSERT_TRUE(name);
  EXPECT_EQ(*name, "Foo Bar");
  std::string* givenName = account->FindString("givenName");
  ASSERT_TRUE(givenName);
  EXPECT_EQ(*givenName, "Foo");
  std::string* pictureUrl = account->FindString("pictureUrl");
  ASSERT_TRUE(pictureUrl);
  EXPECT_EQ(*pictureUrl, "https://pics/pic.jpg");
  std::string* idpConfigUrl = account->FindString("idpConfigUrl");
  ASSERT_TRUE(idpConfigUrl);
  EXPECT_EQ(*idpConfigUrl, "https://idp.example/fedcm.json");
  std::string* idpLoginUrl = account->FindString("idpLoginUrl");
  ASSERT_TRUE(idpLoginUrl);
  EXPECT_EQ(*idpLoginUrl, "https://idp.example/login");
  std::string* loginState = account->FindString("loginState");
  ASSERT_TRUE(loginState);
  EXPECT_EQ(*loginState, "SignIn");

  // This should not have triggered any commands.
  EXPECT_EQ("", web_view.GetLastCommand());
}

TEST_F(FedCmCommandsTest, ExecuteGetTitle) {
  base::Value::Dict params;
  std::unique_ptr<base::Value> value;

  Status status =
      ExecuteGetFedCmTitle(&session, &web_view, params, &value, nullptr);
  ASSERT_EQ(kNoSuchAlert, status.code());

  web_view.SendEvent(&client);

  status = ExecuteGetFedCmTitle(&session, &web_view, params, &value, nullptr);
  ASSERT_EQ(kOk, status.code());
  base::Value::Dict* dict = value->GetIfDict();
  ASSERT_TRUE(dict);
  std::string* title = dict->FindString("title");
  ASSERT_TRUE(title);
  EXPECT_EQ(*title, "Title");

  // This should not have triggered any commands.
  EXPECT_EQ("", web_view.GetLastCommand());
}

TEST_F(FedCmCommandsTest, ExecuteGetDialogType) {
  base::Value::Dict params;
  std::unique_ptr<base::Value> value;

  Status status =
      ExecuteGetDialogType(&session, &web_view, params, &value, nullptr);
  ASSERT_EQ(kNoSuchAlert, status.code());

  web_view.SendEvent(&client);

  status = ExecuteGetDialogType(&session, &web_view, params, &value, nullptr);
  ASSERT_EQ(kOk, status.code());
  std::string* type = value->GetIfString();
  ASSERT_TRUE(type);
  EXPECT_EQ(*type, "AccountChooser");

  // This should not have triggered any commands.
  EXPECT_EQ("", web_view.GetLastCommand());
}

TEST_F(FedCmCommandsTest, ExecuteSetDelayEnabled) {
  base::Value::Dict params;
  std::unique_ptr<base::Value> value;

  // No enabled argument.
  Status status =
      ExecuteSetDelayEnabled(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kInvalidArgument, status.code());

  params.Set("enabled", false);
  status = ExecuteSetDelayEnabled(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kOk, status.code());

  EXPECT_EQ("FedCm.enable", web_view.GetLastCommand());
}

TEST_F(FedCmCommandsTest, ExecuteResetCooldown) {
  base::Value::Dict params;
  std::unique_ptr<base::Value> value;

  Status status =
      ExecuteResetCooldown(&session, &web_view, params, &value, nullptr);
  EXPECT_EQ(kOk, status.code());

  EXPECT_EQ("FedCm.resetCooldown", web_view.GetLastCommand());
}