Reputation: 2235
I'm making a class that will act as a facade into script loading. This class will interact with a headless UIWebView loaded with HTML&JS files on disk.
I'm currently doing all of my execution in the unit testing environment, and it looks like the UIWebView refuses to load anything. Here's what my code looks like:
WebView Init
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0,0,0)];
self.webView.delegate = self;
[self loadScriptingCore];
Script Loader:
- (void)loadScriptingCore
{
NSURLRequest *loadRequest = [NSURLRequest requestWithURL:[self scriptingCoreIndex]];
[self.webView loadRequest:loadRequest];
NSLog([self inspectDom]);
}
- (NSURL *) scriptingCoreIndex
{
NSString *indexPath = [[NSBundle mainBundle] pathForResource:@"scripting-core" ofType:@"html" inDirectory:@"www"];
NSLog([NSString stringWithFormat:@"Scripting Core Index: %@", indexPath]);
return [NSURL fileURLWithPath:indexPath];
}
- (NSString *)inspectDom
{
return [self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML;"];
}
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Scripting Core</title>
</head>
<body>
<div id="element">
Hello
</div>
</body>
</html>
The inspectDom method only ever returns
<html><head></head><body></body></html>
Thich indicates to me that nothing ever happens to the webView. Additionally, the delegate methods don't webViewDidStartLoad, webViewDidFinishLoad and webViewDidFailLoad appear to be firing.
Any suggestions would be appreciated
Thanks!
Upvotes: 0
Views: 971
Reputation: 2050
In Swift, if you're still using UIWebView, and you want to test its content after calling load(data: ...), you can try the following:
class TestCase: XCTestCase {
var testDelegate: TestDelegate()
lazy var loadExpectation: XCTestExpectation = { return self.expectation(description: "waiting") }()
func testSomething() {
testDelegate.expectation = loadExpectation
webViewUnderTest.delegate = testDelegate
webViewUnderTest.load(data: ...)
waitForExpectations(timeout: 5) { (error) in
dump(error)
}
assert(...)
}
}
class TestDelegate: NSObject, UIWebViewDelegate {
var expectation: XCTestExpectation?
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
return true
}
func webViewDidFinishLoad(_ webView: UIWebView) {
expectation?.fulfill()
}
}
Upvotes: 0
Reputation: 2235
The gist of the problem for the tests is that UIWebView loading is asynchronous. I experimented with [NSThread sleepForTimeInterval] after firing the request, but that was not sufficient. Apparently the main thread needed to be alive for the UIWebView to load asynchronously.
I was able to get my unit tests to pass by using this Async testing mechanism:
https://github.com/akisute/SenAsyncTestCase
This code uses the NSRunLoop to spin the run loop while keeping the main thread alive - sort of like a pseudo-sleep. Adding a 1/10th of a second wait in my test, after the script load was requested, resulted in the DOM being correctly loaded and the delegate events firing.
[self waitForTimeout: 0.1];
Upvotes: 2
Reputation: 684
Make sure in your @ implementation that you set the class as a delegate
@implementation myclass:parent <UIWebViewDelegate>
And what is the output of NSLog([NSString stringWithFormat:@"Scripting Core Index: %@", indexPath]);
?
Upvotes: 0