Skip to content

Commit

Permalink
Fix range responses (#198)
Browse files Browse the repository at this point in the history
Fix range responses

### Motivation

Fixes #197, broken range responses, such as `4xx`.

### Modifications

Fix the bug, seems to have been some old copy paste gone wrong, and we didn't have a test for it.

### Result

Now range responses work again.

### Test Plan

Changed one of the status code responses to be a range response, updated fixtures.


Reviewed by: glbrntt

Builds:
     ✔︎ pull request validation (5.8) - Build finished. 
     ✔︎ pull request validation (5.9) - Build finished. 
     ✔︎ pull request validation (docc test) - Build finished. 
     ✔︎ pull request validation (integration test) - Build finished. 
     ✔︎ pull request validation (nightly) - Build finished. 
     ✔︎ pull request validation (soundness) - Build finished. 

#198
  • Loading branch information
czechboy0 authored Aug 16, 2023
1 parent e4b4624 commit 722c1ab
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -454,35 +454,24 @@ extension ServerFileTranslator {
codeBlocks.append(.expression(returnExpr))

let caseKind: SwitchCaseKind
switch responseKind {
case .code, .`default`:
let optionalStatusCode: [String]
if responseKind.wantsStatusCode {
optionalStatusCode = ["statusCode"]
} else {
optionalStatusCode = []
}
caseKind = .`case`(
.dot(responseKind.identifier),
optionalStatusCode + ["value"]
)
codeBlocks =
[
.expression(
.suppressUnusedWarning(
for: "value"
)
let optionalStatusCode: [String]
if responseKind.wantsStatusCode {
optionalStatusCode = ["statusCode"]
} else {
optionalStatusCode = []
}
caseKind = .`case`(
.dot(responseKind.identifier),
optionalStatusCode + ["value"]
)
codeBlocks =
[
.expression(
.suppressUnusedWarning(
for: "value"
)
] + codeBlocks
case let .range(range):
caseKind = .`case`(
.binaryOperation(
left: .literal(range.lowerBound),
operation: .rangeInclusive,
right: .literal(range.upperBound)
)
)
}
] + codeBlocks

return .init(
kind: caseKind,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Pet'
'400':
'4XX':
$ref: '#/components/responses/ErrorBadRequest'
/pets/stats:
get:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public struct Client: APIProtocol {
throw converter.makeUnexpectedContentTypeError(contentType: contentType)
}
return .created(.init(headers: headers, body: body))
case 400:
case 400...499:
let headers: Components.Responses.ErrorBadRequest.Headers = .init(
X_Reason: try converter.getOptionalHeaderFieldAsText(
in: response.headerFields,
Expand All @@ -241,7 +241,10 @@ public struct Client: APIProtocol {
} else {
throw converter.makeUnexpectedContentTypeError(contentType: contentType)
}
return .badRequest(.init(headers: headers, body: body))
return .clientError(
statusCode: response.statusCode,
.init(headers: headers, body: body)
)
default: return .undocumented(statusCode: response.statusCode, .init())
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ fileprivate extension UniversalServer where APIHandler: APIProtocol {
)
}
return response
case let .badRequest(value):
case let .clientError(statusCode, value):
suppressUnusedWarning(value)
var response = Response(statusCode: 400)
var response = Response(statusCode: statusCode)
suppressMutabilityWarning(&response)
try converter.setHeaderFieldAsText(
in: &response.headerFields,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1040,10 +1040,10 @@ public enum Operations {
case created(Operations.createPet.Output.Created)
/// Bad request
///
/// - Remark: Generated from `#/paths//pets/post(createPet)/responses/400`.
/// - Remark: Generated from `#/paths//pets/post(createPet)/responses/4XX`.
///
/// HTTP response code: `400 badRequest`.
case badRequest(Components.Responses.ErrorBadRequest)
/// HTTP response code: `400...499 clientError`.
case clientError(statusCode: Int, Components.Responses.ErrorBadRequest)
/// Undocumented response.
///
/// A response with a code that is not documented in the OpenAPI document.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public struct Client: APIProtocol {
throw converter.makeUnexpectedContentTypeError(contentType: contentType)
}
return .created(.init(headers: headers, body: body))
case 400:
case 400...499:
let headers: Components.Responses.ErrorBadRequest.Headers = .init(
X_hyphen_Reason: try converter.getOptionalHeaderFieldAsText(
in: response.headerFields,
Expand All @@ -241,7 +241,10 @@ public struct Client: APIProtocol {
} else {
throw converter.makeUnexpectedContentTypeError(contentType: contentType)
}
return .badRequest(.init(headers: headers, body: body))
return .clientError(
statusCode: response.statusCode,
.init(headers: headers, body: body)
)
default: return .undocumented(statusCode: response.statusCode, .init())
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ fileprivate extension UniversalServer where APIHandler: APIProtocol {
)
}
return response
case let .badRequest(value):
case let .clientError(statusCode, value):
suppressUnusedWarning(value)
var response = Response(statusCode: 400)
var response = Response(statusCode: statusCode)
suppressMutabilityWarning(&response)
try converter.setHeaderFieldAsText(
in: &response.headerFields,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1042,10 +1042,10 @@ public enum Operations {
case created(Operations.createPet.Output.Created)
/// Bad request
///
/// - Remark: Generated from `#/paths//pets/post(createPet)/responses/400`.
/// - Remark: Generated from `#/paths//pets/post(createPet)/responses/4XX`.
///
/// HTTP response code: `400 badRequest`.
case badRequest(Components.Responses.ErrorBadRequest)
/// HTTP response code: `400...499 clientError`.
case clientError(statusCode: Int, Components.Responses.ErrorBadRequest)
/// Undocumented response.
///
/// A response with a code that is not documented in the OpenAPI document.
Expand Down
3 changes: 2 additions & 1 deletion Tests/PetstoreConsumerTests/Test_Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,11 @@ final class Test_Client: XCTestCase {
let response = try await client.createPet(
.init(body: .json(.init(name: "Fluffz")))
)
guard case let .badRequest(value) = response else {
guard case let .clientError(statusCode, value) = response else {
XCTFail("Unexpected response: \(response)")
return
}
XCTAssertEqual(statusCode, 400)
XCTAssertEqual(value.headers.X_Reason, "bad luck")
switch value.body {
case .json(let body):
Expand Down
3 changes: 2 additions & 1 deletion Tests/PetstoreConsumerTests/Test_Server.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ final class Test_Server: XCTestCase {
func testCreatePet_400() async throws {
client = .init(
createPetBlock: { input in
.badRequest(
.clientError(
statusCode: 400,
.init(
headers: .init(
X_Reason: "bad luck"
Expand Down

0 comments on commit 722c1ab

Please sign in to comment.