CDVWKWebViewEngineTest.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. Licensed to the Apache Software Foundation (ASF) under one
  3. or more contributor license agreements. See the NOTICE file
  4. distributed with this work for additional information
  5. regarding copyright ownership. The ASF licenses this file
  6. to you under the Apache License, Version 2.0 (the
  7. "License"); you may not use this file except in compliance
  8. with the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing,
  11. software distributed under the License is distributed on an
  12. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. KIND, either express or implied. See the License for the
  14. specific language governing permissions and limitations
  15. under the License.
  16. */
  17. #import <UIKit/UIKit.h>
  18. #import <XCTest/XCTest.h>
  19. #import "CDVWKWebViewEngine.h"
  20. #import "CDVWKProcessPoolFactory.h"
  21. #import <Cordova/NSDictionary+CordovaPreferences.h>
  22. #import <Cordova/CDVAvailability.h>
  23. @interface CDVWKWebViewEngineTest : XCTestCase
  24. @property (nonatomic, strong) CDVWKWebViewEngine* plugin;
  25. @property (nonatomic, strong) CDVViewController* viewController;
  26. @end
  27. @interface CDVWKWebViewEngine ()
  28. // TODO: expose private interface, if needed
  29. - (BOOL)shouldReloadWebView;
  30. - (BOOL)shouldReloadWebView:(NSURL*)location title:(NSString*)title;
  31. @end
  32. @interface CDVViewController ()
  33. // expose property as readwrite, for test purposes
  34. @property (nonatomic, readwrite, strong) NSMutableDictionary* settings;
  35. @end
  36. @implementation CDVWKWebViewEngineTest
  37. - (void)setUp {
  38. [super setUp];
  39. // Put setup code here. This method is called before the invocation of each test method in the class.
  40. // NOTE: no app settings are set, so it will rely on default WKWebViewConfiguration settings
  41. self.plugin = [[CDVWKWebViewEngine alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
  42. self.viewController = [[CDVViewController alloc] init];
  43. [self.viewController registerPlugin:self.plugin withClassName:NSStringFromClass([self.plugin class])];
  44. XCTAssert([self.plugin conformsToProtocol:@protocol(CDVWebViewEngineProtocol)], @"Plugin does not conform to CDVWebViewEngineProtocol");
  45. }
  46. - (void)tearDown {
  47. // Put teardown code here. This method is called after the invocation of each test method in the class.
  48. [super tearDown];
  49. }
  50. - (void) testCanLoadRequest {
  51. NSURLRequest* fileUrlRequest = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:@"path/to/file.html"]];
  52. NSURLRequest* httpUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://apache.org"]];
  53. NSURLRequest* miscUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"foo://bar"]];
  54. id<CDVWebViewEngineProtocol> webViewEngineProtocol = self.plugin;
  55. SEL wk_sel = NSSelectorFromString(@"loadFileURL:allowingReadAccessToURL:");
  56. if ([self.plugin.engineWebView respondsToSelector:wk_sel]) {
  57. XCTAssertTrue([webViewEngineProtocol canLoadRequest:fileUrlRequest]);
  58. } else {
  59. XCTAssertFalse([webViewEngineProtocol canLoadRequest:fileUrlRequest]);
  60. }
  61. XCTAssertTrue([webViewEngineProtocol canLoadRequest:httpUrlRequest]);
  62. XCTAssertTrue([webViewEngineProtocol canLoadRequest:miscUrlRequest]);
  63. }
  64. - (void) testUpdateInfo {
  65. // Add -ObjC to Other Linker Flags to test project, to load Categories
  66. // Update objc test template generator as well
  67. id<CDVWebViewEngineProtocol> webViewEngineProtocol = self.plugin;
  68. WKWebView* wkWebView = (WKWebView*)self.plugin.engineWebView;
  69. // iOS >=10 defaults to NO, < 10 defaults to YES.
  70. BOOL mediaPlaybackRequiresUserActionDefault = IsAtLeastiOSVersion(@"10.0")? NO : YES;
  71. NSDictionary* preferences = @{
  72. [@"MinimumFontSize" lowercaseString] : @1.1, // default is 0.0
  73. [@"AllowInlineMediaPlayback" lowercaseString] : @YES, // default is NO
  74. [@"MediaPlaybackRequiresUserAction" lowercaseString] : @(!mediaPlaybackRequiresUserActionDefault), // default is NO on iOS >= 10, YES for < 10
  75. [@"SuppressesIncrementalRendering" lowercaseString] : @YES, // default is NO
  76. [@"MediaPlaybackAllowsAirPlay" lowercaseString] : @NO, // default is YES
  77. [@"DisallowOverscroll" lowercaseString] : @YES, // so bounces is to be NO. defaults to NO
  78. [@"WKWebViewDecelerationSpeed" lowercaseString] : @"fast" // default is 'normal'
  79. };
  80. NSDictionary* info = @{
  81. kCDVWebViewEngineWebViewPreferences : preferences
  82. };
  83. [webViewEngineProtocol updateWithInfo:info];
  84. // the only preference we can set, we **can** change this during runtime
  85. XCTAssertEqualWithAccuracy(wkWebView.configuration.preferences.minimumFontSize, 1.1, 0.0001);
  86. // the WKWebViewConfiguration properties, we **cannot** change outside of initialization
  87. if (IsAtLeastiOSVersion(@"10.0")) {
  88. XCTAssertFalse(wkWebView.configuration.mediaPlaybackRequiresUserAction);
  89. } else {
  90. XCTAssertTrue(wkWebView.configuration.mediaPlaybackRequiresUserAction);
  91. }
  92. XCTAssertFalse(wkWebView.configuration.allowsInlineMediaPlayback);
  93. XCTAssertFalse(wkWebView.configuration.suppressesIncrementalRendering);
  94. XCTAssertTrue(wkWebView.configuration.mediaPlaybackAllowsAirPlay);
  95. // in the test above, DisallowOverscroll is YES, so no bounce
  96. if ([wkWebView respondsToSelector:@selector(scrollView)]) {
  97. XCTAssertFalse(((UIScrollView*)[wkWebView scrollView]).bounces);
  98. } else {
  99. for (id subview in wkWebView.subviews) {
  100. if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
  101. XCTAssertFalse(((UIScrollView*)subview).bounces = NO);
  102. }
  103. }
  104. }
  105. XCTAssertTrue(wkWebView.scrollView.decelerationRate == UIScrollViewDecelerationRateFast);
  106. }
  107. - (void) testConfigurationFromSettings {
  108. // we need to re-set the plugin from the "setup" to take in the app settings we need
  109. self.plugin = [[CDVWKWebViewEngine alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
  110. self.viewController = [[CDVViewController alloc] init];
  111. // generate the app settings
  112. // iOS >=10 defaults to NO, < 10 defaults to YES.
  113. BOOL mediaPlaybackRequiresUserActionDefault = IsAtLeastiOSVersion(@"10.0")? NO : YES;
  114. NSDictionary* settings = @{
  115. [@"MinimumFontSize" lowercaseString] : @1.1, // default is 0.0
  116. [@"AllowInlineMediaPlayback" lowercaseString] : @YES, // default is NO
  117. [@"MediaPlaybackRequiresUserAction" lowercaseString] : @(!mediaPlaybackRequiresUserActionDefault), // default is NO on iOS >= 10, YES for < 10
  118. [@"SuppressesIncrementalRendering" lowercaseString] : @YES, // default is NO
  119. [@"MediaPlaybackAllowsAirPlay" lowercaseString] : @NO, // default is YES
  120. [@"DisallowOverscroll" lowercaseString] : @YES, // so bounces is to be NO. defaults to NO
  121. [@"WKWebViewDecelerationSpeed" lowercaseString] : @"fast" // default is 'normal'
  122. };
  123. // this can be set because of the Category at the top of the file
  124. self.viewController.settings = [settings mutableCopy];
  125. // app settings are read after you register the plugin
  126. [self.viewController registerPlugin:self.plugin withClassName:NSStringFromClass([self.plugin class])];
  127. XCTAssert([self.plugin conformsToProtocol:@protocol(CDVWebViewEngineProtocol)], @"Plugin does not conform to CDVWebViewEngineProtocol");
  128. // after registering (thus plugin initialization), we can grab the webview configuration
  129. WKWebView* wkWebView = (WKWebView*)self.plugin.engineWebView;
  130. // the only preference we can set, we **can** change this during runtime
  131. XCTAssertEqualWithAccuracy(wkWebView.configuration.preferences.minimumFontSize, 1.1, 0.0001);
  132. // the WKWebViewConfiguration properties, we **cannot** change outside of initialization
  133. if (IsAtLeastiOSVersion(@"10.0")) {
  134. XCTAssertTrue(wkWebView.configuration.mediaPlaybackRequiresUserAction);
  135. } else {
  136. XCTAssertFalse(wkWebView.configuration.mediaPlaybackRequiresUserAction);
  137. }
  138. XCTAssertTrue(wkWebView.configuration.allowsInlineMediaPlayback);
  139. XCTAssertTrue(wkWebView.configuration.suppressesIncrementalRendering);
  140. // The test case below is in a separate test "testConfigurationWithMediaPlaybackAllowsAirPlay" (Apple bug)
  141. // XCTAssertFalse(wkWebView.configuration.mediaPlaybackAllowsAirPlay);
  142. // in the test above, DisallowOverscroll is YES, so no bounce
  143. if ([wkWebView respondsToSelector:@selector(scrollView)]) {
  144. XCTAssertFalse(((UIScrollView*)[wkWebView scrollView]).bounces);
  145. } else {
  146. for (id subview in wkWebView.subviews) {
  147. if ([[subview class] isSubclassOfClass:[UIScrollView class]]) {
  148. XCTAssertFalse(((UIScrollView*)subview).bounces = NO);
  149. }
  150. }
  151. }
  152. XCTAssertTrue(wkWebView.scrollView.decelerationRate == UIScrollViewDecelerationRateFast);
  153. }
  154. - (void) testShouldReloadWebView {
  155. WKWebView* wkWebView = (WKWebView*)self.plugin.engineWebView;
  156. NSURL* about_blank = [NSURL URLWithString:@"about:blank"];
  157. NSURL* real_site = [NSURL URLWithString:@"https://cordova.apache.org"];
  158. NSString* empty_title_document = @"<html><head><title></title></head></html>";
  159. // about:blank should reload
  160. [wkWebView loadRequest:[NSURLRequest requestWithURL:about_blank]];
  161. XCTAssertTrue([self.plugin shouldReloadWebView]);
  162. // a network location should *not* reload
  163. [wkWebView loadRequest:[NSURLRequest requestWithURL:real_site]];
  164. XCTAssertFalse([self.plugin shouldReloadWebView]);
  165. // document with empty title should *not* reload
  166. // baseURL:nil results in about:blank, so we use a dummy here
  167. [wkWebView loadHTMLString:empty_title_document baseURL:[NSURL URLWithString:@"about:"]];
  168. XCTAssertFalse([self.plugin shouldReloadWebView]);
  169. // Anecdotal assertion that when the WKWebView process has died,
  170. // the title is nil, should always reload
  171. XCTAssertTrue([self.plugin shouldReloadWebView:about_blank title:nil]);
  172. XCTAssertTrue([self.plugin shouldReloadWebView:real_site title:nil]);
  173. // about:blank should always reload
  174. XCTAssertTrue([self.plugin shouldReloadWebView:about_blank title:@"some title"]);
  175. // non about:blank with a non-nil title should **not** reload
  176. XCTAssertFalse([self.plugin shouldReloadWebView:real_site title:@""]);
  177. }
  178. - (void) testConfigurationWithMediaPlaybackAllowsAirPlay {
  179. WKWebViewConfiguration* configuration = [WKWebViewConfiguration new];
  180. configuration.allowsAirPlayForMediaPlayback = NO;
  181. WKWebView* wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration];
  182. XCTAssertFalse(configuration.allowsAirPlayForMediaPlayback);
  183. // Uh-oh, bug in WKWebView below. Tested on iOS 9, iOS 10 beta 3
  184. XCTAssertFalse(wkWebView.configuration.allowsAirPlayForMediaPlayback);
  185. }
  186. - (void) testWKProcessPoolFactory {
  187. WKProcessPool* shared = [[CDVWKProcessPoolFactory sharedFactory] sharedProcessPool];
  188. XCTAssertTrue(shared != nil);
  189. }
  190. @end