OLD | NEW |
| (Empty) |
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. | |
4 | |
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. | |
8 | |
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" | |
17 | |
18 using webkit_glue::CppArgumentList; | |
19 using webkit_glue::CppVariant; | |
20 | |
21 namespace content { | |
22 | |
23 namespace { | |
24 | |
25 class CppBindingExampleSubObject : public CppBindingExample { | |
26 public: | |
27 CppBindingExampleSubObject() { | |
28 sub_value_.Set("sub!"); | |
29 BindProperty("sub_value", &sub_value_); | |
30 } | |
31 private: | |
32 CppVariant sub_value_; | |
33 }; | |
34 | |
35 | |
36 class CppBindingExampleWithOptionalFallback : public CppBindingExample { | |
37 public: | |
38 CppBindingExampleWithOptionalFallback() { | |
39 BindProperty("sub_object", sub_object_.GetAsCppVariant()); | |
40 } | |
41 | |
42 void set_fallback_method_enabled(bool state) { | |
43 BindFallbackCallback(state ? | |
44 base::Bind(&CppBindingExampleWithOptionalFallback::fallbackMethod, | |
45 base::Unretained(this)) | |
46 : CppBoundClass::Callback()); | |
47 } | |
48 | |
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) { | |
52 } | |
53 | |
54 private: | |
55 CppBindingExampleSubObject sub_object_; | |
56 }; | |
57 | |
58 class TestObserver : public RenderViewObserver { | |
59 public: | |
60 explicit TestObserver(RenderView* render_view) | |
61 : RenderViewObserver(render_view) {} | |
62 virtual void DidClearWindowObject(blink::WebFrame* frame) OVERRIDE { | |
63 example_bound_class_.BindToJavascript(frame, "example"); | |
64 } | |
65 void set_fallback_method_enabled(bool use_fallback) { | |
66 example_bound_class_.set_fallback_method_enabled(use_fallback); | |
67 } | |
68 private: | |
69 CppBindingExampleWithOptionalFallback example_bound_class_; | |
70 }; | |
71 | |
72 } // namespace | |
73 | |
74 class CppBoundClassTest : public RenderViewTest { | |
75 public: | |
76 CppBoundClassTest() {} | |
77 | |
78 virtual void SetUp() OVERRIDE { | |
79 RenderViewTest::SetUp(); | |
80 observer_.reset(new TestObserver(view_)); | |
81 observer_->set_fallback_method_enabled(useFallback()); | |
82 | |
83 blink::WebURLRequest url_request; | |
84 url_request.initialize(); | |
85 url_request.setURL(GURL(kAboutBlankURL)); | |
86 | |
87 GetMainFrame()->loadRequest(url_request); | |
88 ProcessPendingMessages(); | |
89 } | |
90 | |
91 virtual void TearDown() OVERRIDE { | |
92 observer_.reset(); | |
93 RenderViewTest::TearDown(); | |
94 } | |
95 | |
96 // Executes the specified JavaScript and checks that the resulting document | |
97 // text is empty. | |
98 void CheckJavaScriptFailure(const std::string& javascript) { | |
99 ExecuteJavaScript(javascript.c_str()); | |
100 EXPECT_EQ( | |
101 "", | |
102 UTF16ToASCII(GetMainFrame()->document().documentElement().innerText())); | |
103 } | |
104 | |
105 void CheckTrue(const std::string& expression) { | |
106 int was_page_a = -1; | |
107 base::string16 check_page_a = | |
108 base::ASCIIToUTF16(std::string("Number(") + expression + ")"); | |
109 EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a)); | |
110 EXPECT_EQ(1, was_page_a); | |
111 } | |
112 | |
113 protected: | |
114 virtual bool useFallback() { | |
115 return false; | |
116 } | |
117 | |
118 private: | |
119 scoped_ptr<TestObserver> observer_; | |
120 }; | |
121 | |
122 class CppBoundClassWithFallbackMethodTest : public CppBoundClassTest { | |
123 protected: | |
124 virtual bool useFallback() OVERRIDE { | |
125 return true; | |
126 } | |
127 }; | |
128 | |
129 // Ensures that the example object has been bound to JS. | |
130 TEST_F(CppBoundClassTest, ObjectExists) { | |
131 CheckTrue("typeof window.example == 'object'"); | |
132 | |
133 // An additional check to test our test. | |
134 CheckTrue("typeof window.invalid_object == 'undefined'"); | |
135 } | |
136 | |
137 TEST_F(CppBoundClassTest, PropertiesAreInitialized) { | |
138 CheckTrue("example.my_value == 10"); | |
139 | |
140 CheckTrue("example.my_other_value == 'Reinitialized!'"); | |
141 } | |
142 | |
143 TEST_F(CppBoundClassTest, SubOject) { | |
144 CheckTrue("typeof window.example.sub_object == 'object'"); | |
145 | |
146 CheckTrue("example.sub_object.sub_value == 'sub!'"); | |
147 } | |
148 | |
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. | |
158 }; | |
159 | |
160 for (int i = 0; tests[i] != ""; i += 2) { | |
161 std::string left = tests[i]; | |
162 std::string right = tests[i + 1]; | |
163 // left = right; | |
164 std::string js = left; | |
165 js.append(" = "); | |
166 js.append(right); | |
167 js.append(";"); | |
168 ExecuteJavaScript(js.c_str()); | |
169 std::string expression = left; | |
170 expression += " == "; | |
171 expression += right; | |
172 CheckTrue(expression); | |
173 } | |
174 } | |
175 | |
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"); | |
181 | |
182 ExecuteJavaScript("example.my_value_with_callback = 11;"); | |
183 CheckTrue("example.my_value_with_callback == 11"); | |
184 | |
185 CheckTrue("example.same == 42"); | |
186 | |
187 ExecuteJavaScript("example.same = 24;"); | |
188 CheckTrue("example.same == 42"); | |
189 } | |
190 | |
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 | |
199 | |
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 | |
205 | |
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. | |
217 }; | |
218 | |
219 for (int i = 0; tests[i] != ""; i++) | |
220 CheckTrue(tests[i]); | |
221 | |
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"); | |
224 } | |
225 | |
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); | |
232 } | |
233 | |
234 // Ensures existent methods can be invoked successfully when the fallback method | |
235 // is used | |
236 TEST_F(CppBoundClassWithFallbackMethodTest, | |
237 InvokeExistentMethodsWithFallback) { | |
238 CheckTrue("example.echoValue(34) == 34"); | |
239 } | |
240 | |
241 } // namespace content | |
OLD | NEW |