Fix: Retiring Result lib

fix #24
This commit is contained in:
Flávio Caetano 2018-03-06 18:08:28 -03:00
parent 9212a489a5
commit ce03959fe9
16 changed files with 167 additions and 94 deletions

View File

@ -1,11 +1,9 @@
PODS:
- AppSwizzle (1.2)
- ReCaptcha/Core (1.1):
- Result (~> 3.0)
- ReCaptcha/Core (1.1)
- ReCaptcha/RxSwift (1.1):
- ReCaptcha/Core
- RxSwift (~> 4.0)
- Result (3.2.4)
- RxCocoa (4.1.1):
- RxSwift (~> 4.0)
- RxSwift (4.1.1)
@ -31,8 +29,7 @@ CHECKOUT OPTIONS:
SPEC CHECKSUMS:
AppSwizzle: bbd3782652fc426ce59c045a92ec61d36f261984
ReCaptcha: 7a130e2765cf13af3223683400252fe7ae30ca7b
Result: d2d07204ce72856f1fd9130bbe42c35a7b0fea10
ReCaptcha: b94a673f3827e9b9cf7e77db0395694549241247
RxCocoa: fd0862fd2df95fa55562ad28ffd2522c25eb4a85
RxSwift: c6e3b1c7b325c7d121cd4327e9d98b7ed746b570
SwiftLint: 2e4b89feed5909c42c3735bbd6745f4345c4b772

View File

@ -20,6 +20,7 @@
F231B39F1FED4A8C00F82943 /* ReCaptchaDecoder+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F231B39E1FED4A8C00F82943 /* ReCaptchaDecoder+Helper.swift */; };
F288E9451F9537760018688D /* ReCaptchaError+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F288E9441F9537760018688D /* ReCaptchaError+Equatable.swift */; };
F28FAC9F200E425600E14987 /* ReCaptcha_UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F28FAC9E200E425600E14987 /* ReCaptcha_UITests.swift */; };
F2AE8612204F3430002E28D7 /* ReCaptchaResult__Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2AE8611204F3430002E28D7 /* ReCaptchaResult__Tests.swift */; };
F2E2685E1F7AEE3400CD876D /* ReCaptcha__Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2E2685D1F7AEE3400CD876D /* ReCaptcha__Tests.swift */; };
F2ECCF8A1E9FCEFE0097B199 /* ReCaptchaDecoder__Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2ECCF891E9FCEFE0097B199 /* ReCaptchaDecoder__Tests.swift */; };
F2ECCF8C1E9FE37C0097B199 /* mock.html in Resources */ = {isa = PBXBuildFile; fileRef = F2ECCF8B1E9FE37C0097B199 /* mock.html */; };
@ -74,6 +75,7 @@
F28FAC9C200E425600E14987 /* ReCaptcha_UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReCaptcha_UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F28FAC9E200E425600E14987 /* ReCaptcha_UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReCaptcha_UITests.swift; sourceTree = "<group>"; };
F28FACA0200E425600E14987 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F2AE8611204F3430002E28D7 /* ReCaptchaResult__Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReCaptchaResult__Tests.swift; sourceTree = "<group>"; };
F2E2685D1F7AEE3400CD876D /* ReCaptcha__Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReCaptcha__Tests.swift; sourceTree = "<group>"; };
F2ECCF761E9FC47B0097B199 /* ReCaptcha_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReCaptcha_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F2ECCF7A1E9FC47B0097B199 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -211,6 +213,7 @@
F2ECCF8D1E9FE68C0097B199 /* ReCaptchaWebViewManager__Tests.swift */,
F2E2685D1F7AEE3400CD876D /* ReCaptcha__Tests.swift */,
F231B3961FEC325A00F82943 /* DispatchQueue__Tests.swift */,
F2AE8611204F3430002E28D7 /* ReCaptchaResult__Tests.swift */,
);
path = Core;
sourceTree = "<group>";
@ -447,14 +450,12 @@
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-ReCaptcha_Example/Pods-ReCaptcha_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/ReCaptcha/ReCaptcha.framework",
"${BUILT_PRODUCTS_DIR}/Result/Result.framework",
"${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework",
"${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReCaptcha.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Result.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework",
);
@ -595,6 +596,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F2AE8612204F3430002E28D7 /* ReCaptchaResult__Tests.swift in Sources */,
F2ECCF961EA00A5B0097B199 /* ReCaptchaWebViewManager+Helpers.swift in Sources */,
F2ECCF8E1E9FE68C0097B199 /* ReCaptchaWebViewManager__Tests.swift in Sources */,
F2ECCF981EA011370097B199 /* Result+Helpers.swift in Sources */,

View File

@ -55,7 +55,7 @@
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
skipped = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F28FAC9B200E425600E14987"

View File

@ -7,7 +7,6 @@
//
import ReCaptcha
import Result
import RxCocoa
import RxSwift
import UIKit
@ -79,7 +78,6 @@ class ViewController: UIViewController {
.disposed(by: disposeBag)
validate
.map { try $0.dematerialize() }
.bind(to: label.rx.text)
.disposed(by: disposeBag)
}

View File

@ -0,0 +1,39 @@
//
// ReCaptchaResult__Tests.swift
// ReCaptcha
//
// Created by Flávio Caetano on 06/03/18.
// Copyright © 2018 ReCaptcha. All rights reserved.
//
@testable import ReCaptcha
import XCTest
class ReCaptchaResult__Tests: XCTestCase {
func test__Get_Token() {
let token = UUID().uuidString
let result = ReCaptchaResult.token(token)
do {
let value = try result.dematerialize()
XCTAssertEqual(value, token)
}
catch let err {
XCTFail(err.localizedDescription)
}
}
func test__Get_Token__Error() {
let error = ReCaptchaError.random()
let result = ReCaptchaResult.error(error)
do {
_ = try result.dematerialize()
XCTFail("Shouldn't have completed")
}
catch let err {
XCTAssertEqual(err as? ReCaptchaError, error)
}
}
}

View File

@ -8,7 +8,6 @@
@testable import ReCaptcha
import Result
import WebKit
import XCTest
@ -36,7 +35,7 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
func test__Validate__Token() {
let exp1 = expectation(description: "load token")
var result1: ReCaptchaWebViewManager.Response?
var result1: ReCaptchaResult?
// Validate
let manager = ReCaptchaWebViewManager(messageBody: "{token: key}", apiKey: apiKey)
@ -55,12 +54,12 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
// Verify
XCTAssertNotNil(result1)
XCTAssertNil(result1?.error)
XCTAssertEqual(result1?.value, apiKey)
XCTAssertEqual(result1?.token, apiKey)
// Validate again
let exp2 = expectation(description: "reload token")
var result2: ReCaptchaWebViewManager.Response?
var result2: ReCaptchaResult?
// Validate
manager.validate(on: presenterView) { response in
@ -74,7 +73,7 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
// Verify
XCTAssertNotNil(result2)
XCTAssertNil(result2?.error)
XCTAssertEqual(result2?.value, apiKey)
XCTAssertEqual(result2?.token, apiKey)
}
@ -96,7 +95,7 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
func test__Validate__Message_Error() {
var result: ReCaptchaWebViewManager.Response?
var result: ReCaptchaResult?
let exp = expectation(description: "message error")
// Validate
@ -115,11 +114,11 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
// Verify
XCTAssertNotNil(result)
XCTAssertEqual(result?.error, .wrongMessageFormat)
XCTAssertNil(result?.value)
XCTAssertNil(result?.token)
}
func test__Validate__JS_Error() {
var result: ReCaptchaWebViewManager.Response?
var result: ReCaptchaResult?
let exp = expectation(description: "js error")
// Validate
@ -138,7 +137,7 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
// Verify
XCTAssertNotNil(result)
XCTAssertNotNil(result?.error)
XCTAssertNil(result?.value)
XCTAssertNil(result?.token)
switch result!.error! {
case .unexpected(let error as NSError):
@ -210,7 +209,7 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
func test__Key_Setup() {
let exp = expectation(description: "setup key")
var result: ReCaptchaWebViewManager.Response?
var result: ReCaptchaResult?
// Validate
let manager = ReCaptchaWebViewManager(messageBody: "{token: key}", apiKey: apiKey)
@ -227,13 +226,13 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
XCTAssertNotNil(result)
XCTAssertNil(result?.error)
XCTAssertEqual(result?.value, apiKey)
XCTAssertEqual(result?.token, apiKey)
}
func test__Endpoint_Setup() {
let exp = expectation(description: "setup endpoint")
let endpoint = String(describing: arc4random())
var result: ReCaptchaWebViewManager.Response?
let endpoint = ReCaptcha.Endpoint.alternate.url
var result: ReCaptchaResult?
let manager = ReCaptchaWebViewManager(messageBody: "{token: endpoint}", endpoint: endpoint)
manager.configureWebView { _ in
@ -249,14 +248,14 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
XCTAssertNotNil(result)
XCTAssertNil(result?.error)
XCTAssertEqual(result?.value, endpoint)
XCTAssertEqual(result?.token, endpoint)
}
// MARK: Reset
func test__Reset() {
let exp1 = expectation(description: "fail on first execution")
var result1: ReCaptchaWebViewManager.Response?
var result1: ReCaptchaResult?
// Validate
let manager = ReCaptchaWebViewManager(messageBody: "{token: key}", apiKey: apiKey, shouldFail: true)
@ -275,7 +274,7 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
// Resets and tries again
let exp2 = expectation(description: "validates after reset")
var result2: ReCaptchaWebViewManager.Response?
var result2: ReCaptchaResult?
manager.reset()
manager.validate(on: presenterView, resetOnError: false) { result in
@ -285,12 +284,13 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
waitForExpectations(timeout: 10)
XCTAssertEqual(result2?.value, apiKey)
XCTAssertNil(result2?.error)
XCTAssertEqual(result2?.token, apiKey)
}
func test__Validate__Reset_On_Error() {
let exp = expectation(description: "fail on first execution")
var result: ReCaptchaWebViewManager.Response?
var result: ReCaptchaResult?
// Validate
let manager = ReCaptchaWebViewManager(messageBody: "{token: key}", apiKey: apiKey, shouldFail: true)
@ -305,6 +305,8 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
}
waitForExpectations(timeout: 10)
XCTAssertEqual(result?.value, apiKey)
XCTAssertNil(result?.error)
XCTAssertEqual(result?.token, apiKey)
}
}

View File

@ -6,17 +6,17 @@
// Copyright © 2018 ReCaptcha. All rights reserved.
//
import Result
@testable import ReCaptcha
extension Result {
var value: T? {
guard case .success(let value) = self else { return nil }
extension ReCaptchaResult {
var token: String? {
guard case .token(let value) = self else { return nil }
return value
}
var error: Error? {
guard case .failure(let error) = self else { return nil }
var error: ReCaptchaError? {
guard case .error(let error) = self else { return nil }
return error
}
}

View File

@ -43,7 +43,7 @@ class ReCaptcha_Rx__Tests: XCTestCase {
}
var result: ReCaptchaWebViewManager.Response?
var result: String?
let exp = expectation(description: "validate token")
// Validate
@ -65,9 +65,7 @@ class ReCaptcha_Rx__Tests: XCTestCase {
waitForExpectations(timeout: 10)
// Verify
XCTAssertNotNil(result)
XCTAssertEqual(result?.value, apiKey)
XCTAssertNil(result?.error)
XCTAssertEqual(result, apiKey)
}
@ -106,22 +104,22 @@ class ReCaptcha_Rx__Tests: XCTestCase {
XCTFail("should not ask to configure the webview")
}
var result: ReCaptchaWebViewManager.Response?
var result: ReCaptchaError?
let exp = expectation(description: "validate token")
// Validate
manager.rx.validate(on: presenterView, resetOnError: false)
.subscribe { event in
switch event {
case .next(let value):
result = value
case .next:
XCTFail("should not have validated")
case .error(let error):
XCTFail(error.localizedDescription)
result = error as? ReCaptchaError
exp.fulfill()
case .completed:
exp.fulfill()
XCTFail("should not have completed")
}
}
.disposed(by: disposeBag)
@ -129,10 +127,7 @@ class ReCaptcha_Rx__Tests: XCTestCase {
waitForExpectations(timeout: 10)
// Verify
XCTAssertNotNil(result)
XCTAssertNil(result?.value)
XCTAssertNotNil(result?.error)
XCTAssertEqual(result?.error, .wrongMessageFormat)
XCTAssertEqual(result, .wrongMessageFormat)
}
// MARK: Dispose
@ -164,7 +159,6 @@ class ReCaptcha_Rx__Tests: XCTestCase {
func test__Reset() {
let exp1 = expectation(description: "fail on first execution")
let exp2 = expectation(description: "resets after failure")
var result1: ReCaptchaWebViewManager.Response?
// Validate
let manager = ReCaptchaWebViewManager(messageBody: "{token: key}", apiKey: apiKey, shouldFail: true)
@ -179,37 +173,33 @@ class ReCaptcha_Rx__Tests: XCTestCase {
validate
.subscribe { event in
switch event {
case .next(let value):
result1 = value
case .next:
XCTFail("should not have validated")
case .error(let error):
XCTFail(error.localizedDescription)
case .error:
exp1.fulfill()
case .completed:
exp1.fulfill()
XCTFail("should not have completed")
}
}
.disposed(by: disposeBag)
// Resets after failure
validate
.flatMap { result -> Observable<Void> in
switch result {
case .failure: return .just(())
default: return .empty()
}
}
.catchErrorJustReturn("error")
.filter { $0 == "error" }
.map { _ in () }
.take(1)
.do(onCompleted: exp2.fulfill)
.bind(to: manager.rx.reset)
.disposed(by: disposeBag)
waitForExpectations(timeout: 10)
XCTAssertEqual(result1?.error, .wrongMessageFormat)
// Resets and tries again
let exp3 = expectation(description: "validates after reset")
var result2: ReCaptchaWebViewManager.Response?
var result2: String?
manager.rx.validate(on: presenterView, resetOnError: false)
.subscribe { event in
@ -227,12 +217,12 @@ class ReCaptcha_Rx__Tests: XCTestCase {
.disposed(by: disposeBag)
waitForExpectations(timeout: 10)
XCTAssertEqual(result2?.value, apiKey)
XCTAssertEqual(result2, apiKey)
}
func test__Validate__Reset_On_Error() {
let exp = expectation(description: "executes after failure on first execution")
var result: ReCaptchaWebViewManager.Response?
var result: String?
// Validate
let manager = ReCaptchaWebViewManager(messageBody: "{token: key}", apiKey: apiKey, shouldFail: true)
@ -257,6 +247,6 @@ class ReCaptcha_Rx__Tests: XCTestCase {
.disposed(by: disposeBag)
waitForExpectations(timeout: 10)
XCTAssertEqual(result?.value, apiKey)
XCTAssertEqual(result, apiKey)
}
}

View File

@ -57,7 +57,7 @@ override func viewDidLoad() {
func validate() {
recaptcha?.validate(on: view) { [weak self] result in
recaptcha?.validate(on: view) { [weak self] (result: ReCaptchaResult) in
print(try? result.dematerialize())
}
}

View File

@ -20,6 +20,7 @@
F24EA1E61F968403001DEC17 /* ReCaptcha.swift in Sources */ = {isa = PBXBuildFile; fileRef = F24EA1DE1F9683F5001DEC17 /* ReCaptcha.swift */; };
F24EA1E71F968406001DEC17 /* recaptcha.html in Resources */ = {isa = PBXBuildFile; fileRef = F24EA1E01F9683F5001DEC17 /* recaptcha.html */; };
F255FBEC1F8D5654002F5FA8 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F255FBEB1F8D5654002F5FA8 /* Result.framework */; };
F2AE8614204F3B42002E28D7 /* ReCaptchaResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2AE8613204F3B41002E28D7 /* ReCaptchaResult.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -51,6 +52,7 @@
F24EA1DE1F9683F5001DEC17 /* ReCaptcha.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReCaptcha.swift; sourceTree = "<group>"; };
F24EA1E01F9683F5001DEC17 /* recaptcha.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = recaptcha.html; sourceTree = "<group>"; };
F255FBEB1F8D5654002F5FA8 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../ReCaptcha Carthage Test/Carthage/Build/iOS/Result.framework"; sourceTree = "<group>"; };
F2AE8613204F3B41002E28D7 /* ReCaptchaResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReCaptchaResult.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -147,6 +149,7 @@
F24EA1D91F9683F5001DEC17 /* ReCaptchaWebViewManager.swift */,
F24EA1DA1F9683F5001DEC17 /* String+Dict.swift */,
F24EA1DB1F9683F5001DEC17 /* ReCaptchaError.swift */,
F2AE8613204F3B41002E28D7 /* ReCaptchaResult.swift */,
F231B3991FEC51C800F82943 /* DispatchQueue+Throttle.swift */,
F24EA1DC1F9683F5001DEC17 /* Rx */,
F24EA1DE1F9683F5001DEC17 /* ReCaptcha.swift */,
@ -291,6 +294,7 @@
files = (
F24EA1E51F968403001DEC17 /* ReCaptchaError.swift in Sources */,
F24EA1E21F968403001DEC17 /* ReCaptchaDecoder.swift in Sources */,
F2AE8614204F3B42002E28D7 /* ReCaptchaResult.swift in Sources */,
F24EA1E61F968403001DEC17 /* ReCaptcha.swift in Sources */,
F24EA1E31F968403001DEC17 /* ReCaptchaWebViewManager.swift in Sources */,
F24EA1E41F968403001DEC17 /* String+Dict.swift in Sources */,

View File

@ -22,7 +22,6 @@ invisibility is not possible.
s.subspec 'Core' do |core|
core.source_files = 'ReCaptcha/Classes/*'
core.frameworks = 'WebKit'
core.dependency 'Result', '~> 3.0'
core.resource_bundles = {
'ReCaptcha' => ['ReCaptcha/Assets/**/*']

View File

@ -30,7 +30,7 @@ open class ReCaptcha: ReCaptchaWebViewManager {
/// Alternate endpoint. Points to https://www.recaptcha.net/recaptcha/api.js
case alternate
fileprivate var url: String {
internal var url: String {
switch self {
case .default: return "https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
case .alternate: return "https://www.recaptcha.net/recaptcha/api.js?onload=onloadCallback&render=explicit"

View File

@ -0,0 +1,38 @@
//
// ReCaptchaWebViewManager.swift
// ReCaptcha
//
// Created by Flávio Caetano on 06/03/17.
// Copyright © 2018 ReCaptcha. All rights reserved.
//
import Foundation
/** The ReCaptcha result.
This may contain the validation token on success, or an error that may have occurred.
*/
public enum ReCaptchaResult {
/// The validation token.
case token(String)
/// An error that may have occurred.
case error(ReCaptchaError)
/**
- returns: The validation token uppon success.
Tries to unwrap the Result and retrieve the token if it's successful.
- Throws: `ReCaptchaError`
*/
public func dematerialize() throws -> String {
switch self {
case .token(let token):
return token
case .error(let error):
throw error
}
}
}

View File

@ -7,15 +7,12 @@
//
import Foundation
import Result
import WebKit
/** Handles comunications with the webview containing the ReCaptcha challenge.
*/
open class ReCaptchaWebViewManager {
public typealias Response = Result<String, ReCaptchaError>
/** The `webView` delegate object that performs execution uppon script loading
*/
fileprivate class WebViewDelegate: NSObject, WKNavigationDelegate {
@ -98,7 +95,7 @@ open class ReCaptchaWebViewManager {
}
/// Sends the result message
fileprivate var completion: ((Response) -> Void)?
fileprivate var completion: ((ReCaptchaResult) -> Void)?
/// Configures the webview for display when required
fileprivate var configureWebView: ((WKWebView) -> Void)?
@ -172,11 +169,11 @@ open class ReCaptchaWebViewManager {
- parameters:
- view: The view that should present the webview.
- resetOnError: If ReCaptcha should be reset if it errors. Defaults to `true`.
- completion: A closure that receives a Result<String, NSError> which may contain a valid result token.
- completion: A closure that receives a ReCaptchaResult which may contain a valid result token.
Starts the challenge validation
*/
open func validate(on view: UIView, resetOnError: Bool = true, completion: @escaping (Response) -> Void) {
open func validate(on view: UIView, resetOnError: Bool = true, completion: @escaping (ReCaptchaResult) -> Void) {
self.completion = completion
self.shouldResetOnError = resetOnError
@ -266,7 +263,7 @@ fileprivate extension ReCaptchaWebViewManager {
func handle(result: ReCaptchaDecoder.Result) {
switch result {
case .token(let token):
completion?(.success(token))
completion?(.token(token))
case .error(let error):
if shouldResetOnError, let view = webView.superview, let completion = completion {
@ -274,7 +271,7 @@ fileprivate extension ReCaptchaWebViewManager {
validate(on: view, completion: completion)
}
else {
completion?(.failure(error))
completion?(.error(error))
}
case .showReCaptcha:

View File

@ -22,18 +22,25 @@ public extension Reactive where Base: ReCaptchaWebViewManager {
Starts the challenge validation uppon subscription.
The stream's element is a `Result<String, ReCaptchaError>` that may contain a valid token.
The stream's element is a String with the validation token.
Sends `stop()` uppon disposal.
- See: `ReCaptchaWebViewManager.validate(on:resetOnError:completion:)`
- See: `ReCaptchaWebViewManager.stop()`
*/
func validate(on view: UIView, resetOnError: Bool = true) -> Observable<Base.Response> {
return Observable<Base.Response>.create { [weak base] (observer: AnyObserver<Base.Response>) in
base?.validate(on: view, resetOnError: resetOnError) { response in
observer.onNext(response)
observer.onCompleted()
func validate(on view: UIView, resetOnError: Bool = true) -> Observable<String> {
return Observable<String>.create { [weak base] (observer: AnyObserver<String>) in
base?.validate(on: view, resetOnError: resetOnError) { result in
defer { observer.onCompleted() }
switch result {
case .token(let token):
observer.onNext(token)
case .error(let error):
observer.onError(error)
}
}
return Disposables.create { [weak base] in

View File

@ -126,15 +126,15 @@ platform :ios do
# Private
def select_similar_simulator(args)
args.map { |device_string|
pieces = device_string.split(' (')
FastlaneCore::Simulator.all
.select { |s| s.name == pieces.first }
.sort_by { |s| Gem::Version.create(s.os_version) }
.detect { |s| Gem::Requirement.new(pieces[1].tr('()', '')).satisfied_by?(Gem::Version.create(s.os_version)) }
}
.compact
.map { |s| "#{s.name} (#{s.ios_version})"}
end
def select_similar_simulator(args)
args.map { |device_string|
pieces = device_string.split(' (')
FastlaneCore::Simulator.all
.select { |s| s.name == pieces.first }
.sort_by { |s| Gem::Version.create(s.os_version) }
.detect { |s| Gem::Requirement.new(pieces[1].tr('()', '')).satisfied_by?(Gem::Version.create(s.os_version)) }
}
.compact
.map { |s| "#{s.name} (#{s.ios_version})"}
end
end