Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ let package = Package(
// Tests-only: Runtime library linked by generated code, and also
// helps keep the runtime library new enough to work with the generated
// code.
.package(url: "https://github.com/apple/swift-openapi-runtime", from: "1.12.2", traits: []),
.package(url: "https://github.com/apple/swift-openapi-runtime", from: "1.13.0", traits: []),
.package(url: "https://github.com/apple/swift-http-types", from: "1.7.0"),
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ At the time of writing, the list of coders used is as follows.

| Format | Encoder | Decoder | Supported in |
| ------ | ------- | ------- | ----- |
| JSON | `Foundation.JSONEncoder` | `Foundation.JSONDecoder` | Bodies, headers |
| JSON | `Foundation.JSONEncoder` | `Foundation.JSONDecoder` | Bodies, headers, query items |
| URI (†) | `OpenAPIRuntime.URIEncoder` | `OpenAPIRuntime.URIDecoder` | Path, query, headers |
| Plain text | `OpenAPIRuntime.StringEncoder` | `OpenAPIRuntime.StringDecoder` | Bodies |

Expand Down Expand Up @@ -91,6 +91,7 @@ method parameters: value or type of value
| common | get | header field | JSON | required | getRequiredHeaderFieldAsJSON |
| client | set | request path | URI | required | renderedPath |
| client | set | request query | URI | both | setQueryItemAsURI |
| client | set | request query | JSON | both | setQueryItemAsJSON |
| client | set | request body | JSON | optional | setOptionalRequestBodyAsJSON |
| client | set | request body | JSON | required | setRequiredRequestBodyAsJSON |
| client | set | request body | binary | optional | setOptionalRequestBodyAsBinary |
Expand All @@ -104,6 +105,8 @@ method parameters: value or type of value
| server | get | request path | URI | required | getPathParameterAsURI |
| server | get | request query | URI | optional | getOptionalQueryItemAsURI |
| server | get | request query | URI | required | getRequiredQueryItemAsURI |
| server | get | request query | JSON | optional | getOptionalQueryItemAsJSON |
| server | get | request query | JSON | required | getRequiredQueryItemAsJSON |
| server | get | request body | JSON | optional | getOptionalRequestBodyAsJSON |
| server | get | request body | JSON | required | getRequiredRequestBodyAsJSON |
| server | get | request body | binary | optional | getOptionalRequestBodyAsBinary |
Expand Down
20 changes: 20 additions & 0 deletions Tests/OpenAPIGeneratorReferenceTests/Resources/Docs/petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ paths:
state:
type: string
- $ref: '#/components/parameters/query.born-since'
- $ref: '#/components/parameters/query.json-filters'
responses:
'200':
description: A paged array of pets
Expand Down Expand Up @@ -296,6 +297,16 @@ components:
name: since
schema:
$ref: '#/components/schemas/DOB'
query.json-filters:
description: Filter pets with structured JSON criteria.
in: query
name: jsonFilters
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/PetFilter'
path.petId:
name: petId
in: path
Expand All @@ -305,6 +316,15 @@ components:
type: integer
format: int64
schemas:
PetFilter:
type: object
required:
- name
properties:
name:
type: string
state:
type: string
Pet:
type: object
title: "Pet title"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ public struct Client: APIProtocol {
name: "since",
value: input.query.since
)
try converter.setQueryItemAsJSON(
in: &request,
style: .form,
explode: true,
name: "jsonFilters",
value: input.query.jsonFilters
)
converter.setAcceptHeader(
in: &request.headerFields,
contentTypes: input.headers.accept
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ fileprivate extension UniversalServer where APIHandler: APIProtocol {
explode: true,
name: "since",
as: Components.Parameters.Query_bornSince.self
),
jsonFilters: try converter.getOptionalQueryItemAsJSON(
in: request.soar_query,
style: .form,
explode: true,
name: "jsonFilters",
as: Components.Parameters.Query_jsonFilters.self
)
)
let headers: Operations.ListPets.Input.Headers = .init(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ extension Components {
///
/// - Remark: Generated from `#/components/parameters/query.born-since`.
public typealias Query_bornSince = Components.Schemas.Dob
/// Filter pets with structured JSON criteria.
///
/// - Remark: Generated from `#/components/parameters/query.json-filters`.
public typealias Query_jsonFilters = [Components.Schemas.PetFilter]
/// The id of the pet to retrieve
///
/// - Remark: Generated from `#/components/parameters/path.petId`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@ public import struct Foundation.Date
extension Components {
/// Types generated from the `#/components/schemas` section of the OpenAPI document.
public enum Schemas {
/// - Remark: Generated from `#/components/schemas/PetFilter`.
public struct PetFilter: Codable, Hashable, Sendable {
/// - Remark: Generated from `#/components/schemas/PetFilter/name`.
public var name: Swift.String
/// - Remark: Generated from `#/components/schemas/PetFilter/state`.
public var state: Swift.String?
/// Creates a new `PetFilter`.
///
/// - Parameters:
/// - name:
/// - state:
public init(
name: Swift.String,
state: Swift.String? = nil
) {
self.name = name
self.state = state
}
public enum CodingKeys: String, CodingKey {
case name
case state
}
}
/// Pet metadata
///
/// - Remark: Generated from `#/components/schemas/Pet`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ public enum Operations {
///
/// - Remark: Generated from `#/paths/pets/GET/query/since`.
public var since: Components.Parameters.Query_bornSince?
/// Filter pets with structured JSON criteria.
///
/// - Remark: Generated from `#/paths/pets/GET/query/jsonFilters`.
public var jsonFilters: Components.Parameters.Query_jsonFilters?
/// Creates a new `Query`.
///
/// - Parameters:
Expand All @@ -109,20 +113,23 @@ public enum Operations {
/// - sort:
/// - filter:
/// - since: Supply this parameter to filter pets born since the provided date.
/// - jsonFilters: Filter pets with structured JSON criteria.
public init(
limit: Swift.Int32? = nil,
habitat: Operations.ListPets.Input.Query.HabitatPayload? = nil,
feeds: Operations.ListPets.Input.Query.FeedsPayload? = nil,
sort: Operations.ListPets.Input.Query.SortPayload? = nil,
filter: Operations.ListPets.Input.Query.FilterPayload,
since: Components.Parameters.Query_bornSince? = nil
since: Components.Parameters.Query_bornSince? = nil,
jsonFilters: Components.Parameters.Query_jsonFilters? = nil
) {
self.limit = limit
self.habitat = habitat
self.feeds = feeds
self.sort = sort
self.filter = filter
self.since = since
self.jsonFilters = jsonFilters
}
}
public var query: Operations.ListPets.Input.Query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3126,6 +3126,75 @@ final class SnippetBasedReferenceTests: XCTestCase {
)
}

func testRequestWithRequiredJSONQueryItem() throws {
try self.assertRequestInTypesClientServerTranslation(
"""
/foo:
get:
parameters:
- name: filters
in: query
required: true
content:
application/json:
schema:
type: array
items:
type: string
responses:
default:
description: Response
""",
input: """
public struct Input: Sendable, Hashable {
public struct Query: Sendable, Hashable {
public var filters: [Swift.String]
public init(filters: [Swift.String]) {
self.filters = filters
}
}
public var query: Operations.get_sol_foo.Input.Query
public init(query: Operations.get_sol_foo.Input.Query) {
self.query = query
}
}
""",
client: """
{ input in
let path = try converter.renderedPath(
template: "/foo",
parameters: []
)
var request: HTTPTypes.HTTPRequest = .init(
soar_path: path,
method: .get
)
suppressMutabilityWarning(&request)
try converter.setQueryItemAsJSON(
in: &request,
style: .form,
explode: true,
name: "filters",
value: input.query.filters
)
return (request, nil)
}
""",
server: """
{ request, requestBody, metadata in
let query: Operations.get_sol_foo.Input.Query = .init(filters: try converter.getRequiredQueryItemAsJSON(
in: request.soar_query,
style: .form,
explode: true,
name: "filters",
as: [Swift.String].self
))
return Operations.get_sol_foo.Input(query: query)
}
"""
)
}

func testRequestWithPathParams() throws {
try self.assertRequestInTypesClientServerTranslation(
"""
Expand Down
5 changes: 3 additions & 2 deletions Tests/PetstoreConsumerTests/Test_Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class Test_Client: XCTestCase {
XCTAssertEqual(operationID, "listPets")
XCTAssertEqual(
request.path,
"/pets?limit=24&habitat=water&feeds=herbivore&feeds=carnivore&sort%5Bid%5D=ascending&sort%5Bname%5D=descending&filter%5Bname%5D=whale&since=2023-01-18T10%3A04%3A11Z"
"/pets?limit=24&habitat=water&feeds=herbivore&feeds=carnivore&sort%5Bid%5D=ascending&sort%5Bname%5D=descending&filter%5Bname%5D=whale&since=2023-01-18T10%3A04%3A11Z&jsonFilters=%5B%7B%22name%22%3A%22whale%22%2C%22state%22%3A%22water%22%7D%2C%7B%22name%22%3A%22dog%22%7D%5D"
)
XCTAssertEqual(baseURL.absoluteString, "/api")
XCTAssertEqual(request.method, .get)
Expand Down Expand Up @@ -72,7 +72,8 @@ final class Test_Client: XCTestCase {
feeds: [.herbivore, .carnivore],
sort: .init(id: "ascending", name: "descending"),
filter: .init(name: "whale"),
since: .test
since: .test,
jsonFilters: [.init(name: "whale", state: "water"), .init(name: "dog")]
),
headers: .init(myRequestUUID: "abcd-1234")
)
Expand Down
6 changes: 4 additions & 2 deletions Tests/PetstoreConsumerTests/Test_Server.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ final class Test_Server: XCTestCase {
XCTAssertEqual(input.query.since, .test)
XCTAssertEqual(input.query.feeds, [.carnivore, .herbivore])
XCTAssertEqual(input.query.sort, .init(id: "ascending", name: "descending"))
XCTAssertEqual(input.query.jsonFilters, [.init(name: "whale", state: "water"), .init(name: "dog")])
XCTAssertEqual(input.headers.myRequestUUID, "abcd-1234")
return .ok(
.init(
Expand All @@ -45,7 +46,7 @@ final class Test_Server: XCTestCase {
let (response, responseBody) = try await server.listPets(
.init(
soar_path:
"/api/pets?limit=24&habitat=water&feeds=carnivore&feeds=herbivore&sort%5Bid%5D=ascending&sort%5Bname%5D=descending&filter%5Bname%5D=whale&since=\(Date.testString)",
"/api/pets?limit=24&habitat=water&feeds=carnivore&feeds=herbivore&sort%5Bid%5D=ascending&sort%5Bname%5D=descending&filter%5Bname%5D=whale&since=\(Date.testString)&jsonFilters=%5B%7B%22name%22%3A%22whale%22%2C%22state%22%3A%22water%22%7D%2C%7B%22name%22%3A%22dog%22%7D%5D",
method: .get,
headerFields: [.init("My-Request-UUID")!: "abcd-1234"]
),
Expand Down Expand Up @@ -81,7 +82,8 @@ final class Test_Server: XCTestCase {

func testListPets_default() async throws {
client = .init(listPetsBlock: { input in
.default(statusCode: 400, .init(body: .json(.init(code: 1, me_dollar_sage: "Oh no!"))))
XCTAssertNil(input.query.jsonFilters)
return .default(statusCode: 400, .init(body: .json(.init(code: 1, me_dollar_sage: "Oh no!"))))
})
let (response, responseBody) = try await server.listPets(
.init(soar_path: "/api/pets?filter%5Bname%5D=whale", method: .get),
Expand Down
Loading