|
22 | 22 | private func makeValidDictionary() -> [String: AnyHashable] {
|
23 | 23 | return [
|
24 | 24 | "credentialCreationOptions": [
|
25 |
| - "rp": ["id": "example.com"] as [String: AnyHashable], |
26 |
| - "user": ["id": "USER_123"] as [String: AnyHashable], |
| 25 | + "rp": ["id": "FAKE_RP_ID"] as [String: AnyHashable], |
| 26 | + "user": ["id": "FAKE_USER_ID"] as [String: AnyHashable], |
27 | 27 | "challenge": "FAKE_CHALLENGE" as String,
|
28 | 28 | ] as [String: AnyHashable],
|
29 | 29 | ]
|
30 | 30 | }
|
31 | 31 |
|
32 |
| - func testInitWithValidDictionary() throws { |
33 |
| - let response = try StartPasskeyEnrollmentResponse(dictionary: makeValidDictionary()) |
34 |
| - XCTAssertEqual(response.rpID, "example.com") |
35 |
| - XCTAssertEqual(response.userID, "USER_123") |
36 |
| - XCTAssertEqual(response.challenge, "FAKE_CHALLENGE") |
37 |
| - } |
38 |
| - |
39 |
| - func testInitWithMissingCredentialCreationOptions() { |
40 |
| - let invalidDict: [String: AnyHashable] = [:] |
41 |
| - XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: invalidDict)) { error in |
42 |
| - let nsError = error as NSError |
43 |
| - XCTAssertEqual(nsError.domain, AuthErrorDomain) |
44 |
| - XCTAssertEqual(nsError.code, AuthErrorCode.internalError.rawValue) |
45 |
| - } |
46 |
| - } |
47 |
| - |
48 |
| - func testInitWithMissingRp() { |
49 |
| - var dict = makeValidDictionary() |
50 |
| - if var options = dict["credentialCreationOptions"] as? [String: Any] { |
51 |
| - options.removeValue(forKey: "rp") |
52 |
| - dict["credentialCreationOptions"] = options as? AnyHashable |
53 |
| - } |
54 |
| - XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict)) { error in |
55 |
| - let nsError = error as NSError |
56 |
| - XCTAssertEqual(nsError.domain, AuthErrorDomain) |
57 |
| - XCTAssertEqual(nsError.code, AuthErrorCode.internalError.rawValue) |
| 32 | + /// Helper function to remove a nested key from a dictionary |
| 33 | + private func removeField(_ dict: inout [String: AnyHashable], keyPath: [String]) { |
| 34 | + guard let first = keyPath.first else { return } |
| 35 | + if keyPath.count == 1 { |
| 36 | + dict.removeValue(forKey: first) |
| 37 | + } else if var inDict = dict[first] as? [String: AnyHashable] { |
| 38 | + removeField(&inDict, keyPath: Array(keyPath.dropFirst())) |
| 39 | + dict[first] = inDict |
58 | 40 | }
|
59 | 41 | }
|
60 | 42 |
|
61 |
| - func testInitWithMissingRpId() { |
62 |
| - var dict = makeValidDictionary() |
63 |
| - if var options = dict["credentialCreationOptions"] as? [String: Any], |
64 |
| - var rp = options["rp"] as? [String: Any] { |
65 |
| - rp.removeValue(forKey: "id") |
66 |
| - options["rp"] = rp |
67 |
| - dict["credentialCreationOptions"] = options as? AnyHashable |
68 |
| - } |
69 |
| - XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict)) { error in |
70 |
| - let nsError = error as NSError |
71 |
| - XCTAssertEqual(nsError.domain, AuthErrorDomain) |
72 |
| - XCTAssertEqual(nsError.code, AuthErrorCode.internalError.rawValue) |
73 |
| - } |
74 |
| - } |
75 |
| - |
76 |
| - func testInitWithMissingUser() { |
77 |
| - var dict = makeValidDictionary() |
78 |
| - if var options = dict["credentialCreationOptions"] as? [String: Any] { |
79 |
| - options.removeValue(forKey: "user") |
80 |
| - dict["credentialCreationOptions"] = options as? AnyHashable |
81 |
| - } |
82 |
| - XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict)) { error in |
83 |
| - let nsError = error as NSError |
84 |
| - XCTAssertEqual(nsError.domain, AuthErrorDomain) |
85 |
| - XCTAssertEqual(nsError.code, AuthErrorCode.internalError.rawValue) |
86 |
| - } |
87 |
| - } |
88 |
| - |
89 |
| - func testInitWithMissingUserId() { |
90 |
| - var dict = makeValidDictionary() |
91 |
| - if var options = dict["credentialCreationOptions"] as? [String: Any], |
92 |
| - var user = options["user"] as? [String: Any] { |
93 |
| - user.removeValue(forKey: "id") |
94 |
| - options["user"] = user |
95 |
| - dict["credentialCreationOptions"] = options as? AnyHashable |
96 |
| - } |
97 |
| - XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict)) { error in |
98 |
| - let nsError = error as NSError |
99 |
| - XCTAssertEqual(nsError.domain, AuthErrorDomain) |
100 |
| - XCTAssertEqual(nsError.code, AuthErrorCode.internalError.rawValue) |
101 |
| - } |
| 43 | + func testInitWithValidDictionary() throws { |
| 44 | + let response = try StartPasskeyEnrollmentResponse(dictionary: makeValidDictionary()) |
| 45 | + XCTAssertEqual(response.rpID, "FAKE_RP_ID") |
| 46 | + XCTAssertEqual(response.userID, "FAKE_USER_ID") |
| 47 | + XCTAssertEqual(response.challenge, "FAKE_CHALLENGE") |
102 | 48 | }
|
103 | 49 |
|
104 |
| - func testInitWithMissingChallenge() { |
105 |
| - var dict = makeValidDictionary() |
106 |
| - if var options = dict["credentialCreationOptions"] as? [String: AnyHashable] { |
107 |
| - options.removeValue(forKey: "challenge") |
108 |
| - dict["credentialCreationOptions"] = options as [String: AnyHashable] |
| 50 | + func testInitWithMissingFields() throws { |
| 51 | + struct TestCase { |
| 52 | + let name: String |
| 53 | + let removeFieldPath: [String] |
109 | 54 | }
|
110 |
| - XCTAssertThrowsError( |
111 |
| - try StartPasskeyEnrollmentResponse(dictionary: dict) |
112 |
| - ) { error in |
113 |
| - let nsError = error as NSError |
114 |
| - XCTAssertEqual(nsError.domain, AuthErrorDomain) |
115 |
| - XCTAssertEqual(nsError.code, AuthErrorCode.internalError.rawValue) |
| 55 | + let cases: [TestCase] = [ |
| 56 | + .init(name: "Missing rpId", removeFieldPath: ["credentialCreationOptions", "rp", "id"]), |
| 57 | + .init(name: "Missing userId", removeFieldPath: ["credentialCreationOptions", "user", "id"]), |
| 58 | + .init( |
| 59 | + name: "Missing Challenge", |
| 60 | + removeFieldPath: ["credentialCreationOptions", "challenge"] |
| 61 | + ), |
| 62 | + ] |
| 63 | + for testCase in cases { |
| 64 | + var dict = makeValidDictionary() |
| 65 | + removeField(&dict, keyPath: testCase.removeFieldPath) |
| 66 | + XCTAssertThrowsError(try StartPasskeyEnrollmentResponse(dictionary: dict), |
| 67 | + testCase.name) { error in |
| 68 | + let nsError = error as NSError |
| 69 | + XCTAssertEqual(nsError.domain, AuthErrorDomain) |
| 70 | + XCTAssertEqual(nsError.code, AuthErrorCode.internalError.rawValue) |
| 71 | + } |
116 | 72 | }
|
117 | 73 | }
|
118 | 74 |
|
119 | 75 | func testSuccessfulStartPasskeyEnrollmentResponse() async throws {
|
120 |
| - let expectedRpID = "example.com" |
121 |
| - let expectedUserID = "USER_123" |
| 76 | + let expectedRpID = "FAKE_RP_ID" |
| 77 | + let expectedUserID = "FAKE_USER_ID" |
122 | 78 | let expectedChallenge = "FAKE_CHALLENGE"
|
123 | 79 | rpcIssuer.respondBlock = {
|
124 | 80 | try self.rpcIssuer.respond(withJSON: [
|
|
130 | 86 | ])
|
131 | 87 | }
|
132 | 88 | let request = StartPasskeyEnrollmentRequest(
|
133 |
| - idToken: "DUMMY_ID_TOKEN", |
| 89 | + idToken: "FAKE_ID_TOKEN", |
134 | 90 | requestConfiguration: AuthRequestConfiguration(apiKey: "API_KEY", appID: "APP_ID")
|
135 | 91 | )
|
136 | 92 | let response = try await authBackend.call(with: request)
|
|
0 commit comments