Commit 5b443bf4 authored by Sergei Datsenko's avatar Sergei Datsenko Committed by Commit Bot

Implement some render tests.

Add tests to verify we render correctly pages that use JavaScript to
change page title and write console logs.

Change-Id: I7b33a888ad721c1673aaa7520e0ea22c4bdcdd75
Reviewed-on: https://chromium-review.googlesource.com/765632Reviewed-by: default avatarAlex Clarke <alexclarke@chromium.org>
Commit-Queue: Sergei Datsenko <dats@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517233}
parent eb7476a1
<html>
<head>
<script language="JavaScript">
<![CDATA[
function image() {
window.open('<xsl:value-of select="/IMAGE/@href" />');
}
]]>
</script>
</head>
<body onload="func3()">
<script type="text/javascript">
func1()
</script>
<script type="text/javascript">
func2()
</script>
<script type="text/javascript">
console.log("Hello, Script!");
</script>
</body>
</html>
<html>
<head>
<title>JavaScript is off</title>
<script language="JavaScript">
<!-- Begin
document.title = "JavaScript is on";
// End -->
</script>
</head>
<body onload="settitle()">
Hello, World!
</body>
</html>
......@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <functional>
#include <strstream>
#include "content/public/test/browser_test.h"
#include "headless/public/devtools/domains/dom_snapshot.h"
#include "headless/public/devtools/domains/page.h"
#include "headless/public/devtools/domains/runtime.h"
#include "headless/public/headless_devtools_client.h"
#include "headless/test/headless_render_test.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -30,17 +34,31 @@ std::vector<T> ElementsView(const std::vector<std::unique_ptr<V>>& elements,
return result;
}
bool HasType(int type, const DOMNode& node) {
return node.GetNodeType() == type;
}
bool HasName(const char* name, const DOMNode& node) {
return node.GetNodeName() == name;
}
bool IsTag(const DOMNode& node) {
return HasType(1, node);
}
bool IsText(const DOMNode& node) {
return HasType(3, node);
}
bool IsTagWithName(const char* name, const DOMNode& node) {
return IsTag(node) && HasName(name, node);
}
std::vector<std::string> Structure(const GetSnapshotResult* snapshot) {
return ElementsView<std::string, DOMNode>(
*snapshot->GetDomNodes(),
[](const auto& node) { return node.GetNodeType() == 1; },
*snapshot->GetDomNodes(), IsTag,
[](const auto& node) { return node.GetNodeName(); });
}
std::vector<std::string> Contents(const GetSnapshotResult* snapshot) {
return ElementsView<std::string, DOMNode>(
*snapshot->GetDomNodes(),
[](const auto& node) { return node.GetNodeType() == 3; },
*snapshot->GetDomNodes(), IsText,
[](const auto& node) { return node.GetNodeValue(); });
}
......@@ -51,6 +69,45 @@ std::vector<std::string> TextLayout(const GetSnapshotResult* snapshot) {
[](const auto& node) { return node.GetLayoutText(); });
}
std::vector<const DOMNode*> FilterDOM(
const GetSnapshotResult* snapshot,
std::function<bool(const DOMNode&)> filter) {
return ElementsView<const DOMNode*, DOMNode>(
*snapshot->GetDomNodes(), filter, [](const auto& n) { return &n; });
}
size_t IndexInDOM(const GetSnapshotResult* snapshot, const DOMNode* node) {
for (size_t i = 0; i < snapshot->GetDomNodes()->size(); ++i) {
if (snapshot->GetDomNodes()->at(i).get() == node)
return i;
}
CHECK(false);
return static_cast<size_t>(-1);
}
const DOMNode* GetAt(const GetSnapshotResult* snapshot, size_t index) {
CHECK_LE(index, snapshot->GetDomNodes()->size());
return snapshot->GetDomNodes()->at(index).get();
}
MATCHER_P(NodeName, expected, "") {
return arg->GetNodeName() == expected;
}
MATCHER_P(NodeValue, expected, "") {
return arg->GetNodeValue() == expected;
}
MATCHER_P(NodeType, expected, 0) {
return arg->GetNodeType() == expected;
}
MATCHER_P(RemoteString, expected, "") {
return arg->GetType() == runtime::RemoteObjectType::STRING &&
arg->GetValue()->GetString() == expected;
}
using testing::ElementsAre;
using testing::StartsWith;
} // namespace
class HelloWorldTest : public HeadlessRenderTest {
......@@ -61,11 +118,10 @@ class HelloWorldTest : public HeadlessRenderTest {
void VerifyDom(GetSnapshotResult* dom_snapshot) override {
EXPECT_THAT(Structure(dom_snapshot),
testing::ElementsAre("HTML", "HEAD", "BODY", "H1"));
ElementsAre("HTML", "HEAD", "BODY", "H1"));
EXPECT_THAT(Contents(dom_snapshot),
testing::ElementsAre("Hello headless world!", "\n"));
EXPECT_THAT(TextLayout(dom_snapshot),
testing::ElementsAre("Hello headless world!"));
ElementsAre("Hello headless world!", "\n"));
EXPECT_THAT(TextLayout(dom_snapshot), ElementsAre("Hello headless world!"));
AllDone();
}
};
......@@ -90,4 +146,92 @@ class TimeoutTest : public HeadlessRenderTest {
};
HEADLESS_ASYNC_DEVTOOLED_TEST_F(TimeoutTest);
class JavaScriptOverrideTitle_JsEnabled : public HeadlessRenderTest {
private:
GURL GetPageUrl(HeadlessDevToolsClient* client) override {
return embedded_test_server()->GetURL(
"/render/javascript_override_title.html");
}
void VerifyDom(GetSnapshotResult* dom_snapshot) override {
auto dom = FilterDOM(
dom_snapshot, [](const auto& n) { return IsTagWithName("TITLE", n); });
ASSERT_THAT(dom, ElementsAre(NodeName("TITLE")));
size_t pos = IndexInDOM(dom_snapshot, dom[0]);
const DOMNode* value = GetAt(dom_snapshot, pos + 1);
EXPECT_THAT(value, NodeValue("JavaScript is on"));
AllDone();
}
};
HEADLESS_ASYNC_DEVTOOLED_TEST_F(JavaScriptOverrideTitle_JsEnabled);
class JavaScriptOverrideTitle_JsDisabled : public HeadlessRenderTest {
private:
void OverrideWebPreferences(WebPreferences* preferences) override {
HeadlessRenderTest::OverrideWebPreferences(preferences);
preferences->javascript_enabled = false;
}
GURL GetPageUrl(HeadlessDevToolsClient* client) override {
return embedded_test_server()->GetURL(
"/render/javascript_override_title.html");
}
void VerifyDom(GetSnapshotResult* dom_snapshot) override {
auto dom = FilterDOM(
dom_snapshot, [](const auto& n) { return IsTagWithName("TITLE", n); });
ASSERT_THAT(dom, ElementsAre(NodeName("TITLE")));
size_t pos = IndexInDOM(dom_snapshot, dom[0]);
const DOMNode* value = GetAt(dom_snapshot, pos + 1);
EXPECT_THAT(value, NodeValue("JavaScript is off"));
AllDone();
}
};
HEADLESS_ASYNC_DEVTOOLED_TEST_F(JavaScriptOverrideTitle_JsDisabled);
class JavaScriptConsoleErrors : public HeadlessRenderTest,
public runtime::ExperimentalObserver {
private:
HeadlessDevToolsClient* client_;
std::vector<std::string> messages_;
bool log_called_ = false;
GURL GetPageUrl(HeadlessDevToolsClient* client) override {
client_ = client;
client_->GetRuntime()->GetExperimental()->AddObserver(this);
base::RunLoop run_loop;
client_->GetRuntime()->GetExperimental()->Enable(run_loop.QuitClosure());
base::MessageLoop::ScopedNestableTaskAllower nest_loop(
base::MessageLoop::current());
run_loop.Run();
return embedded_test_server()->GetURL("/render/console_errors.html");
}
void OnConsoleAPICalled(
const runtime::ConsoleAPICalledParams& params) override {
EXPECT_THAT(*params.GetArgs(), ElementsAre(RemoteString("Hello, Script!")));
log_called_ = true;
}
void OnExceptionThrown(
const runtime::ExceptionThrownParams& params) override {
const runtime::ExceptionDetails* details = params.GetExceptionDetails();
messages_.push_back(details->GetText() + " " +
details->GetException()->GetDescription());
}
void VerifyDom(GetSnapshotResult* dom_snapshot) override {
client_->GetRuntime()->GetExperimental()->Disable();
client_->GetRuntime()->GetExperimental()->RemoveObserver(this);
EXPECT_TRUE(log_called_);
EXPECT_THAT(messages_,
ElementsAre(StartsWith("Uncaught SyntaxError:"),
StartsWith("Uncaught ReferenceError: func1"),
StartsWith("Uncaught ReferenceError: func2"),
StartsWith("Uncaught ReferenceError: func3")));
AllDone();
}
};
HEADLESS_ASYNC_DEVTOOLED_TEST_F(JavaScriptConsoleErrors);
} // namespace headless
......@@ -53,6 +53,19 @@ void HeadlessRenderTest::OnTimeout() {
FAIL() << "Renderer timeout";
}
void HeadlessRenderTest::CustomizeHeadlessBrowserContext(
HeadlessBrowserContext::Builder& builder) {
builder.SetOverrideWebPreferencesCallback(
base::Bind(&HeadlessRenderTest::OverrideWebPreferences,
weak_ptr_factory_.GetWeakPtr()));
}
void HeadlessRenderTest::OverrideWebPreferences(WebPreferences* preferences) {
preferences->hide_scrollbars = true;
preferences->javascript_enabled = true;
preferences->autoplay_policy = content::AutoplayPolicy::kUserGestureRequired;
}
void HeadlessRenderTest::UrlRequestFailed(net::URLRequest* request,
int net_error,
bool canceled_by_devtools) {
......
......@@ -40,8 +40,12 @@ class HeadlessRenderTest : public HeadlessAsyncDevTooledBrowserTest,
virtual GURL GetPageUrl(HeadlessDevToolsClient* client) = 0;
virtual void VerifyDom(dom_snapshot::GetSnapshotResult* dom_snapshot) = 0;
virtual void OnTimeout();
virtual void OverrideWebPreferences(WebPreferences* preferences);
void AllDone() { done_called_ = true; }
void CustomizeHeadlessBrowserContext(
HeadlessBrowserContext::Builder& builder) override;
// HeadlessBrowserContext::Observer
void UrlRequestFailed(net::URLRequest* request,
int net_error,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment