blob: 9f544e8c8d5ccac6951db383a3dcd221a3f58ec7 [file] [log] [blame]
// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/dom/window.h"
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "cobalt/bindings/testing/utils.h"
#include "cobalt/dom/screen.h"
#include "cobalt/dom/testing/test_with_javascript.h"
#include "cobalt/network_bridge/net_poster.h"
#include "cobalt/script/testing/fake_script_value.h"
#include "cobalt/web/error_event.h"
#include "cobalt/web/message_event.h"
#include "cobalt/web/testing/mock_event_listener.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
namespace dom {
using script::testing::FakeScriptValue;
class WindowTestBase {
protected:
WindowTestBase() {
fake_event_listener_ = web::testing::MockEventListener::Create();
}
virtual ~WindowTestBase() {}
std::unique_ptr<web::testing::MockEventListener> fake_event_listener_;
};
class WindowTest : public WindowTestBase, public testing::TestWithJavaScript {};
TEST_F(WindowTest, WindowShouldNotHaveChildren) {
EXPECT_EQ(window(), window()->window());
EXPECT_EQ(window(), window()->self());
EXPECT_EQ(window(), window()->frames());
EXPECT_EQ(0, window()->length());
EXPECT_EQ(window(), window()->top());
EXPECT_EQ(window(), window()->opener());
EXPECT_EQ(window(), window()->parent());
EXPECT_FALSE(window()->AnonymousIndexedGetter(0));
}
TEST_F(WindowTest, ViewportSize) {
EXPECT_FLOAT_EQ(window()->inner_width(), 1920.0f);
EXPECT_FLOAT_EQ(window()->inner_height(), 1080.0f);
EXPECT_FLOAT_EQ(window()->screen_x(), 0.0f);
EXPECT_FLOAT_EQ(window()->screen_y(), 0.0f);
EXPECT_FLOAT_EQ(window()->outer_width(), 1920.0f);
EXPECT_FLOAT_EQ(window()->outer_height(), 1080.0f);
EXPECT_FLOAT_EQ(window()->device_pixel_ratio(), 1.0f);
EXPECT_FLOAT_EQ(window()->screen()->width(), 1920.0f);
EXPECT_FLOAT_EQ(window()->screen()->height(), 1080.0f);
EXPECT_FLOAT_EQ(window()->screen()->avail_width(), 1920.0f);
EXPECT_FLOAT_EQ(window()->screen()->avail_height(), 1080.0f);
}
TEST_F(WindowTest, WindowIsWindow) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window", &result));
EXPECT_TRUE(bindings::testing::IsAcceptablePrototypeString("Window", result));
EXPECT_TRUE(EvaluateScript("typeof window.window", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.window", &result));
EXPECT_TRUE(bindings::testing::IsAcceptablePrototypeString("Window", result));
}
TEST_F(WindowTest, SelfIsWindow) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.self", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.self", &result));
EXPECT_TRUE(bindings::testing::IsAcceptablePrototypeString("Window", result));
}
TEST_F(WindowTest, DocumentIsDocument) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.document", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.document", &result));
EXPECT_TRUE(
bindings::testing::IsAcceptablePrototypeString("Document", result));
}
TEST_F(WindowTest, LocationIsObject) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.location", &result));
EXPECT_EQ("object", result);
// Note: Due the stringifier of URLUtils.href implemented by this attribute,
// the prototype is not recognized as type Location, and the href is returned.
EXPECT_TRUE(EvaluateScript("window.location", &result));
EXPECT_EQ("about:blank", result);
}
TEST_F(WindowTest, HistoryIsHistory) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.history", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.history", &result));
EXPECT_TRUE(
bindings::testing::IsAcceptablePrototypeString("History", result));
}
TEST_F(WindowTest, FramesIsWindow) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.frames", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.frames", &result));
EXPECT_TRUE(bindings::testing::IsAcceptablePrototypeString("Window", result));
}
TEST_F(WindowTest, LengthIsZero) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.length", &result));
EXPECT_EQ("number", result);
EXPECT_TRUE(EvaluateScript("window.length", &result));
EXPECT_EQ("0", result);
}
TEST_F(WindowTest, TopIsWindow) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.top", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.top", &result));
EXPECT_TRUE(bindings::testing::IsAcceptablePrototypeString("Window", result));
}
TEST_F(WindowTest, OpenerIsWindow) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.opener", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.opener", &result));
EXPECT_TRUE(bindings::testing::IsAcceptablePrototypeString("Window", result));
}
TEST_F(WindowTest, ParentIsWindow) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.parent", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.parent", &result));
EXPECT_TRUE(bindings::testing::IsAcceptablePrototypeString("Window", result));
}
TEST_F(WindowTest, NavigatorIsNavigator) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.navigator", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.navigator", &result));
EXPECT_TRUE(
bindings::testing::IsAcceptablePrototypeString("Navigator", result));
}
TEST_F(WindowTest, Btoa) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.btoa", &result));
EXPECT_EQ("function", result);
EXPECT_TRUE(EvaluateScript("window.btoa", &result));
EXPECT_EQ("function btoa() { [native code] }", result);
EXPECT_TRUE(EvaluateScript("window.btoa('test')", &result));
EXPECT_EQ("dGVzdA==", result);
}
TEST_F(WindowTest, Atob) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.atob", &result));
EXPECT_EQ("function", result);
EXPECT_TRUE(EvaluateScript("window.atob", &result));
EXPECT_EQ("function atob() { [native code] }", result);
EXPECT_TRUE(EvaluateScript("window.atob('dGVzdA==')", &result));
EXPECT_EQ("test", result);
}
TEST_F(WindowTest, Camera3DIsCamera3D) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.camera3D", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript("window.camera3D", &result));
EXPECT_TRUE(
bindings::testing::IsAcceptablePrototypeString("Camera3D", result));
}
TEST_F(WindowTest, Gc) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.gc", &result));
EXPECT_EQ("function", result);
EXPECT_TRUE(EvaluateScript("window.gc", &result));
EXPECT_EQ("function gc() { [native code] }", result);
EXPECT_TRUE(EvaluateScript("window.gc()", &result));
EXPECT_EQ("undefined", result);
}
TEST_F(WindowTest, Minimize) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.minimize", &result));
EXPECT_EQ("function", result);
EXPECT_TRUE(EvaluateScript("window.minimize", &result));
EXPECT_EQ("function minimize() { [native code] }", result);
EXPECT_TRUE(EvaluateScript("window.minimize()", &result));
EXPECT_EQ("undefined", result);
}
TEST_F(WindowTest, Screenshot) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.screenshot", &result));
EXPECT_EQ("function", result);
EXPECT_TRUE(EvaluateScript("window.screenshot", &result));
EXPECT_EQ("function screenshot() { [native code] }", result);
// Note we can't call screenshot in this unit test, since StubWindow doesn't
// pass in the screenshot function callback.
}
TEST_F(WindowTest, MessageEvent) {
window()->AddEventListener(
"message",
FakeScriptValue<web::EventListener>(fake_event_listener_.get()), true);
fake_event_listener_->ExpectHandleEventCall("message", window());
window()->DispatchEvent(new web::MessageEvent("message"));
}
TEST_F(WindowTest, OnMessageEvent) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.onmessage", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript(R"(
logString = '(empty)';
window.onmessage= function() {
logString = 'handled';
};
window.dispatchEvent(new MessageEvent('message'));
logString;
)",
&result));
EXPECT_EQ("handled", result);
}
TEST_F(WindowTest, MessageErrorEvent) {
window()->AddEventListener(
"messageerror",
FakeScriptValue<web::EventListener>(fake_event_listener_.get()), true);
fake_event_listener_->ExpectHandleEventCall("messageerror", window());
window()->DispatchEvent(new web::MessageEvent("messageerror"));
}
TEST_F(WindowTest, OnMessageErrorEvent) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.onmessageerror", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript(R"(
logString = '(empty)';
window.onmessageerror = function() {
logString = 'handled';
};
window.dispatchEvent(new Event('messageerror'));
logString;
)",
&result));
EXPECT_EQ("handled", result);
}
TEST_F(WindowTest, ErrorEvent) {
window()->AddEventListener(
"error", FakeScriptValue<web::EventListener>(fake_event_listener_.get()),
true);
fake_event_listener_->ExpectHandleEventCall("error", window());
window()->DispatchEvent(
new web::ErrorEvent(/*environment_settings=*/nullptr));
}
TEST_F(WindowTest, OnErrorEvent) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof window.onerror", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript(R"(
logString = '(empty)';
window.onerror = function() {
logString = 'handled';
};
window.dispatchEvent(new ErrorEvent('error'));
logString;
)",
&result));
EXPECT_EQ("handled", result);
}
namespace {
class WindowTestEventTest : public WindowTestBase,
public testing::TestWithJavaScriptBase,
public ::testing::TestWithParam<const char*> {};
std::string GetEventName(::testing::TestParamInfo<const char*> info) {
return std::string(info.param);
}
const char* events[] = {"beforeunload",
"blur",
"click",
"focus",
"hashchange",
"keydown",
"keypress",
"keyup",
"languagechange",
"load",
"loadeddata",
"loadedmetadata",
"loadstart",
"mousedown",
"mouseenter",
"mouseleave",
"mousemove",
"mouseout",
"mouseover",
"mouseup",
"offline",
"online",
"pause",
"play",
"playing",
"resize",
"scroll",
"transitionend",
"gotpointercapture",
"lostpointercapture",
"pointercancel",
"pointerdown",
"pointerenter",
"pointerleave",
"pointermove",
"pointerout",
"pointerover",
"pointerup",
"progress",
"ratechange",
"rejectionhandled",
"seeked",
"seeking",
"timeupdate",
"unhandledrejection",
"volumechange",
"waiting",
"wheel"};
} // namespace
TEST_P(WindowTestEventTest, AddEventListener) {
const char* event_name = GetParam();
window()->AddEventListener(
event_name,
FakeScriptValue<web::EventListener>(fake_event_listener_.get()), true);
fake_event_listener_->ExpectHandleEventCall(event_name, window());
window()->DispatchEvent(new web::Event(event_name));
}
TEST_P(WindowTestEventTest, OnEvent) {
const char* event_name = GetParam();
std::string result;
EXPECT_TRUE(EvaluateScript(
base::StringPrintf("typeof window.on%s", event_name), &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(
EvaluateScript(base::StringPrintf(R"(
logString = '(empty)';
self.on%s = function() {
logString = '%s';
};
self.dispatchEvent(new Event('%s'));
logString;
)",
event_name, event_name, event_name),
&result));
EXPECT_EQ(event_name, result);
}
INSTANTIATE_TEST_CASE_P(WindowTest, WindowTestEventTest,
::testing::ValuesIn(events), GetEventName);
// Test that when Window's network status change callbacks are triggered,
// corresponding online and offline events are fired to listeners.
TEST_F(WindowTest, OfflineEvent) {
window()->AddEventListener(
"offline",
FakeScriptValue<web::EventListener>(fake_event_listener_.get()), true);
fake_event_listener_->ExpectHandleEventCall("offline", window());
window()->OnWindowOnOfflineEvent();
}
TEST_F(WindowTest, OnlineEvent) {
window()->AddEventListener(
"online", FakeScriptValue<web::EventListener>(fake_event_listener_.get()),
true);
fake_event_listener_->ExpectHandleEventCall("online", window());
window()->OnWindowOnOnlineEvent();
}
TEST_F(WindowTest, UnloadEvent) {
window()->AddEventListener(
"unload", FakeScriptValue<web::EventListener>(fake_event_listener_.get()),
true);
fake_event_listener_->ExpectHandleEventCall("unload", window());
window()->DispatchEvent(new web::Event("unload"));
// Remove the unload event listener here so that the fixture destructor
// doesn't call into this event handler after it has been destroyed.
window()->RemoveEventListener(
"unload", FakeScriptValue<web::EventListener>(fake_event_listener_.get()),
true);
}
TEST_F(WindowTest, OnUnloadEvent) {
std::string result;
EXPECT_TRUE(EvaluateScript("typeof self.onunload", &result));
EXPECT_EQ("object", result);
EXPECT_TRUE(EvaluateScript(R"(
logString = '(empty)';
self.onunload = function() {
logString = 'handled';
};
self.dispatchEvent(new Event('unload'));
logString;
)",
&result));
EXPECT_EQ("handled", result);
}
} // namespace dom
} // namespace cobalt