blob: 5d464c080cf7dd9b0eb913604cf28b01b5e7c397 [file] [log] [blame]
// Copyright 2022 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/worker/extendable_message_event.h"
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "cobalt/script/testing/fake_script_value.h"
#include "cobalt/script/v8c/entry_scope.h"
#include "cobalt/script/value_handle.h"
#include "cobalt/web/testing/gtest_workarounds.h"
#include "cobalt/web/testing/mock_event_listener.h"
#include "cobalt/worker/extendable_message_event_init.h"
#include "cobalt/worker/testing/test_with_javascript.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
namespace worker {
using script::testing::FakeScriptValue;
using ::testing::IsSubstring;
using web::testing::MockEventListener;
namespace {
class ExtendableMessageEventTestWithJavaScript
: public testing::TestServiceWorkerWithJavaScript {
protected:
ExtendableMessageEventTestWithJavaScript() {
fake_event_listener_ = MockEventListener::Create();
}
~ExtendableMessageEventTestWithJavaScript() override {}
std::unique_ptr<MockEventListener> fake_event_listener_;
};
} // namespace
TEST_F(ExtendableMessageEventTestWithJavaScript,
ConstructorWithEventTypeString) {
scoped_refptr<ExtendableMessageEvent> event =
new ExtendableMessageEvent(environment_settings(), "mytestevent");
EXPECT_EQ("mytestevent", event->type());
EXPECT_EQ(NULL, event->target().get());
EXPECT_EQ(NULL, event->current_target().get());
EXPECT_EQ(web::Event::kNone, event->event_phase());
EXPECT_FALSE(event->bubbles());
EXPECT_FALSE(event->cancelable());
EXPECT_FALSE(event->default_prevented());
EXPECT_FALSE(event->IsBeingDispatched());
EXPECT_FALSE(event->propagation_stopped());
EXPECT_FALSE(event->immediate_propagation_stopped());
script::Handle<script::ValueHandle> event_data =
event->data(web_context()->environment_settings());
EXPECT_TRUE(event_data.IsEmpty());
}
TEST_F(ExtendableMessageEventTestWithJavaScript, ConstructorWithAny) {
base::Optional<script::ValueHandleHolder::Reference> reference;
EvaluateScript("'ConstructorWithAnyMessageData'", &reference);
auto* isolate = web::get_isolate(web_context()->environment_settings());
const ExtendableMessageEventInit init;
scoped_refptr<ExtendableMessageEvent> event = new ExtendableMessageEvent(
environment_settings(), base::Tokens::message(), init,
std::make_unique<script::StructuredClone>(reference->referenced_value()));
EXPECT_EQ("message", event->type());
EXPECT_EQ(NULL, event->target().get());
EXPECT_EQ(NULL, event->current_target().get());
EXPECT_EQ(web::Event::kNone, event->event_phase());
EXPECT_FALSE(event->bubbles());
EXPECT_FALSE(event->cancelable());
EXPECT_FALSE(event->default_prevented());
EXPECT_FALSE(event->IsBeingDispatched());
EXPECT_FALSE(event->propagation_stopped());
EXPECT_FALSE(event->immediate_propagation_stopped());
script::v8c::EntryScope entry_scope(isolate);
script::Handle<script::ValueHandle> event_data =
event->data(web_context()->environment_settings());
EXPECT_FALSE(event_data.IsEmpty());
auto script_value = event_data.GetScriptValue();
v8::Local<v8::Value> v8_value = script::GetV8Value(*script_value);
std::string actual =
*(v8::String::Utf8Value(isolate, v8_value.As<v8::String>()));
EXPECT_EQ("ConstructorWithAnyMessageData", actual);
}
TEST_F(ExtendableMessageEventTestWithJavaScript,
ConstructorWithEventTypeAndDefaultInitDict) {
ExtendableMessageEventInit init;
scoped_refptr<ExtendableMessageEvent> event =
new ExtendableMessageEvent(environment_settings(), "mytestevent", init);
EXPECT_EQ("mytestevent", event->type());
EXPECT_EQ(nullptr, event->target().get());
EXPECT_EQ(nullptr, event->current_target().get());
EXPECT_EQ(web::Event::kNone, event->event_phase());
EXPECT_FALSE(event->bubbles());
EXPECT_FALSE(event->cancelable());
EXPECT_FALSE(event->default_prevented());
EXPECT_FALSE(event->IsBeingDispatched());
EXPECT_FALSE(event->propagation_stopped());
EXPECT_FALSE(event->immediate_propagation_stopped());
script::Handle<script::ValueHandle> event_data =
event->data(web_context()->environment_settings());
EXPECT_TRUE(event_data.IsEmpty());
EXPECT_TRUE(event->origin().empty());
EXPECT_TRUE(event->last_event_id().empty());
EXPECT_FALSE(event->source().IsType<scoped_refptr<Client>>());
EXPECT_FALSE(event->source().IsType<scoped_refptr<ServiceWorker>>());
EXPECT_FALSE(event->source().IsType<scoped_refptr<web::MessagePort>>());
EXPECT_TRUE(event->ports().empty());
}
TEST_F(ExtendableMessageEventTestWithJavaScript,
ConstructorWithEventTypeAndInitDict) {
ExtendableMessageEventInit init;
base::Optional<script::ValueHandleHolder::Reference> reference;
EvaluateScript("'data_value'", &reference);
init.set_data(&(reference->referenced_value()));
init.set_origin("OriginString");
init.set_last_event_id("lastEventIdString");
base::Optional<ExtendableMessageEvent::SourceType> client(
Client::Create(web_context()->environment_settings()));
init.set_source(client);
scoped_refptr<ExtendableMessageEvent> event =
new ExtendableMessageEvent(environment_settings(), "mytestevent", init);
EXPECT_EQ("mytestevent", event->type());
EXPECT_EQ(nullptr, event->target().get());
EXPECT_EQ(nullptr, event->current_target().get());
EXPECT_EQ(web::Event::kNone, event->event_phase());
EXPECT_FALSE(event->bubbles());
EXPECT_FALSE(event->cancelable());
EXPECT_FALSE(event->default_prevented());
EXPECT_FALSE(event->IsBeingDispatched());
EXPECT_FALSE(event->propagation_stopped());
EXPECT_FALSE(event->immediate_propagation_stopped());
script::Handle<script::ValueHandle> event_data =
event->data(web_context()->environment_settings());
auto script_value = event_data.GetScriptValue();
auto* isolate = script::GetIsolate(*script_value);
script::v8c::EntryScope entry_scope(isolate);
v8::Local<v8::Value> v8_value = script::GetV8Value(*script_value);
std::string actual =
*(v8::String::Utf8Value(isolate, v8_value.As<v8::String>()));
EXPECT_EQ("data_value", actual);
EXPECT_EQ("OriginString", event->origin());
EXPECT_EQ("lastEventIdString", event->last_event_id());
EXPECT_TRUE(event->source().IsType<scoped_refptr<Client>>());
EXPECT_EQ(client.value().AsType<scoped_refptr<Client>>().get(),
event->source().AsType<scoped_refptr<Client>>().get());
EXPECT_TRUE(event->ports().empty());
}
TEST_F(ExtendableMessageEventTestWithJavaScript,
ConstructorWithEventTypeAndInvalidSource) {
std::string result;
EXPECT_FALSE(
EvaluateScript("var event = new ExtendableMessageEvent('dog', "
" {source: this});"
"if (event.type == 'dog') event.source;",
&result))
<< "Failed to evaluate script.";
EXPECT_PRED_FORMAT2(IsSubstring,
"TypeError: Value is not a member of the union type.",
result);
// EXPECT_FALSE(IsSubstring(
// "", "", "TypeError: Value is not a member of the union type.", result));
}
TEST_F(ExtendableMessageEventTestWithJavaScript,
ConstructorWithEventTypeAndExtendableMessageEventInitDict) {
std::string result;
// Note: None of the types for 'source' are constructible, so that can
// not easily be tested here.
EXPECT_TRUE(
EvaluateScript("var event = new ExtendableMessageEvent('dog', "
" {cancelable: true, "
" origin: 'OriginValue',"
" lastEventId: 'LastEventIdValue',"
" data: {value: 'data_value'},"
" }"
");"
"if (event.type == 'dog' &&"
" event.bubbles == false &&"
" event.cancelable == true &&"
" event.origin == 'OriginValue' &&"
" event.lastEventId == 'LastEventIdValue' &&"
" event.ports.length == 0 &&"
" event.data.value == 'data_value') "
" event.data.value;",
&result))
<< "Failed to evaluate script.";
EXPECT_EQ("data_value", result);
}
} // namespace worker
} // namespace cobalt