Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 2.10.0

- Feat: Add phone prefix/number support for MFA flows

# 2.9.6

- Feat: upgrade RxSwift to 6.9.0
Expand Down
4 changes: 4 additions & 0 deletions Example/HCaptcha.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
43C25BC32E3FC51600AB0A36 /* TestTimeouts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C25BC22E3FC51600AB0A36 /* TestTimeouts.swift */; };
43C25BC42E3FC51600AB0A36 /* TestTimeouts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C25BC22E3FC51600AB0A36 /* TestTimeouts.swift */; };
43DC08122E95B131003839A5 /* HCaptchaVerifyParams__Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DC08112E95B131003839A5 /* HCaptchaVerifyParams__Tests.swift */; };
50AC78913CD85915C922C6E7 /* Pods_HCaptcha_RxSwift_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 81A23EFF913417B4D093248E /* Pods_HCaptcha_RxSwift_Example.framework */; };
607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; };
607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; };
Expand Down Expand Up @@ -98,6 +99,7 @@
15CF87684AC2F129E32CC71E /* Pods-HCaptcha_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HCaptcha_Example.debug.xcconfig"; path = "Target Support Files/Pods-HCaptcha_Example/Pods-HCaptcha_Example.debug.xcconfig"; sourceTree = "<group>"; };
1CF662E463D56A0421D8A84A /* Pods-HCaptcha_RxSwift_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HCaptcha_RxSwift_Example.debug.xcconfig"; path = "Target Support Files/Pods-HCaptcha_RxSwift_Example/Pods-HCaptcha_RxSwift_Example.debug.xcconfig"; sourceTree = "<group>"; };
43C25BC22E3FC51600AB0A36 /* TestTimeouts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestTimeouts.swift; sourceTree = "<group>"; };
43DC08112E95B131003839A5 /* HCaptchaVerifyParams__Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HCaptchaVerifyParams__Tests.swift; sourceTree = "<group>"; };
4D10E8098B5018907486C310 /* Pods_HCaptcha_UIKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_HCaptcha_UIKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD01AFB9204008FA782 /* HCaptcha_RxSwift_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HCaptcha_RxSwift_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -398,6 +400,7 @@
F2ECCF821E9FC4AC0097B199 /* Core */ = {
isa = PBXGroup;
children = (
43DC08112E95B131003839A5 /* HCaptchaVerifyParams__Tests.swift */,
F2ECCF891E9FCEFE0097B199 /* HCaptchaDecoder__Tests.swift */,
F2ECCF8D1E9FE68C0097B199 /* HCaptchaWebViewManager__Tests.swift */,
9C5125BD26CB9A3A0094B023 /* HCaptchaWebViewManager__HTML__Tests.swift */,
Expand Down Expand Up @@ -999,6 +1002,7 @@
F2ECCF8E1E9FE68C0097B199 /* HCaptchaWebViewManager__Tests.swift in Sources */,
F231B3971FEC325A00F82943 /* DispatchQueue__Tests.swift in Sources */,
E64F97912895CD250044257C /* HCaptcha__Bench.swift in Sources */,
43DC08122E95B131003839A5 /* HCaptchaVerifyParams__Tests.swift in Sources */,
F231B39F1FED4A8C00F82943 /* HCaptchaDecoder+Helper.swift in Sources */,
F2E2685E1F7AEE3400CD876D /* HCaptcha__Tests.swift in Sources */,
F2ECCF931EA009360097B199 /* HCaptcha+Rx__Tests.swift in Sources */,
Expand Down
337 changes: 337 additions & 0 deletions Example/HCaptcha_Tests/Core/HCaptchaVerifyParams__Tests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,337 @@
//
// HCaptchaVerifyParams__Tests.swift
// HCaptcha
//
// Created by Assistant on 26/09/25.
// Copyright © 2025 HCaptcha. All rights reserved.
//

@testable import HCaptcha
import XCTest

class HCaptchaVerifyParams__Tests: XCTestCase {

// MARK: - Initialization Tests

func test__init__defaultValues() {
// Given/When
let params = HCaptchaVerifyParams()

// Then
XCTAssertNil(params.phonePrefix)
XCTAssertNil(params.phoneNumber)
XCTAssertTrue(params.resetOnError)
}

func test__init__withPhonePrefix() {
// Given
let phonePrefix = "44"

// When
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix)

// Then
XCTAssertEqual(params.phonePrefix, phonePrefix)
XCTAssertNil(params.phoneNumber)
XCTAssertTrue(params.resetOnError)
}

func test__init__withPhoneNumber() {
// Given
let phoneNumber = "+1234567890"

// When
let params = HCaptchaVerifyParams(phoneNumber: phoneNumber)

// Then
XCTAssertNil(params.phonePrefix)
XCTAssertEqual(params.phoneNumber, phoneNumber)
XCTAssertTrue(params.resetOnError)
}

func test__init__withBothPhoneValues() {
// Given
let phonePrefix = "44"
let phoneNumber = "1234567890"

// When
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix, phoneNumber: phoneNumber)

// Then
XCTAssertEqual(params.phonePrefix, phonePrefix)
XCTAssertEqual(params.phoneNumber, phoneNumber)
XCTAssertTrue(params.resetOnError)
}

func test__init__withResetOnError() {
// Given
let phonePrefix = "44"
let resetOnError = false

// When
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix, resetOnError: resetOnError)

// Then
XCTAssertEqual(params.phonePrefix, phonePrefix)
XCTAssertNil(params.phoneNumber)
XCTAssertFalse(params.resetOnError)
}

func test__init__withAllValues() {
// Given
let phonePrefix = "44"
let phoneNumber = "1234567890"
let resetOnError = false

// When
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix, phoneNumber: phoneNumber, resetOnError: resetOnError)

// Then
XCTAssertEqual(params.phonePrefix, phonePrefix)
XCTAssertEqual(params.phoneNumber, phoneNumber)
XCTAssertFalse(params.resetOnError)
}

// MARK: - toDictionary Tests

func test__toDictionary__withAllValues() {
// Given
let phonePrefix = "44"
let phoneNumber = "1234567890"
let resetOnError = false
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix, phoneNumber: phoneNumber, resetOnError: resetOnError)

// When
let dict = params.toDictionary()

// Then
XCTAssertEqual(dict["phonePrefix"] as? String, phonePrefix)
XCTAssertEqual(dict["phoneNumber"] as? String, phoneNumber)
XCTAssertEqual(dict["resetOnError"] as? Bool, resetOnError)
XCTAssertEqual(dict.count, 3)
}

func test__toDictionary__withPartialValues() {
// Given
let phonePrefix = "44"
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix)

// When
let dict = params.toDictionary()

// Then
XCTAssertEqual(dict["phonePrefix"] as? String, phonePrefix)
XCTAssertNil(dict["phoneNumber"])
XCTAssertEqual(dict["resetOnError"] as? Bool, true)
XCTAssertEqual(dict.count, 2)
}

func test__toDictionary__withNilValues() {
// Given
let params = HCaptchaVerifyParams()

// When
let dict = params.toDictionary()

// Then
XCTAssertNil(dict["phonePrefix"])
XCTAssertNil(dict["phoneNumber"])
XCTAssertEqual(dict["resetOnError"] as? Bool, true)
XCTAssertEqual(dict.count, 1)
}

func test__toDictionary__withOnlyPhoneNumber() {
// Given
let phoneNumber = "+1234567890"
let resetOnError = false
let params = HCaptchaVerifyParams(phoneNumber: phoneNumber, resetOnError: resetOnError)

// When
let dict = params.toDictionary()

// Then
XCTAssertNil(dict["phonePrefix"])
XCTAssertEqual(dict["phoneNumber"] as? String, phoneNumber)
XCTAssertEqual(dict["resetOnError"] as? Bool, resetOnError)
XCTAssertEqual(dict.count, 2)
}

// MARK: - toJSONString Tests

func test__toJSONString__validJSON() {
// Given
let phonePrefix = "44"
let phoneNumber = "1234567890"
let resetOnError = false
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix, phoneNumber: phoneNumber, resetOnError: resetOnError)

// When
let jsonString = params.toJSONString()

// Then
XCTAssertNotNil(jsonString)

// Verify JSON structure
let data = jsonString!.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(with: data) as! [String: Any]
XCTAssertEqual(json["phonePrefix"] as? String, phonePrefix)
XCTAssertEqual(json["phoneNumber"] as? String, phoneNumber)
XCTAssertEqual(json["resetOnError"] as? Bool, resetOnError)
}

func test__toJSONString__withNilValues() {
// Given
let params = HCaptchaVerifyParams()

// When
let jsonString = params.toJSONString()

// Then
XCTAssertNotNil(jsonString)

// Verify JSON structure
let data = jsonString!.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(with: data) as! [String: Any]
XCTAssertNil(json["phonePrefix"])
XCTAssertNil(json["phoneNumber"])
XCTAssertEqual(json["resetOnError"] as? Bool, true)
}

func test__toJSONString__withPartialValues() {
// Given
let phonePrefix = "44"
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix)

// When
let jsonString = params.toJSONString()

// Then
XCTAssertNotNil(jsonString)

// Verify JSON structure
let data = jsonString!.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(with: data) as! [String: Any]
XCTAssertEqual(json["phonePrefix"] as? String, phonePrefix)
XCTAssertNil(json["phoneNumber"])
XCTAssertEqual(json["resetOnError"] as? Bool, true)
}

// MARK: - Edge Cases

func test__init__withEmptyStrings() {
// Given
let emptyPrefix = ""
let emptyNumber = ""

// When
let params = HCaptchaVerifyParams(phonePrefix: emptyPrefix, phoneNumber: emptyNumber)

// Then
XCTAssertEqual(params.phonePrefix, emptyPrefix)
XCTAssertEqual(params.phoneNumber, emptyNumber)
XCTAssertTrue(params.resetOnError)
}

func test__toDictionary__withEmptyStrings() {
// Given
let params = HCaptchaVerifyParams(phonePrefix: "", phoneNumber: "")

// When
let dict = params.toDictionary()

// Then
XCTAssertEqual(dict["phonePrefix"] as? String, "")
XCTAssertEqual(dict["phoneNumber"] as? String, "")
XCTAssertEqual(dict["resetOnError"] as? Bool, true)
}

func test__toJSONString__withEmptyStrings() {
// Given
let params = HCaptchaVerifyParams(phonePrefix: "", phoneNumber: "")

// When
let jsonString = params.toJSONString()

// Then
XCTAssertNotNil(jsonString)

// Verify JSON structure
let data = jsonString!.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(with: data) as! [String: Any]
XCTAssertEqual(json["phonePrefix"] as? String, "")
XCTAssertEqual(json["phoneNumber"] as? String, "")
XCTAssertEqual(json["resetOnError"] as? Bool, true)
}

func test__init__withSpecialCharacters() {
// Given
let phonePrefix = "+44"
let phoneNumber = "+1-234-567-8900"

// When
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix, phoneNumber: phoneNumber)

// Then
XCTAssertEqual(params.phonePrefix, phonePrefix)
XCTAssertEqual(params.phoneNumber, phoneNumber)
XCTAssertTrue(params.resetOnError)
}

func test__toJSONString__withSpecialCharacters() {
// Given
let phonePrefix = "+44"
let phoneNumber = "+1-234-567-8900"
let params = HCaptchaVerifyParams(phonePrefix: phonePrefix, phoneNumber: phoneNumber)

// When
let jsonString = params.toJSONString()

// Then
XCTAssertNotNil(jsonString)

// Verify JSON structure
let data = jsonString!.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(with: data) as! [String: Any]
XCTAssertEqual(json["phonePrefix"] as? String, phonePrefix)
XCTAssertEqual(json["phoneNumber"] as? String, phoneNumber)
XCTAssertEqual(json["resetOnError"] as? Bool, true)
}

// MARK: - Objective-C Compatibility Tests

func test__objcCompatibility__init() {
// Given/When
let params = HCaptchaVerifyParams(phonePrefix: "44", phoneNumber: "1234567890", resetOnError: false)

// Then
XCTAssertTrue(params.isKind(of: NSObject.self))
XCTAssertTrue(params.responds(to: #selector(HCaptchaVerifyParams.toDictionary)))
XCTAssertTrue(params.responds(to: #selector(HCaptchaVerifyParams.toJSONString)))
}

func test__objcCompatibility__properties() {
// Given
let params = HCaptchaVerifyParams(phonePrefix: "44", phoneNumber: "1234567890", resetOnError: false)

// When/Then
XCTAssertTrue(params.responds(to: #selector(getter: HCaptchaVerifyParams.phonePrefix)))
XCTAssertTrue(params.responds(to: #selector(getter: HCaptchaVerifyParams.phoneNumber)))
XCTAssertTrue(params.responds(to: #selector(getter: HCaptchaVerifyParams.resetOnError)))
}

// MARK: - Memory Management Tests

func test__memoryManagement__retainCycle() {
// Given
weak var weakParams: HCaptchaVerifyParams?

// When
autoreleasepool {
let params = HCaptchaVerifyParams(phonePrefix: "44", phoneNumber: "1234567890")
weakParams = params
}

// Then
XCTAssertNil(weakParams, "HCaptchaVerifyParams should not create retain cycles")
}
}
Loading
Loading