|
| 1 | +import XCTest |
| 2 | +@testable import gen_swift |
| 3 | + |
| 4 | +final class gen_swiftTests: XCTestCase { |
| 5 | + |
| 6 | + private let client = TestApiClient(hostname: "http://localhost:9988") |
| 7 | + |
| 8 | + func testEmpty() async throws { |
| 9 | + await XCTAssertNoThrow(try await client.getEmpty(), "getEmpty() should get empty type successfully") |
| 10 | + } |
| 11 | + |
| 12 | + func testError() async throws { |
| 13 | + await XCTAssertThrowsError(try await client.getError(), "getError() should throw error") |
| 14 | + } |
| 15 | + |
| 16 | + func testOne() async throws { |
| 17 | + let response = try await client.getOne() |
| 18 | + await XCTAssertNoThrow(try await client.sendOne(one: response), |
| 19 | + "getOne() should receive simple type and send it back via sendOne() successfully") |
| 20 | + |
| 21 | + } |
| 22 | + |
| 23 | + func testMulti() async throws { |
| 24 | + let (one, two, three) = try await client.getMulti() |
| 25 | + await XCTAssertNoThrow(try await client.sendMulti(one: one, two: two, three: three), |
| 26 | + "getMulti() should receive simple type and send it back via sendMulti() successfully") |
| 27 | + } |
| 28 | + |
| 29 | + func testComplex() async throws { |
| 30 | + let response = try await client.getComplex() |
| 31 | + await XCTAssertNoThrow(try await client.sendComplex(complex: response), |
| 32 | + "getComplex() should receive complex type and send it back via sendComplex() successfully") |
| 33 | + } |
| 34 | + |
| 35 | + func testCustomErrors() async throws { |
| 36 | + let errors: [WebrpcError] = [ |
| 37 | + .init( |
| 38 | + error: "WebrpcEndpoint", |
| 39 | + code: 0, |
| 40 | + message: "endpoint error", |
| 41 | + cause: "failed to read file: unexpected EOF", |
| 42 | + status: 400, |
| 43 | + errorKind: .webrpcEndpointError |
| 44 | + ), |
| 45 | + .init( |
| 46 | + error: "Unauthorized", |
| 47 | + code: 1, |
| 48 | + message: "unauthorized", |
| 49 | + cause: "failed to verify JWT token", |
| 50 | + status: 401, |
| 51 | + errorKind: .unauthorizedError |
| 52 | + ), |
| 53 | + .init( |
| 54 | + error: "ExpiredToken", |
| 55 | + code: 2, |
| 56 | + message: "expired token", |
| 57 | + cause: nil, |
| 58 | + status: 401, |
| 59 | + errorKind: .expiredTokenError |
| 60 | + ), |
| 61 | + .init( |
| 62 | + error: "InvalidToken", |
| 63 | + code: 3, |
| 64 | + message: "invalid token", |
| 65 | + cause: nil, |
| 66 | + status: 401, |
| 67 | + errorKind: .invalidTokenError |
| 68 | + ), |
| 69 | + .init( |
| 70 | + error: "Deactivated", |
| 71 | + code: 4, |
| 72 | + message: "account deactivated", |
| 73 | + cause: nil, |
| 74 | + status: 403, |
| 75 | + errorKind: .deactivatedError |
| 76 | + ), |
| 77 | + .init( |
| 78 | + error: "ConfirmAccount", |
| 79 | + code: 5, |
| 80 | + message: "confirm your email", |
| 81 | + cause: nil, |
| 82 | + status: 403, |
| 83 | + errorKind: .confirmAccountError |
| 84 | + ), |
| 85 | + .init( |
| 86 | + error: "AccessDenied", |
| 87 | + code: 6, |
| 88 | + message: "access denied", |
| 89 | + cause: nil, |
| 90 | + status: 403, |
| 91 | + errorKind: .accessDeniedError |
| 92 | + ), |
| 93 | + .init( |
| 94 | + error: "MissingArgument", |
| 95 | + code: 7, |
| 96 | + message: "missing argument", |
| 97 | + cause: nil, |
| 98 | + status: 400, |
| 99 | + errorKind: .missingArgumentError |
| 100 | + ), |
| 101 | + .init( |
| 102 | + error: "UnexpectedValue", |
| 103 | + code: 8, |
| 104 | + message: "unexpected value", |
| 105 | + cause: nil, |
| 106 | + status: 400, |
| 107 | + errorKind: .unexpectedValueError |
| 108 | + ), |
| 109 | + .init( |
| 110 | + error: "RateLimited", |
| 111 | + code: 100, |
| 112 | + message: "too many requests", |
| 113 | + cause: "1000 req/min exceeded", |
| 114 | + status: 429, |
| 115 | + errorKind: .rateLimitedError |
| 116 | + ), |
| 117 | + .init( |
| 118 | + error: "DatabaseDown", |
| 119 | + code: 101, |
| 120 | + message: "service outage", |
| 121 | + cause: nil, |
| 122 | + status: 503, |
| 123 | + errorKind: .databaseDownError |
| 124 | + ), |
| 125 | + .init( |
| 126 | + error: "ElasticDown", |
| 127 | + code: 102, |
| 128 | + message: "search is degraded", |
| 129 | + cause: nil, |
| 130 | + status: 503, |
| 131 | + errorKind: .elasticDownError |
| 132 | + ), |
| 133 | + .init( |
| 134 | + error: "NotImplemented", |
| 135 | + code: 103, |
| 136 | + message: "not implemented", |
| 137 | + cause: nil, |
| 138 | + status: 501, |
| 139 | + errorKind: .notImplementedError |
| 140 | + ), |
| 141 | + .init( |
| 142 | + error: "UserNotFound", |
| 143 | + code: 200, |
| 144 | + message: "user not found", |
| 145 | + cause: nil, |
| 146 | + status: 400, |
| 147 | + errorKind: .userNotFoundError |
| 148 | + ), |
| 149 | + .init( |
| 150 | + error: "UserBusy", |
| 151 | + code: 201, |
| 152 | + message: "user busy", |
| 153 | + cause: nil, |
| 154 | + status: 400, |
| 155 | + errorKind: .userBusyError |
| 156 | + ), |
| 157 | + .init( |
| 158 | + error: "InvalidUsername", |
| 159 | + code: 202, |
| 160 | + message: "invalid username", |
| 161 | + cause: nil, |
| 162 | + status: 400, |
| 163 | + errorKind: .invalidUsernameError |
| 164 | + ), |
| 165 | + .init( |
| 166 | + error: "FileTooBig", |
| 167 | + code: 300, |
| 168 | + message: "file is too big (max 1GB)", |
| 169 | + cause: nil, |
| 170 | + status: 400, |
| 171 | + errorKind: .fileTooBigError |
| 172 | + ), |
| 173 | + .init( |
| 174 | + error: "FileInfected", |
| 175 | + code: 301, |
| 176 | + message: "file is infected", |
| 177 | + cause: nil, |
| 178 | + status: 400, |
| 179 | + errorKind: .fileInfectedError |
| 180 | + ), |
| 181 | + .init( |
| 182 | + error: "FileType", |
| 183 | + code: 302, |
| 184 | + message: "unsupported file type", |
| 185 | + cause: ".wav is not supported", |
| 186 | + status: 400, |
| 187 | + errorKind: .fileTypeError |
| 188 | + ) |
| 189 | + ] |
| 190 | + for error in errors { |
| 191 | + do { |
| 192 | + try await client.getSchemaError(code: error.code) |
| 193 | + XCTFail("Expected to throw \(error)") |
| 194 | + } catch let err as WebrpcError { |
| 195 | + XCTAssertEqual(error.code, err.code) |
| 196 | + XCTAssertEqual(error.error, err.error) |
| 197 | + XCTAssertEqual(error.message, err.message) |
| 198 | + XCTAssertEqual(error.status, err.status) |
| 199 | + XCTAssertEqual(error.cause, err.cause) |
| 200 | + XCTAssertEqual(error.kind, err.kind) |
| 201 | + } catch let err { |
| 202 | + XCTFail("Expected to throw \(error) but got \(err) instead") |
| 203 | + } |
| 204 | + } |
| 205 | + } |
| 206 | +} |
| 207 | + |
| 208 | +extension XCTest { |
| 209 | + func XCTAssertThrowsError<T: Sendable>( |
| 210 | + _ expression: @autoclosure () async throws -> T, |
| 211 | + _ message: @autoclosure () -> String = "", |
| 212 | + file: StaticString = #filePath, |
| 213 | + line: UInt = #line, |
| 214 | + _ errorHandler: (_ error: Error) -> Void = { _ in } |
| 215 | + ) async { |
| 216 | + do { |
| 217 | + _ = try await expression() |
| 218 | + XCTFail(message(), file: file, line: line) |
| 219 | + } catch { |
| 220 | + errorHandler(error) |
| 221 | + } |
| 222 | + } |
| 223 | + |
| 224 | + func XCTAssertNoThrow<T: Sendable>( |
| 225 | + _ expression: @autoclosure () async throws -> T, |
| 226 | + _ message: @autoclosure () -> String = "", |
| 227 | + file: StaticString = #filePath, |
| 228 | + line: UInt = #line |
| 229 | + ) async { |
| 230 | + do { |
| 231 | + _ = try await expression() |
| 232 | + } catch { |
| 233 | + XCTFail(message(), file: file, line: line) |
| 234 | + } |
| 235 | + } |
| 236 | +} |
0 commit comments