| // 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); } |
| void SetDetached() override {} |
| void SetOwner(WebViewImpl* owner) override {} |
| |
| 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->is_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); |
| } |