Skip to content

Commit

Permalink
Add Future on asynchronous functions
Browse files Browse the repository at this point in the history
- Add podspec subspec for Future
- Add Future example in readme
  • Loading branch information
phimage committed Nov 27, 2015
1 parent 7ef5047 commit 80dbf31
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 27 deletions.
7 changes: 6 additions & 1 deletion Erik.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Pod::Spec.new do |s|

# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
s.name = "Erik"
s.version = "1.0.1"
s.version = "1.0.2"
s.summary = "An headless brother written in Swift"
s.description = <<-DESC
Erik is an headless browser based on WebKit and HTML parser Kanna.
Expand Down Expand Up @@ -31,6 +31,11 @@ Pod::Spec.new do |s|
sp.source_files = "Erik/*.swift"
end

s.subspec "Future" do |sp|
sp.source_files = "Erik/Future/*.swift"
sp.dependency 'BrightFutures'
end

s.dependency 'Kanna'
s.dependency 'Eki'

Expand Down
14 changes: 14 additions & 0 deletions Erik.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
C4D50DDE1BFB51130053B624 /* Erik.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D50DDC1BFB51130053B624 /* Erik.swift */; };
C4D50DEC1BFB58EE0053B624 /* Erik.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C431787F1BFA3E1A00C04250 /* Erik.framework */; };
C4D50DF21BFB59030053B624 /* ErikTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42828E61BF9EDE1005EC7C3 /* ErikTests.swift */; };
C4F7D01C1C088A0100EF359B /* Future.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F7D01B1C088A0100EF359B /* Future.swift */; };
C4F7D01D1C088A0100EF359B /* Future.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F7D01B1C088A0100EF359B /* Future.swift */; };
E0D1B8CBEC687F5EE711EAC1 /* Pods_ErikOSX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A34CAB2D6E9C56DE435463C /* Pods_ErikOSX.framework */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -68,6 +70,7 @@
C4D50DEB1BFB58EE0053B624 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C4DF857E1C04AD0A0002E142 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../Eki/README.md; sourceTree = "<group>"; };
C4DF857F1C04ADDA0002E142 /* Erik.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = Erik.podspec; sourceTree = "<group>"; };
C4F7D01B1C088A0100EF359B /* Future.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Future.swift; path = Future/Future.swift; sourceTree = "<group>"; };
C735044BB44C9D1E52EB9784 /* Pods-Erik.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Erik.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Erik/Pods-Erik.debug.xcconfig"; sourceTree = "<group>"; };
E64C9E85EE53CF0A28E97D7D /* Pods-Erik.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Erik.release.xcconfig"; path = "Pods/Target Support Files/Pods-Erik/Pods-Erik.release.xcconfig"; sourceTree = "<group>"; };
EEC248EA8E4AD2CD57F9011A /* Pods-ErikOSXTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ErikOSXTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ErikOSXTests/Pods-ErikOSXTests.debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -171,6 +174,7 @@
C4D50DDC1BFB51130053B624 /* Erik.swift */,
C42828F51BF9EEAF005EC7C3 /* LayoutEngine.swift */,
C463134B1BFCE3A50078FB9D /* Document.swift */,
C4F7D01A1C0889A700EF359B /* Future */,
);
path = Erik;
sourceTree = "<group>";
Expand Down Expand Up @@ -201,6 +205,14 @@
path = ErikOSXTests;
sourceTree = "<group>";
};
C4F7D01A1C0889A700EF359B /* Future */ = {
isa = PBXGroup;
children = (
C4F7D01B1C088A0100EF359B /* Future.swift */,
);
name = Future;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -542,6 +554,7 @@
files = (
C4D50DDD1BFB51130053B624 /* Erik.swift in Sources */,
C463134C1BFCE3A50078FB9D /* Document.swift in Sources */,
C4F7D01C1C088A0100EF359B /* Future.swift in Sources */,
C42828F61BF9EEAF005EC7C3 /* LayoutEngine.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -560,6 +573,7 @@
files = (
C4D50DDE1BFB51130053B624 /* Erik.swift in Sources */,
C463134D1BFCE3FF0078FB9D /* Document.swift in Sources */,
C4F7D01D1C088A0100EF359B /* Future.swift in Sources */,
C43178891BFA3E2200C04250 /* LayoutEngine.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
26 changes: 20 additions & 6 deletions Erik/Document.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
//
// HTMLDocument.swift
// Document.swift
// Erik
//
// Created by phimage on 18/11/15.
// Copyright © 2015 phimage. All rights reserved.
//

/*
The MIT License (MIT)
Copyright (c) 2015 Eric Marchand (phimage)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import Foundation

public protocol HTMLParser {
Expand Down
23 changes: 19 additions & 4 deletions Erik/Erik.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
//
// Erik.swift
// Erik
//
// Created by phimage on 17/11/15.
// Copyright © 2015 phimage. All rights reserved.
//
/*
The MIT License (MIT)
Copyright (c) 2015 Eric Marchand (phimage)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

import Foundation
import WebKit
Expand Down
87 changes: 87 additions & 0 deletions Erik/Future/Future.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//
// Future.swift
// Erik
/*
The MIT License (MIT)
Copyright (c) 2015 Eric Marchand (phimage)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/


import Foundation
import BrightFutures
import Result

extension Erik {

public func visitURLFuture(url: NSURL) -> Future<Document, NSError> {
let promise = Promise<Document, NSError>()

self.visitURL(url) { (obj, err) -> Void in
if let document = obj {
promise.success(document)
}
else if let error = err {
promise.failure(error as NSError)
}
}

return promise.future
}

public func currentContentFuture() -> Future<Document, NSError> {
let promise = Promise<Document, NSError>()

self.currentContent { (obj, err) -> Void in
if let document = obj {
promise.success(document)
}
else if let error = err {
promise.failure(error as NSError)
}
}

return promise.future
}

public func evaluateJavaScriptFuture(javaScriptString: String) -> Future<AnyObject?, NSError> {
let promise = Promise<AnyObject?, NSError>()

self.evaluateJavaScript(javaScriptString) { (obj, err) -> Void in
if let error = err {
promise.failure(error as NSError)
}
else {
promise.success(obj)
}
}

return promise.future
}

public static func visitURLFuture(url: NSURL) -> Future<Document, NSError> {
return Erik.sharedInstance.visitURLFuture(url)
}

public static func currentContentFuture() -> Future<Document, NSError> {
return Erik.sharedInstance.currentContentFuture()
}

public static func evaluateJavaScriptFuture(javaScriptString: String) -> Future<AnyObject?, NSError> {
return Erik.sharedInstance.evaluateJavaScriptFuture(javaScriptString)
}
}
26 changes: 20 additions & 6 deletions Erik/LayoutEngine.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
//
// WebKit.swift
// LayoutEngine.swift
// Erik
//
// Created by phimage on 16/11/15.
// Copyright © 2015 phimage. All rights reserved.
//

/*
The MIT License (MIT)
Copyright (c) 2015 Eric Marchand (phimage)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import Foundation

public protocol JavaScriptEvaluator {
Expand Down
61 changes: 59 additions & 2 deletions ErikTests/ErikTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ import XCTest
@testable import Erik
import Eki
import FileKit
import BrightFutures





class ErikTests: XCTestCase {

let url = NSURL(string:"http://www.google.com")!
#if os(OSX)
let googleFormSelector = "f"
#elseif os(iOS)
let googleFormSelector = "gs"
#endif

override func setUp() {
super.setUp()
Expand All @@ -36,10 +46,11 @@ class ErikTests: XCTestCase {
self.waitForExpectationsWithTimeout(5, handler: nil)
}


func testSubmit() {

let visitExpectation = self.expectationWithDescription("visit")
let inputExpectation = self.expectationWithDescription("getInput")
let submitExpectation = self.expectationWithDescription("submit")
let currentContentExpectation = self.expectationWithDescription("currentContent")

Erik.visitURL(url) { (obj, err) -> Void in
Expand All @@ -54,6 +65,7 @@ class ErikTests: XCTestCase {
//print(doc)
// do a google search
for input in doc.querySelectorAll("input[name='q']") {
inputExpectation.fulfill()
print(input)

let value: String? = "test"
Expand All @@ -75,7 +87,8 @@ class ErikTests: XCTestCase {
XCTFail("not parsable")
}

for input in doc.querySelectorAll("form[name=\"f\"]") {
for input in doc.querySelectorAll("form[name='\(self.googleFormSelector)']") {
submitExpectation.fulfill()
if let form = input as? Form {
form.submit()
}
Expand Down Expand Up @@ -270,5 +283,49 @@ class ErikTests: XCTestCase {
}
}
}

func testFuture() {
let value: String? = "test"

let visitExpectation = self.expectationWithDescription("visit")
let browser = Erik()

var future: Future<Document, NSError> = browser.visitURLFuture(url)

future = future.flatMap { document -> Future<Document, NSError> in

if let input = document.querySelector("input[name='q']") {
input["value"] = value
}
return browser.currentContentFuture()
}

future = future.flatMap { document -> Future<Document, NSError> in

if let input2 = document.querySelector("input[name='q']") {
print(input2)
XCTAssertEqual(value, input2["value"])
}

if let form = document.querySelector("form[name=\"\(self.googleFormSelector)\"]") as? Form {
form.submit()
}

return browser.currentContentFuture()
}

future.onSuccess { document in
visitExpectation.fulfill()
}
future.onFailure { error in
XCTFail("\(error)")
}

self.waitForExpectationsWithTimeout(20, handler: { error in
XCTAssertNil(error, "Oh, we got timeout")
})

}


}
Loading

0 comments on commit 80dbf31

Please sign in to comment.