blob: c0d9b4d5b3c0c35e4f129b892f3cc6915f700ed6 [file] [log] [blame]
// Copyright (c) 2013 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/test/chromedriver/chrome/web_view_impl.h"
#include <list>
#include <memory>
#include <string>
#include "base/compiler_specific.h"
#include "base/values.h"
#include "chrome/test/chromedriver/chrome/devtools_client.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class FakeDevToolsClient : public DevToolsClient {
public:
FakeDevToolsClient() : id_("fake-id"), status_(kOk) {}
~FakeDevToolsClient() override {}
void set_status(const Status& status) {
status_ = status;
}
void set_result(const base::DictionaryValue& result) {
result_.Clear();
result_.MergeDictionary(&result);
}
// Overridden from DevToolsClient:
const std::string& GetId() override { return id_; }
bool WasCrashed() override { return false; }
Status ConnectIfNecessary() override { return Status(kOk); }
Status SendCommand(
const std::string& method,
const base::DictionaryValue& params) override {
return SendCommandAndGetResult(method, params, nullptr);
}
Status SendCommandWithTimeout(
const std::string& method,
const base::DictionaryValue& params,
const Timeout* timeout) override {
return SendCommandAndGetResult(method, params, nullptr);
}
Status SendAsyncCommand(
const std::string& method,
const base::DictionaryValue& params) override {
return SendCommandAndGetResult(method, params, nullptr);
}
Status SendCommandAndGetResult(
const std::string& method,
const base::DictionaryValue& params,
std::unique_ptr<base::DictionaryValue>* result) override {
if (status_.IsError())
return status_;
result->reset(result_.DeepCopy());
return Status(kOk);
}
Status SendCommandAndGetResultWithTimeout(
const std::string& method,
const base::DictionaryValue& params,
const Timeout* timeout,
std::unique_ptr<base::DictionaryValue>* result) override {
return SendCommandAndGetResult(method, params, result);
}
Status SendCommandAndIgnoreResponse(
const std::string& method,
const base::DictionaryValue& params) override {
return SendCommandAndGetResult(method, params, nullptr);
}
void AddListener(DevToolsEventListener* listener) override {}
Status HandleEventsUntil(const ConditionalFunc& conditional_func,
const Timeout& timeout) override {
return Status(kOk);
}
Status HandleReceivedEvents() override { return Status(kOk); }
private:
const std::string id_;
Status status_;
base::DictionaryValue result_;
};
void AssertEvalFails(const base::DictionaryValue& command_result) {
std::unique_ptr<base::DictionaryValue> result;
FakeDevToolsClient client;
client.set_result(command_result);
Status status = internal::EvaluateScript(
&client, 0, std::string(), internal::ReturnByValue, &result);
ASSERT_EQ(kUnknownError, status.code());
ASSERT_FALSE(result);
}
} // namespace
TEST(EvaluateScript, CommandError) {
std::unique_ptr<base::DictionaryValue> result;
FakeDevToolsClient client;
client.set_status(Status(kUnknownError));
Status status = internal::EvaluateScript(
&client, 0, std::string(), internal::ReturnByValue, &result);
ASSERT_EQ(kUnknownError, status.code());
ASSERT_FALSE(result);
}
TEST(EvaluateScript, MissingWasThrown) {
base::DictionaryValue dict;
ASSERT_NO_FATAL_FAILURE(AssertEvalFails(dict));
}
TEST(EvaluateScript, MissingResult) {
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", false);
ASSERT_NO_FATAL_FAILURE(AssertEvalFails(dict));
}
TEST(EvaluateScript, Throws) {
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", true);
dict.SetString("result.type", "undefined");
ASSERT_NO_FATAL_FAILURE(AssertEvalFails(dict));
}
TEST(EvaluateScript, Ok) {
std::unique_ptr<base::DictionaryValue> result;
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", false);
dict.SetInteger("result.key", 100);
FakeDevToolsClient client;
client.set_result(dict);
ASSERT_TRUE(internal::EvaluateScript(
&client, 0, std::string(), internal::ReturnByValue, &result).IsOk());
ASSERT_TRUE(result);
ASSERT_TRUE(result->HasKey("key"));
}
TEST(EvaluateScriptAndGetValue, MissingType) {
std::unique_ptr<base::Value> result;
FakeDevToolsClient client;
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", false);
dict.SetInteger("result.value", 1);
client.set_result(dict);
ASSERT_TRUE(internal::EvaluateScriptAndGetValue(
&client, 0, std::string(), &result).IsError());
}
TEST(EvaluateScriptAndGetValue, Undefined) {
std::unique_ptr<base::Value> result;
FakeDevToolsClient client;
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", false);
dict.SetString("result.type", "undefined");
client.set_result(dict);
Status status =
internal::EvaluateScriptAndGetValue(&client, 0, std::string(), &result);
ASSERT_EQ(kOk, status.code());
ASSERT_TRUE(result && result->IsType(base::Value::Type::NONE));
}
TEST(EvaluateScriptAndGetValue, Ok) {
std::unique_ptr<base::Value> result;
FakeDevToolsClient client;
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", false);
dict.SetString("result.type", "integer");
dict.SetInteger("result.value", 1);
client.set_result(dict);
Status status =
internal::EvaluateScriptAndGetValue(&client, 0, std::string(), &result);
ASSERT_EQ(kOk, status.code());
int value;
ASSERT_TRUE(result && result->GetAsInteger(&value));
ASSERT_EQ(1, value);
}
TEST(EvaluateScriptAndGetObject, NoObject) {
FakeDevToolsClient client;
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", false);
dict.SetString("result.type", "integer");
client.set_result(dict);
bool got_object;
std::string object_id;
ASSERT_TRUE(internal::EvaluateScriptAndGetObject(
&client, 0, std::string(), &got_object, &object_id).IsOk());
ASSERT_FALSE(got_object);
ASSERT_TRUE(object_id.empty());
}
TEST(EvaluateScriptAndGetObject, Ok) {
FakeDevToolsClient client;
base::DictionaryValue dict;
dict.SetBoolean("wasThrown", false);
dict.SetString("result.objectId", "id");
client.set_result(dict);
bool got_object;
std::string object_id;
ASSERT_TRUE(internal::EvaluateScriptAndGetObject(
&client, 0, std::string(), &got_object, &object_id).IsOk());
ASSERT_TRUE(got_object);
ASSERT_STREQ("id", object_id.c_str());
}
TEST(ParseCallFunctionResult, NotDict) {
std::unique_ptr<base::Value> result;
base::Value value(1);
ASSERT_NE(kOk, internal::ParseCallFunctionResult(value, &result).code());
}
TEST(ParseCallFunctionResult, Ok) {
std::unique_ptr<base::Value> result;
base::DictionaryValue dict;
dict.SetInteger("status", 0);
dict.SetInteger("value", 1);
Status status = internal::ParseCallFunctionResult(dict, &result);
ASSERT_EQ(kOk, status.code());
int value;
ASSERT_TRUE(result && result->GetAsInteger(&value));
ASSERT_EQ(1, value);
}
TEST(ParseCallFunctionResult, ScriptError) {
std::unique_ptr<base::Value> result;
base::DictionaryValue dict;
dict.SetInteger("status", 1);
dict.SetInteger("value", 1);
Status status = internal::ParseCallFunctionResult(dict, &result);
ASSERT_EQ(1, status.code());
ASSERT_FALSE(result);
}