diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 62a58a2..64dc964 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,8 +1,8 @@ PODS: - AppSwizzle (1.2) - - ReCaptcha/Core (1.0.1): + - ReCaptcha/Core (1.0.2): - Result (~> 3.0) - - ReCaptcha/RxSwift (1.0.1): + - ReCaptcha/RxSwift (1.0.2): - ReCaptcha/Core - RxSwift (~> 4.0) - Result (3.2.4) @@ -31,7 +31,7 @@ CHECKOUT OPTIONS: SPEC CHECKSUMS: AppSwizzle: bbd3782652fc426ce59c045a92ec61d36f261984 - ReCaptcha: f281cd074be9b282f528c6dda9337476f13bd776 + ReCaptcha: f1d10fd37e8f219c00521790aa9124ca12b65e16 Result: d2d07204ce72856f1fd9130bbe42c35a7b0fea10 RxCocoa: fd0862fd2df95fa55562ad28ffd2522c25eb4a85 RxSwift: c6e3b1c7b325c7d121cd4327e9d98b7ed746b570 diff --git a/Example/ReCaptcha_Tests/Core/ReCaptcha__Tests.swift b/Example/ReCaptcha_Tests/Core/ReCaptcha__Tests.swift index 822d7a8..56b25b3 100644 --- a/Example/ReCaptcha_Tests/Core/ReCaptcha__Tests.swift +++ b/Example/ReCaptcha_Tests/Core/ReCaptcha__Tests.swift @@ -26,7 +26,6 @@ class ReCaptcha__Tests: XCTestCase { toAlterSelector: #selector(Bundle.failHTMLLoad(_:type:)) ) - do { _ = try ReCaptcha() XCTFail("Should have failed") @@ -57,16 +56,28 @@ class ReCaptcha__Tests: XCTestCase { } // Ensures plist url if nil key - let plistURL = URL(string: "bar")! + let plistURL = URL(string: "https://bar")! let config1 = try? ReCaptcha.Config(apiKey: "", infoPlistKey: nil, baseURL: nil, infoPlistURL: plistURL) XCTAssertEqual(config1?.baseURL, plistURL) // Ensures preference of given url over plist entry - let url = URL(string: "foo")! + let url = URL(string: "ftp://foo")! let config2 = try? ReCaptcha.Config(apiKey: "", infoPlistKey: nil, baseURL: url, infoPlistURL: plistURL) XCTAssertEqual(config2?.baseURL, url) } + func test__Base_URL_Without_Scheme() { + // Ignores URL with scheme + let goodURL = URL(string: "https://foo.bar")! + let config0 = try? ReCaptcha.Config(apiKey: "", infoPlistKey: nil, baseURL: goodURL, infoPlistURL: nil) + XCTAssertEqual(config0?.baseURL, goodURL) + + // Fixes URL without scheme + let badURL = URL(string: "foo")! + let config = try? ReCaptcha.Config(apiKey: "", infoPlistKey: nil, baseURL: badURL, infoPlistURL: nil) + XCTAssertEqual(config?.baseURL.absoluteString, "http://" + badURL.absoluteString) + } + func test__API_Key() { // Ensures key failure when nil do { diff --git a/Gemfile b/Gemfile index fa55363..b13ca5a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ source 'https://rubygems.org' gem 'fastlane', '~> 2.75' -gem 'cocoapods', '~> 1.3.1' +gem 'cocoapods', '~> 1.4' diff --git a/Gemfile.lock b/Gemfile.lock index 61b3e32..85412af 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,30 +11,30 @@ GEM public_suffix (>= 2.0.2, < 4.0) babosa (1.0.2) claide (1.0.2) - cocoapods (1.3.1) + cocoapods (1.4.0) activesupport (>= 4.0.2, < 5) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.3.1) - cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-core (= 1.4.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) cocoapods-downloader (>= 1.1.3, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.2.0, < 2.0) + cocoapods-trunk (>= 1.3.0, < 2.0) cocoapods-try (>= 1.1.0, < 2.0) colored2 (~> 3.1) escape (~> 0.0.4) fourflusher (~> 2.0.1) gh_inspector (~> 1.0) - molinillo (~> 0.5.7) + molinillo (~> 0.6.4) nap (~> 1.0) ruby-macho (~> 1.1) - xcodeproj (>= 1.5.1, < 2.0) - cocoapods-core (1.3.1) + xcodeproj (>= 1.5.4, < 2.0) + cocoapods-core (1.4.0) activesupport (>= 4.0.2, < 6) fuzzy_match (~> 2.0.4) nap (~> 1.0) - cocoapods-deintegrate (1.0.1) + cocoapods-deintegrate (1.0.2) cocoapods-downloader (1.1.3) cocoapods-plugins (1.0.0) nap @@ -120,7 +120,7 @@ GEM http-cookie (1.0.3) domain_name (~> 0.5) httpclient (2.8.3) - i18n (0.9.0) + i18n (0.9.1) concurrent-ruby (~> 1.0) json (2.1.0) jwt (2.1.0) @@ -133,8 +133,8 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_magick (4.5.1) - minitest (5.10.3) - molinillo (0.5.7) + minitest (5.11.1) + molinillo (0.6.4) multi_json (1.13.0) multi_xml (0.6.0) multipart-post (2.0.0) @@ -189,7 +189,7 @@ PLATFORMS ruby DEPENDENCIES - cocoapods (~> 1.3.1) + cocoapods (~> 1.4) fastlane (~> 2.75) BUNDLED WITH diff --git a/README.md b/README.md index fd718d0..a573f1f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ when creating your [API Key](https://www.google.com/recaptcha/admin). ## Installation ReCaptcha is available through [CocoaPods](http://cocoapods.org) and [Carthage](https://github.com/Carthage/Carthage). -To install it, simply add the following line to your depedencies file: +To install it, simply add the following line to your dependencies file: #### Cocoapods ``` ruby @@ -42,7 +42,7 @@ extension for the ReCaptcha framework. ## Usage -Simply add `ReCaptchaKey` and `ReCaptchaDomain` to your Info.plist and run: +Simply add `ReCaptchaKey` and `ReCaptchaDomain` (with a protocol) to your Info.plist and run: ``` swift let recaptcha = try? ReCaptcha() diff --git a/ReCaptcha/Classes/DispatchQueue+Throttle.swift b/ReCaptcha/Classes/DispatchQueue+Throttle.swift index 885ad70..017f9e0 100644 --- a/ReCaptcha/Classes/DispatchQueue+Throttle.swift +++ b/ReCaptcha/Classes/DispatchQueue+Throttle.swift @@ -8,10 +8,14 @@ import Foundation -private var workItems = [AnyHashable: DispatchWorkItem]() -private let nilContext = UUID() - +/// Adds throttling to dispatch queues extension DispatchQueue { + /// Stores a throttle DispatchWorkItem instance for a given context + private static var workItems = [AnyHashable: DispatchWorkItem]() + + /// An object representing a context if none is given + private static let nilContext = UUID() + /** - parameters: - deadline: The timespan to delay a closure execution @@ -22,13 +26,13 @@ extension DispatchQueue { */ func throttle(deadline: DispatchTime, context: AnyHashable = nilContext, action: @escaping () -> Void) { let worker = DispatchWorkItem { - defer { workItems[context] = nil } + defer { DispatchQueue.workItems.removeValue(forKey: context) } action() } asyncAfter(deadline: deadline, execute: worker) - workItems[context]?.cancel() - workItems[context] = worker + DispatchQueue.workItems[context]?.cancel() + DispatchQueue.workItems[context] = worker } } diff --git a/ReCaptcha/Classes/ReCaptcha.swift b/ReCaptcha/Classes/ReCaptcha.swift index 190424c..5fadf88 100644 --- a/ReCaptcha/Classes/ReCaptcha.swift +++ b/ReCaptcha/Classes/ReCaptcha.swift @@ -38,7 +38,7 @@ open class ReCaptcha: ReCaptchaWebViewManager { } } - /** Internal data model for DI in unit tests + /** Internal data model for CI in unit tests */ struct Config { /// The raw unformated HTML file content @@ -93,7 +93,7 @@ open class ReCaptcha: ReCaptchaWebViewManager { self.html = rawHTML self.apiKey = apiKey - self.baseURL = domain + self.baseURL = Config.fixSchemeIfNeeded(for: domain) } } @@ -128,3 +128,26 @@ open class ReCaptcha: ReCaptchaWebViewManager { super.init(html: config.html, apiKey: config.apiKey, baseURL: config.baseURL, endpoint: endpoint.url) } } + +// MARK: - Private Methods + +private extension ReCaptcha.Config { + /** + - parameter url: The URL to be fixed + - returns: An URL with scheme + + If the given URL has no scheme, prepends `http://` to it and return the fixed URL. + */ + static func fixSchemeIfNeeded(for url: URL) -> URL { + guard url.scheme?.isEmpty != false else { + return url + } + + if let fixedURL = URL(string: "http://" + url.absoluteString) { + debugPrint("[ReCaptcha] - Prepending 'http://' to url (\(url))") + return fixedURL + } + + return url + } +}