Fix breakages in https://codereview.chromium.org/1155713003/
[chromium-blink-merge.git] / ios / web / web_state / js / crw_js_injection_manager_unittest.mm
blob854bde23a5e3e0b70dd27db4c17e1eca15f45807
1 // Copyright 2013 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 #import <UIKit/UIWebView.h>
7 #include "ios/web/public/test/web_test_util.h"
8 #import "ios/web/public/web_state/js/crw_js_injection_manager.h"
9 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
10 #include "ios/web/test/web_test.h"
11 #import "testing/gtest_mac.h"
13 // Testing class of JsInjectioManager that has no dependencies.
14 @interface TestingCRWJSBaseManager : CRWJSInjectionManager
15 @end
17 @implementation TestingCRWJSBaseManager
19 - (NSString*)presenceBeacon {
20   return @"base";
23 - (NSString*)staticInjectionContent {
24   return @"base = {};";
27 @end
29 // Testing class of JsInjectionManager that has no dependencies.
30 @interface TestingAnotherCRWJSBaseManager : CRWJSInjectionManager
31 @end
33 @implementation TestingAnotherCRWJSBaseManager
35 - (NSString*)presenceBeacon {
36   return @"anotherbase";
39 - (NSString*)staticInjectionContent {
40   return @"anotherbase = {};";
43 @end
45 // Testing class of JsInjectioManager that has dependencies.
46 @interface TestingJsManager : CRWJSInjectionManager
47 @end
49 @implementation TestingJsManager
51 - (NSString*)presenceBeacon {
52   return @"base['testingjs']";
55 - (NSString*)staticInjectionContent {
56   return @"base['testingjs'] = {};";
59 - (NSArray*)directDependencies {
60   return @[ [TestingCRWJSBaseManager class] ];
63 @end
65 // Testing class of JsInjectioManager that has dynamic content.
66 @interface TestingDynamicJsManager : CRWJSInjectionManager
67 @end
69 @implementation TestingDynamicJsManager
71 - (NSString*)presenceBeacon {
72   return @"dynamic";
75 - (NSString*)injectionContent {
76   static int i = 0;
77   return [NSString stringWithFormat:@"dynamic = {}; dynamic['foo'] = %d;", ++i];
80 - (NSString*)staticInjectionContent {
81   // This should never be called on a manager that has dynamic content.
82   NOTREACHED();
83   return nil;
86 @end
89 // Testing class of JsInjectioManager that has dependencies.
90 @interface TestingAnotherJsManager : CRWJSInjectionManager
91 @end
93 @implementation TestingAnotherJsManager
95 - (NSString*)presenceBeacon {
96   return @"base['anothertestingjs']";
99 - (NSString*)staticInjectionContent {
100   return @"base['anothertestingjs'] = {};";
103 - (NSArray*)directDependencies {
104   return @[ [TestingCRWJSBaseManager class] ];
107 @end
110 // Testing class of JsInjectioManager that has nested dependencies.
111 @interface TestingJsManagerWithNestedDependencies : CRWJSInjectionManager
112 @end
114 @implementation TestingJsManagerWithNestedDependencies
116 - (NSString*)presenceBeacon {
117   return @"base['testingjswithnesteddependencies']";
120 - (NSString*)staticInjectionContent {
121   return @"base['testingjswithnesteddependencies'] = {};";
124 - (NSArray*)directDependencies {
125   return @[[TestingJsManager class]];
128 @end
130 // Testing class of JsInjectioManager that has nested dependencies.
131 @interface TestingJsManagerComplex : CRWJSInjectionManager
132 @end
134 @implementation TestingJsManagerComplex
136 - (NSString*)presenceBeacon {
137   return @"base['testingjswithnesteddependencies']['complex']";
140 - (NSString*)staticInjectionContent {
141   return @"base['testingjswithnesteddependencies']['complex'] = {};";
144 - (NSArray*)directDependencies {
145   return @[
146     [TestingJsManagerWithNestedDependencies class],
147     [TestingAnotherJsManager class],
148     [TestingAnotherCRWJSBaseManager class],
149   ];
152 @end
154 #pragma mark -
156 namespace {
158 // A mixin class for testing with CRWWKWebViewWebController or
159 // CRWUIWebViewWebController.
160 template <typename WebTestT>
161 class JsInjectionManagerTest : public WebTestT {
162  protected:
163   virtual void SetUp() override {
164     WebTestT::SetUp();
165     // Loads a dummy page to prepare JavaScript evaluation.
166     NSString* const kPageContent = @"<html><body><div></div></body></html>";
167     WebTestT::LoadHtml(kPageContent);
168   }
169   // Returns the manager of the given class.
170   CRWJSInjectionManager* GetInstanceOfClass(Class jsInjectionManagerClass);
171   // Returns true if the receiver_ has all the managers in |managers|.
172   bool HasReceiverManagers(NSArray* managers);
173   // EXPECTs that |actual| consists of the CRWJSInjectionManagers of the
174   // expected classes in a correct order.
175   void TestAllDependencies(NSArray* expected, NSArray* actual);
178 // Concrete test fixture to test UIWebView-based web controller injection.
179 typedef JsInjectionManagerTest<web::UIWebViewWebTest>
180     JsInjectionManagerUIWebViewTest;
182 // Concrete test fixture to test WKWebView-based web controller injection.
183 class JsInjectionManagerWKWebViewTest :
184     public JsInjectionManagerTest<web::WKWebViewWebTest> {
185  protected:
186   void SetUp() override {
187     // SetUp crashes on WKWebView creation if running on iOS7.
188     CR_TEST_REQUIRES_WK_WEB_VIEW();
189     JsInjectionManagerTest<web::WKWebViewWebTest>::SetUp();
190   }
193 template <typename WebTestT>
194 bool JsInjectionManagerTest<WebTestT>::HasReceiverManagers(
195     NSArray* manager_classes) {
196   NSDictionary* receiver_managers =
197       [[WebTestT::webController_ jsInjectionReceiver] managers];
198   for (Class manager_class in manager_classes) {
199     if (![receiver_managers objectForKey:manager_class])
200       return false;
201   }
202   return true;
205 template <typename WebTestT>
206 void JsInjectionManagerTest<WebTestT>::TestAllDependencies(
207     NSArray* expected_classes,
208     NSArray* actual) {
209   EXPECT_EQ([expected_classes count], [actual count]);
211   for (Class manager_class in expected_classes) {
212     CRWJSInjectionManager* expected_manager = GetInstanceOfClass(manager_class);
213     EXPECT_TRUE([actual containsObject:expected_manager]);
214   }
216   for (size_t index = 0; index < [actual count]; ++ index) {
217     CRWJSInjectionManager* manager = [actual objectAtIndex:index];
218     for (Class manager_class in [manager directDependencies]) {
219       CRWJSInjectionManager* dependency = GetInstanceOfClass(manager_class);
220       size_t dependency_index = [actual indexOfObject:dependency];
221       EXPECT_TRUE(index > dependency_index);
222     }
223   }
226 template <typename WebTestT>
227 CRWJSInjectionManager* JsInjectionManagerTest<WebTestT>::GetInstanceOfClass(
228     Class jsInjectionManagerClass) {
229   return [[WebTestT::webController_ jsInjectionReceiver]
230       instanceOfClass:jsInjectionManagerClass];
233 WEB_TEST_F(JsInjectionManagerUIWebViewTest,
234            JsInjectionManagerWKWebViewTest,
235            NoDependencies) {
236   NSUInteger originalCount =
237       [[[this->webController_ jsInjectionReceiver] managers] count];
238   CRWJSInjectionManager* manager =
239       this->GetInstanceOfClass([TestingCRWJSBaseManager class]);
240   EXPECT_TRUE(manager);
241   EXPECT_EQ(originalCount + 1U,
242             [[[this->webController_ jsInjectionReceiver] managers] count]);
243   EXPECT_TRUE(this->HasReceiverManagers(@[ [TestingCRWJSBaseManager class] ]));
244   EXPECT_FALSE([manager hasBeenInjected]);
246   [manager inject];
247   EXPECT_TRUE([manager hasBeenInjected]);
250 WEB_TEST_F(JsInjectionManagerUIWebViewTest,
251            JsInjectionManagerWKWebViewTest,
252            HasDependencies) {
253   NSUInteger originalCount =
254       [[[this->webController_ jsInjectionReceiver] managers] count];
255   CRWJSInjectionManager* manager =
256       this->GetInstanceOfClass([TestingJsManager class]);
257   EXPECT_TRUE(manager);
258   EXPECT_EQ(originalCount + 2U,
259             [[[this->webController_ jsInjectionReceiver] managers] count])
260       << "Two more CRWJSInjectionManagers should be created.";
261   EXPECT_TRUE(this->HasReceiverManagers(
262       @[ [TestingCRWJSBaseManager class], [TestingCRWJSBaseManager class] ]));
264   EXPECT_FALSE([manager hasBeenInjected]);
266   [manager inject];
267   EXPECT_TRUE([manager hasBeenInjected]);
268   EXPECT_TRUE([this->GetInstanceOfClass([TestingCRWJSBaseManager class])
269                   hasBeenInjected]);
272 WEB_TEST_F(JsInjectionManagerUIWebViewTest,
273            JsInjectionManagerWKWebViewTest,
274            Dynamic) {
275   CRWJSInjectionManager* manager =
276       this->GetInstanceOfClass([TestingDynamicJsManager class]);
277   EXPECT_TRUE(manager);
279   EXPECT_FALSE([manager hasBeenInjected]);
280   [manager inject];
281   EXPECT_TRUE([manager hasBeenInjected]);
282   // Ensure that content isn't cached.
283   EXPECT_NSNE([manager injectionContent], [manager injectionContent]);
286 WEB_TEST_F(JsInjectionManagerUIWebViewTest,
287            JsInjectionManagerWKWebViewTest,
288            HasNestedDependencies) {
289   NSUInteger originalCount =
290       [[[this->webController_ jsInjectionReceiver] managers] count];
291   CRWJSInjectionManager* manager =
292       this->GetInstanceOfClass([TestingJsManagerWithNestedDependencies class]);
293   EXPECT_TRUE(manager);
294   EXPECT_EQ(originalCount + 3U,
295             [[[this->webController_ jsInjectionReceiver] managers] count])
296       << "Three more CRWJSInjectionManagers should be created.";
297   EXPECT_TRUE(this->HasReceiverManagers(@[
298     [TestingJsManagerWithNestedDependencies class],
299     [TestingCRWJSBaseManager class],
300     [TestingCRWJSBaseManager class]
301   ]));
303   EXPECT_FALSE([manager hasBeenInjected]);
305   [manager inject];
306   EXPECT_TRUE([manager hasBeenInjected]);
307   EXPECT_TRUE(
308       [this->GetInstanceOfClass([TestingJsManager class]) hasBeenInjected]);
309   EXPECT_TRUE([this->GetInstanceOfClass([TestingCRWJSBaseManager class])
310                   hasBeenInjected]);
312   NSArray* list = [manager allDependencies];
313   this->TestAllDependencies(
314       @[
315         [TestingCRWJSBaseManager class],
316         [TestingJsManager class],
317         [TestingJsManagerWithNestedDependencies class]
318       ],
319       list);
322 // Tests that checking for an uninjected presence beacon returns false.
323 WEB_TEST_F(JsInjectionManagerUIWebViewTest,
324            JsInjectionManagerWKWebViewTest,
325            WebControllerCheckForUninjectedScript) {
326   EXPECT_FALSE([this->webController_
327       scriptHasBeenInjectedForClass:Nil
328                      presenceBeacon:@"__gCrWeb.dummyBeacon"]);
331 WEB_TEST_F(JsInjectionManagerUIWebViewTest,
332            JsInjectionManagerWKWebViewTest,
333            AllDependencies) {
334   CRWJSInjectionManager* manager =
335       this->GetInstanceOfClass([TestingJsManagerComplex class]);
336   NSArray* list = [manager allDependencies];
337   this->TestAllDependencies(
338       @[
339         [TestingCRWJSBaseManager class],
340         [TestingAnotherCRWJSBaseManager class],
341         [TestingJsManager class],
342         [TestingAnotherJsManager class],
343         [TestingJsManagerWithNestedDependencies class],
344         [TestingJsManagerComplex class]
345       ],
346       list);
349 }  // namespace