1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Tests for CppBoundClass, in conjunction with CppBindingExample. Binds
6 // a CppBindingExample class into JavaScript in a custom test shell and tests
7 // the binding from the outside by loading JS into the shell.
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/public/common/url_constants.h"
11 #include "content/public/renderer/render_view_observer.h"
12 #include "content/public/test/render_view_test.h"
13 #include "content/test/cpp_binding_example.h"
14 #include "third_party/WebKit/public/platform/WebURLRequest.h"
15 #include "third_party/WebKit/public/web/WebDocument.h"
16 #include "third_party/WebKit/public/web/WebElement.h"
18 using webkit_glue::CppArgumentList
;
19 using webkit_glue::CppVariant
;
25 class CppBindingExampleSubObject
: public CppBindingExample
{
27 CppBindingExampleSubObject() {
28 sub_value_
.Set("sub!");
29 BindProperty("sub_value", &sub_value_
);
32 CppVariant sub_value_
;
36 class CppBindingExampleWithOptionalFallback
: public CppBindingExample
{
38 CppBindingExampleWithOptionalFallback() {
39 BindProperty("sub_object", sub_object_
.GetAsCppVariant());
42 void set_fallback_method_enabled(bool state
) {
43 BindFallbackCallback(state
?
44 base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod
,
45 base::Unretained(this))
46 : CppBoundClass::Callback());
49 // The fallback method does nothing, but because of it the JavaScript keeps
50 // running when a nonexistent method is called on an object.
51 void fallbackMethod(const CppArgumentList
& args
, CppVariant
* result
) {
55 CppBindingExampleSubObject sub_object_
;
58 class TestObserver
: public RenderViewObserver
{
60 explicit TestObserver(RenderView
* render_view
)
61 : RenderViewObserver(render_view
) {}
62 virtual void DidClearWindowObject(WebKit::WebFrame
* frame
) OVERRIDE
{
63 example_bound_class_
.BindToJavascript(frame
, "example");
65 void set_fallback_method_enabled(bool use_fallback
) {
66 example_bound_class_
.set_fallback_method_enabled(use_fallback
);
69 CppBindingExampleWithOptionalFallback example_bound_class_
;
74 class CppBoundClassTest
: public RenderViewTest
{
76 CppBoundClassTest() {}
78 virtual void SetUp() OVERRIDE
{
79 RenderViewTest::SetUp();
80 observer_
.reset(new TestObserver(view_
));
81 observer_
->set_fallback_method_enabled(useFallback());
83 WebKit::WebURLRequest url_request
;
84 url_request
.initialize();
85 url_request
.setURL(GURL(kAboutBlankURL
));
87 GetMainFrame()->loadRequest(url_request
);
88 ProcessPendingMessages();
91 virtual void TearDown() OVERRIDE
{
93 RenderViewTest::TearDown();
96 // Executes the specified JavaScript and checks that the resulting document
98 void CheckJavaScriptFailure(const std::string
& javascript
) {
99 ExecuteJavaScript(javascript
.c_str());
102 UTF16ToASCII(GetMainFrame()->document().documentElement().innerText()));
105 void CheckTrue(const std::string
& expression
) {
107 string16 check_page_a
=
108 ASCIIToUTF16(std::string("Number(") + expression
+ ")");
109 EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a
, &was_page_a
));
110 EXPECT_EQ(1, was_page_a
);
114 virtual bool useFallback() {
119 scoped_ptr
<TestObserver
> observer_
;
122 class CppBoundClassWithFallbackMethodTest
: public CppBoundClassTest
{
124 virtual bool useFallback() OVERRIDE
{
129 // Ensures that the example object has been bound to JS.
130 TEST_F(CppBoundClassTest
, ObjectExists
) {
131 CheckTrue("typeof window.example == 'object'");
133 // An additional check to test our test.
134 CheckTrue("typeof window.invalid_object == 'undefined'");
137 TEST_F(CppBoundClassTest
, PropertiesAreInitialized
) {
138 CheckTrue("example.my_value == 10");
140 CheckTrue("example.my_other_value == 'Reinitialized!'");
143 TEST_F(CppBoundClassTest
, SubOject
) {
144 CheckTrue("typeof window.example.sub_object == 'object'");
146 CheckTrue("example.sub_object.sub_value == 'sub!'");
149 TEST_F(CppBoundClassTest
, SetAndGetProperties
) {
150 // The property on the left will be set to the value on the right, then
151 // checked to make sure it holds that same value.
152 static const std::string tests
[] = {
153 "example.my_value", "7",
154 "example.my_value", "'test'",
155 "example.my_other_value", "3.14",
156 "example.my_other_value", "false",
157 "" // Array end marker: insert additional test pairs before this.
160 for (int i
= 0; tests
[i
] != ""; i
+= 2) {
161 std::string left
= tests
[i
];
162 std::string right
= tests
[i
+ 1];
164 std::string js
= left
;
168 ExecuteJavaScript(js
.c_str());
169 std::string expression
= left
;
170 expression
+= " == ";
172 CheckTrue(expression
);
176 TEST_F(CppBoundClassTest
, SetAndGetPropertiesWithCallbacks
) {
177 // TODO(dglazkov): fix NPObject issues around failing property setters and
178 // getters and add tests for situations when GetProperty or SetProperty fail.
179 ExecuteJavaScript("example.my_value_with_callback = 10;");
180 CheckTrue("example.my_value_with_callback == 10");
182 ExecuteJavaScript("example.my_value_with_callback = 11;");
183 CheckTrue("example.my_value_with_callback == 11");
185 CheckTrue("example.same == 42");
187 ExecuteJavaScript("example.same = 24;");
188 CheckTrue("example.same == 42");
191 TEST_F(CppBoundClassTest
, InvokeMethods
) {
192 // The expression on the left is expected to return the value on the right.
193 static const std::string tests
[] = {
194 "example.echoValue(true) == true",
195 "example.echoValue(13) == 13",
196 "example.echoValue(2.718) == 2.718",
197 "example.echoValue('yes') == 'yes'",
198 "example.echoValue() == null", // Too few arguments
200 "example.echoType(false) == true",
201 "example.echoType(19) == 3.14159",
202 "example.echoType(9.876) == 3.14159",
203 "example.echoType('test string') == 'Success!'",
204 "example.echoType() == null", // Too few arguments
206 // Comparing floats that aren't integer-valued is usually problematic due
207 // to rounding, but exact powers of 2 should also be safe.
208 "example.plus(2.5, 18.0) == 20.5",
209 "example.plus(2, 3.25) == 5.25",
210 "example.plus(2, 3) == 5",
211 "example.plus() == null", // Too few arguments
212 "example.plus(1) == null", // Too few arguments
213 "example.plus(1, 'test') == null", // Wrong argument type
214 "example.plus('test', 2) == null", // Wrong argument type
215 "example.plus('one', 'two') == null", // Wrong argument type
216 "" // Array end marker: insert additional test pairs before this.
219 for (int i
= 0; tests
[i
] != ""; i
++)
222 ExecuteJavaScript("example.my_value = 3.25; example.my_other_value = 1.25;");
223 CheckTrue("example.plus(example.my_value, example.my_other_value) == 4.5");
226 // Tests that invoking a nonexistent method with no fallback method stops the
227 // script's execution
228 TEST_F(CppBoundClassTest
,
229 InvokeNonexistentMethodNoFallback
) {
230 std::string js
= "example.nonExistentMethod();document.writeln('SUCCESS');";
231 CheckJavaScriptFailure(js
);
234 // Ensures existent methods can be invoked successfully when the fallback method
236 TEST_F(CppBoundClassWithFallbackMethodTest
,
237 InvokeExistentMethodsWithFallback
) {
238 CheckTrue("example.echoValue(34) == 34");
241 } // namespace content