Added support for Buildkite's JSON errors, and wrote more tests for pagination
This commit is contained in:
parent
2865672821
commit
9481c26290
|
@ -49,7 +49,7 @@ public final class Buildkite {
|
|||
transport.send(request: request, completion: handleContentfulResponse(completion: completion))
|
||||
}
|
||||
|
||||
public func send<R: Resource & HasResponseBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil, completion: @escaping (Result<Response<R.Content>, Error>) -> Void) {
|
||||
public func send<R: Resource & Paginated>(_ resource: R, pageOptions: PageOptions? = nil, completion: @escaping (Result<Response<R.Content>, Error>) -> Void) {
|
||||
let request = URLRequest(resource, configuration: configuration, pageOptions: pageOptions)
|
||||
transport.send(request: request, completion: handleContentfulResponse(completion: completion))
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public final class Buildkite {
|
|||
transport.send(request: request, completion: handleContentfulResponse(completion: completion))
|
||||
}
|
||||
|
||||
public func send<R: Resource & HasRequestBody & HasResponseBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil, completion: @escaping (Result<Response<R.Content>, Error>) -> Void) {
|
||||
public func send<R: Resource & HasRequestBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil, completion: @escaping (Result<Response<R.Content>, Error>) -> Void) {
|
||||
let request: URLRequest
|
||||
do {
|
||||
request = try URLRequest(resource, configuration: configuration, encoder: encoder, pageOptions: pageOptions)
|
||||
|
@ -92,17 +92,6 @@ public final class Buildkite {
|
|||
transport.send(request: request, completion: handleEmptyResponse(completion: completion))
|
||||
}
|
||||
|
||||
public func send<R: Resource & HasRequestBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil, completion: @escaping (Result<Response<Void>, Error>) -> Void) {
|
||||
let request: URLRequest
|
||||
do {
|
||||
request = try URLRequest(resource, configuration: configuration, encoder: encoder, pageOptions: pageOptions)
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
transport.send(request: request, completion: handleEmptyResponse(completion: completion))
|
||||
}
|
||||
|
||||
private func handleContentfulResponse<Content: Decodable>(completion: @escaping (Result<Response<Content>, Error>) -> Void) -> Transport.Completion {
|
||||
return { [weak self] result in
|
||||
guard let self = self else {
|
||||
|
@ -113,7 +102,7 @@ public final class Buildkite {
|
|||
do {
|
||||
let data: Data
|
||||
(data, response) = try result.get()
|
||||
try self.checkResponseForIssues(response)
|
||||
try self.checkResponseForIssues(response, data: data)
|
||||
content = try self.decoder.decode(Content.self, from: data)
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
|
@ -140,15 +129,20 @@ public final class Buildkite {
|
|||
}
|
||||
}
|
||||
|
||||
private func checkResponseForIssues(_ response: URLResponse) throws {
|
||||
private func checkResponseForIssues(_ response: URLResponse, data: Data? = nil) throws {
|
||||
guard let response = response as? HTTPURLResponse,
|
||||
let statusCode = StatusCode(rawValue: response.statusCode) else {
|
||||
throw ResponseError.missingResponse
|
||||
}
|
||||
if !statusCode.isSuccess {
|
||||
if let data = data,
|
||||
let errorIntermediary = try? decoder.decode(BuildkiteError.Intermediary.self, from: data) {
|
||||
throw BuildkiteError(statusCode: statusCode, intermediary: errorIntermediary)
|
||||
} else {
|
||||
throw statusCode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Combine)
|
||||
|
@ -159,7 +153,7 @@ extension Buildkite {
|
|||
public func sendPublisher<R: Resource & HasResponseBody>(_ resource: R) -> AnyPublisher<Response<R.Content>, Error> {
|
||||
transport.sendPublisher(request: URLRequest(resource, configuration: configuration))
|
||||
.tryMap {
|
||||
try self.checkResponseForIssues($0.response)
|
||||
try self.checkResponseForIssues($0.response, data: $0.data)
|
||||
let content = try self.decoder.decode(R.Content.self, from: $0.data)
|
||||
return Response(content: content, response: $0.response)
|
||||
}
|
||||
|
@ -169,7 +163,7 @@ extension Buildkite {
|
|||
public func sendPublisher<R: Resource & HasResponseBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil) -> AnyPublisher<Response<R.Content>, Error> {
|
||||
transport.sendPublisher(request: URLRequest(resource, configuration: configuration, pageOptions: pageOptions))
|
||||
.tryMap {
|
||||
try self.checkResponseForIssues($0.response)
|
||||
try self.checkResponseForIssues($0.response, data: $0.data)
|
||||
let content = try self.decoder.decode(R.Content.self, from: $0.data)
|
||||
return Response(content: content, response: $0.response)
|
||||
}
|
||||
|
@ -181,19 +175,19 @@ extension Buildkite {
|
|||
.publisher
|
||||
.flatMap(transport.sendPublisher)
|
||||
.tryMap {
|
||||
try self.checkResponseForIssues($0.response)
|
||||
try self.checkResponseForIssues($0.response, data: $0.data)
|
||||
let content = try self.decoder.decode(R.Content.self, from: $0.data)
|
||||
return Response(content: content, response: $0.response)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
public func sendPublisher<R: Resource & HasRequestBody & HasResponseBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil) -> AnyPublisher<Response<R.Content>, Error> {
|
||||
public func sendPublisher<R: Resource & HasRequestBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil) -> AnyPublisher<Response<R.Content>, Error> {
|
||||
Result { try URLRequest(resource, configuration: configuration, encoder: encoder, pageOptions: pageOptions) }
|
||||
.publisher
|
||||
.flatMap(transport.sendPublisher)
|
||||
.tryMap {
|
||||
try self.checkResponseForIssues($0.response)
|
||||
try self.checkResponseForIssues($0.response, data: $0.data)
|
||||
let content = try self.decoder.decode(R.Content.self, from: $0.data)
|
||||
return Response(content: content, response: $0.response)
|
||||
}
|
||||
|
@ -219,16 +213,5 @@ extension Buildkite {
|
|||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func sendPublisher<R: Resource & HasRequestBody & Paginated>(_ resource: R, pageOptions: PageOptions? = nil) -> AnyPublisher<Response<Void>, Error> {
|
||||
Result { try URLRequest(resource, configuration: configuration, encoder: encoder, pageOptions: pageOptions) }
|
||||
.publisher
|
||||
.flatMap(transport.sendPublisher)
|
||||
.tryMap {
|
||||
try self.checkResponseForIssues($0.response)
|
||||
return Response(content: (), response: $0.response)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -127,7 +127,7 @@ public enum Job: Codable, Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
public struct LogOutput: Codable {
|
||||
public struct LogOutput: Codable, Equatable {
|
||||
public var url: URL // Resource<Job.Resources.GetLogOutput>
|
||||
public var content: String
|
||||
public var size: Int
|
||||
|
|
|
@ -17,6 +17,23 @@ enum ResponseError: Error {
|
|||
case unexpectedlyNoContent
|
||||
}
|
||||
|
||||
public struct BuildkiteError: Error {
|
||||
public var statusCode: StatusCode
|
||||
public var message: String
|
||||
public var errors: [String]
|
||||
|
||||
init(statusCode: StatusCode, intermediary: Intermediary) {
|
||||
self.statusCode = statusCode
|
||||
self.message = intermediary.message ?? ""
|
||||
self.errors = intermediary.errors ?? []
|
||||
}
|
||||
|
||||
struct Intermediary: Codable {
|
||||
var message: String?
|
||||
var errors: [String]?
|
||||
}
|
||||
}
|
||||
|
||||
public struct Response<T> {
|
||||
public let content: T
|
||||
public let response: URLResponse
|
||||
|
|
|
@ -12,7 +12,7 @@ import Foundation
|
|||
import FoundationNetworking
|
||||
#endif
|
||||
|
||||
public enum StatusCode: Int, Error {
|
||||
public enum StatusCode: Int, Error, Codable {
|
||||
/// The request was successfully processed by Buildkite.
|
||||
case ok = 200
|
||||
|
||||
|
@ -22,6 +22,9 @@ public enum StatusCode: Int, Error {
|
|||
/// The request has been accepted, but not yet processed.
|
||||
case accepted = 202
|
||||
|
||||
/// The request was found
|
||||
case found = 302
|
||||
|
||||
/// The response to the request can be found under a different URL in the Location header and can be retrieved using a GET method on that resource.
|
||||
case seeOther = 303
|
||||
|
||||
|
@ -49,8 +52,6 @@ public enum StatusCode: Int, Error {
|
|||
case unprocessableEntity = 422
|
||||
|
||||
/// The requested shop is currently locked. Shops are locked if they repeatedly exceed their API request limit, or if there is an issue with the account, such as a detected compromise or fraud risk.
|
||||
///
|
||||
/// Contact support if your shop is locked.
|
||||
case locked = 423
|
||||
|
||||
/// The request was not accepted because the application has exceeded the rate limit. See the API Call Limit documentation for a breakdown of Buildkite's rate-limiting mechanism.
|
||||
|
@ -72,5 +73,6 @@ public enum StatusCode: Int, Error {
|
|||
self == .ok
|
||||
|| self == .created
|
||||
|| self == .accepted
|
||||
|| self == .found
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,8 +91,8 @@ extension Job.Resources {
|
|||
}
|
||||
|
||||
/// Get a job’s log output
|
||||
public struct LogOutput: Resource {
|
||||
typealias Content = Job.LogOutput
|
||||
public struct LogOutput: Resource, HasResponseBody {
|
||||
public typealias Content = Job.LogOutput
|
||||
/// organization slug
|
||||
public var organization: String
|
||||
/// pipeline slug
|
||||
|
@ -166,3 +166,36 @@ extension Job.Resources {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Job.Resources.LogOutput {
|
||||
public struct Alternative: Resource, HasResponseBody {
|
||||
public enum Format: String {
|
||||
case html
|
||||
case plainText = "txt"
|
||||
}
|
||||
|
||||
public typealias Content = String
|
||||
/// organization slug
|
||||
public var organization: String
|
||||
/// pipeline slug
|
||||
public var pipeline: String
|
||||
/// build number
|
||||
public var build: Int
|
||||
/// job ID
|
||||
public var job: UUID
|
||||
|
||||
public var format: Format
|
||||
|
||||
public var path: String {
|
||||
"organizations/\(organization)/pipelines/\(pipeline)/builds/\(build)/jobs/\(job)/log.\(format)"
|
||||
}
|
||||
|
||||
public init(organization: String, pipeline: String, build: Int, job: UUID, format: Format) {
|
||||
self.organization = organization
|
||||
self.pipeline = pipeline
|
||||
self.build = build
|
||||
self.job = job
|
||||
self.format = format
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ extension Team.Resources {
|
|||
public typealias Content = [Team]
|
||||
/// organization slug
|
||||
public var organization: String
|
||||
|
||||
/// Filters the results to teams that have the given user as a member.
|
||||
public var userId: UUID?
|
||||
|
||||
public var path: String {
|
||||
|
|
|
@ -22,7 +22,10 @@ class BuildkiteTests: XCTestCase {
|
|||
private struct TestData {
|
||||
enum Case {
|
||||
case success
|
||||
case successPaginated
|
||||
case successNoContent
|
||||
case successHasBody
|
||||
case successHasBodyPaginated
|
||||
case badResponse
|
||||
case unsuccessfulResponse
|
||||
case noData
|
||||
|
@ -38,8 +41,14 @@ class BuildkiteTests: XCTestCase {
|
|||
switch testCase {
|
||||
case .success:
|
||||
responses = [try MockData.mockingSuccess(with: resources.content, url: configuration.baseURL)]
|
||||
case .successPaginated:
|
||||
responses = [try MockData.mockingSuccess(with: resources.paginatedContent, url: configuration.baseURL)]
|
||||
case .successNoContent:
|
||||
responses = [MockData.mockingSuccessNoContent(url: configuration.baseURL)]
|
||||
case .successHasBody:
|
||||
responses = [MockData.mockingSuccessNoContent(url: configuration.baseURL)]
|
||||
case .successHasBodyPaginated:
|
||||
responses = [try MockData.mockingSuccess(with: resources.bodyAndPaginatedContent, url: configuration.baseURL)]
|
||||
case .badResponse:
|
||||
responses = [MockData.mockingIncompatibleResponse(for: configuration.baseURL)]
|
||||
case .unsuccessfulResponse:
|
||||
|
@ -73,11 +82,55 @@ extension BuildkiteTests {
|
|||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testClosureBasedRequestWithPagination() throws {
|
||||
let testData = try TestData(testCase: .success)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
testData.client.send(testData.resources.paginatedContentResource, pageOptions: PageOptions(page: 1, perPage: 30)) { result in
|
||||
do {
|
||||
let response = try result.get()
|
||||
XCTAssertEqual(testData.resources.paginatedContent, response.content)
|
||||
XCTAssertNotNil(response.page)
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testClosureBasedRequestNoContent() throws {
|
||||
let testData = try TestData(testCase: .successNoContent)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
testData.client.send(testData.resources.noContentResource) { _ in
|
||||
testData.client.send(testData.resources.noContentNoBodyResource) { _ in
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testClosureBasedRequestHasBody() throws {
|
||||
let testData = try TestData(testCase: .successHasBody)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
testData.client.send(testData.resources.bodyResource) { _ in
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testClosureBasedRequestHasBodyWithPagination() throws {
|
||||
let testData = try TestData(testCase: .successHasBodyPaginated)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
testData.client.send(testData.resources.bodyAndPaginatedResource, pageOptions: PageOptions(page: 1, perPage: 30)) { result in
|
||||
do {
|
||||
let response = try result.get()
|
||||
XCTAssertEqual(testData.resources.bodyAndPaginatedContent, response.content)
|
||||
XCTAssertNotNil(response.page)
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation])
|
||||
|
@ -149,11 +202,30 @@ extension BuildkiteTests {
|
|||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testPublisherBasedRequestWithPagination() throws {
|
||||
let testData = try TestData(testCase: .success)
|
||||
let expectation = XCTestExpectation()
|
||||
var cancellables: Set<AnyCancellable> = []
|
||||
testData.client.sendPublisher(testData.resources.paginatedContentResource, pageOptions: PageOptions(page: 1, perPage: 30))
|
||||
.sink(receiveCompletion: {
|
||||
if case let .failure(error) = $0 {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
},
|
||||
receiveValue: {
|
||||
XCTAssertEqual(testData.resources.paginatedContent, $0.content)
|
||||
XCTAssertNotNil($0.page)
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testPublisherBasedRequestNoContent() throws {
|
||||
let testData = try TestData(testCase: .success)
|
||||
let expectation = XCTestExpectation()
|
||||
var cancellables: Set<AnyCancellable> = []
|
||||
testData.client.sendPublisher(testData.resources.noContentResource)
|
||||
testData.client.sendPublisher(testData.resources.noContentNoBodyResource)
|
||||
.sink(receiveCompletion: {
|
||||
if case let .failure(error) = $0 {
|
||||
XCTFail(error.localizedDescription)
|
||||
|
@ -164,6 +236,40 @@ extension BuildkiteTests {
|
|||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testPublisherBasedRequestHasBody() throws {
|
||||
let testData = try TestData(testCase: .successHasBody)
|
||||
let expectation = XCTestExpectation()
|
||||
var cancellables: Set<AnyCancellable> = []
|
||||
testData.client.sendPublisher(testData.resources.bodyResource)
|
||||
.sink(receiveCompletion: {
|
||||
if case let .failure(error) = $0 {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
}, receiveValue: { _ in })
|
||||
.store(in: &cancellables)
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testPublisherBasedRequestHasBodyWithPagination() throws {
|
||||
let testData = try TestData(testCase: .successHasBodyPaginated)
|
||||
let expectation = XCTestExpectation()
|
||||
var cancellables: Set<AnyCancellable> = []
|
||||
testData.client.sendPublisher(testData.resources.bodyAndPaginatedResource, pageOptions: PageOptions(page: 1, perPage: 30))
|
||||
.sink(receiveCompletion: {
|
||||
if case let .failure(error) = $0 {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
},
|
||||
receiveValue: {
|
||||
XCTAssertEqual(testData.resources.bodyAndPaginatedContent, $0.content)
|
||||
XCTAssertNotNil($0.page)
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testPublisherBasedRequestInvalidResponse() throws {
|
||||
let testData = try TestData(testCase: .badResponse)
|
||||
let expectation = XCTestExpectation()
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
//
|
||||
// PaginationTests.swift
|
||||
// Buildkite
|
||||
//
|
||||
// Created by Aaron Sky on 5/7/20.
|
||||
// Copyright © 2020 Aaron Sky. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
@testable import Buildkite
|
||||
|
||||
#if canImport(FoundationNetworking)
|
||||
import FoundationNetworking
|
||||
#endif
|
||||
|
||||
class PaginationTests: XCTestCase {
|
||||
func testPagination() throws {
|
||||
let expected = [Pipeline(), Pipeline()]
|
||||
let context = try MockContext(content: expected)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
context.client.send(Pipeline.Resources.List(organization: "buildkite"), pageOptions: PageOptions(page: 1, perPage: 30)) { result in
|
||||
do {
|
||||
let response = try result.get()
|
||||
XCTAssertEqual(expected, response.content)
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation])
|
||||
}
|
||||
}
|
|
@ -55,13 +55,51 @@ class JobsTests: XCTestCase {
|
|||
}
|
||||
|
||||
func testJobsLogOutput() throws {
|
||||
let context = MockContext()
|
||||
let expected = Job.LogOutput()
|
||||
let context = try MockContext(content: expected)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
context.client.send(Job.Resources.LogOutput(organization: "buildkite", pipeline: "my-pipeline", build: 1, job: UUID())) { result in
|
||||
do {
|
||||
_ = try result.get()
|
||||
let response = try result.get()
|
||||
XCTAssertEqual(expected, response.content)
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testJobsLogOutputAlternativePlainText() throws {
|
||||
let expected = "hello friends"
|
||||
let context = try MockContext(content: expected)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
context.client.send(Job.Resources.LogOutput.Alternative(organization: "buildkite", pipeline: "my-pipeline", build: 1, job: UUID(), format: .plainText)) { result in
|
||||
do {
|
||||
let response = try result.get()
|
||||
XCTAssertEqual(expected, response.content)
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation])
|
||||
}
|
||||
|
||||
func testJobsLogOutputAlternativeHTML() throws {
|
||||
let expected = "hello friends"
|
||||
let context = try MockContext(content: expected)
|
||||
|
||||
let expectation = XCTestExpectation()
|
||||
|
||||
context.client.send(Job.Resources.LogOutput.Alternative(organization: "buildkite", pipeline: "my-pipeline", build: 1, job: UUID(), format: .html)) { result in
|
||||
do {
|
||||
let response = try result.get()
|
||||
XCTAssertEqual(expected, response.content)
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
|
@ -104,3 +142,12 @@ class JobsTests: XCTestCase {
|
|||
wait(for: [expectation])
|
||||
}
|
||||
}
|
||||
|
||||
extension Job.LogOutput {
|
||||
init() {
|
||||
self.init(url: URL(),
|
||||
content: "hello friends",
|
||||
size: 13,
|
||||
headerTimes: [])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,13 @@ import FoundationNetworking
|
|||
#endif
|
||||
|
||||
struct MockResources {
|
||||
struct NoContentNoBody: Resource {
|
||||
typealias Content = Void
|
||||
let path = "mock"
|
||||
}
|
||||
|
||||
var noContentNoBodyResource = NoContentNoBody()
|
||||
|
||||
struct HasContent: Resource, HasResponseBody {
|
||||
struct Content: Codable, Equatable {
|
||||
var name: String
|
||||
|
@ -25,12 +32,49 @@ struct MockResources {
|
|||
var contentResource = HasContent()
|
||||
var content = HasContent.Content(name: "Jeff", age: 35)
|
||||
|
||||
struct NoContent: Resource {
|
||||
typealias Content = Void
|
||||
struct HasPaginatedContent: Resource, Paginated {
|
||||
struct Content: Codable, Equatable {
|
||||
var name: String
|
||||
var age: Int
|
||||
}
|
||||
|
||||
let path = "mock"
|
||||
}
|
||||
|
||||
var noContentResource = NoContent()
|
||||
var paginatedContentResource = HasPaginatedContent()
|
||||
var paginatedContent = HasPaginatedContent.Content(name: "Jeff", age: 35)
|
||||
|
||||
struct HasBody: Resource, HasRequestBody {
|
||||
struct Body: Codable, Equatable {
|
||||
var name: String
|
||||
var age: Int
|
||||
}
|
||||
|
||||
var body: Body
|
||||
|
||||
let path = "mock"
|
||||
}
|
||||
|
||||
var bodyResource = HasBody(body: HasBody.Body(name: "Jeff", age: 35))
|
||||
|
||||
struct HasBodyAndPaginated: Resource, HasRequestBody, Paginated {
|
||||
struct Body: Codable, Equatable {
|
||||
var name: String
|
||||
var age: Int
|
||||
}
|
||||
|
||||
struct Content: Codable, Equatable {
|
||||
var name: String
|
||||
var age: Int
|
||||
}
|
||||
|
||||
var body: Body
|
||||
|
||||
let path = "mock"
|
||||
}
|
||||
|
||||
var bodyAndPaginatedResource = HasBodyAndPaginated(body: HasBodyAndPaginated.Body(name: "Jeff", age: 35))
|
||||
var bodyAndPaginatedContent = HasBodyAndPaginated.Content(name: "Jeff", age: 35)
|
||||
}
|
||||
|
||||
enum MockData {
|
||||
|
@ -57,7 +101,7 @@ extension MockData {
|
|||
}
|
||||
|
||||
static func mockingUnsuccessfulResponse(for url: URL) -> (Data, URLResponse) {
|
||||
return (Data(), urlResponse(for: url, status: .notFound))
|
||||
return (#"{"message":"not found","errors": ["go away"]}"#.data(using: .utf8)!, urlResponse(for: url, status: .notFound))
|
||||
}
|
||||
|
||||
static func mockingSuccessNoContent(for request: URLRequest) throws -> (Data, URLResponse) {
|
||||
|
@ -76,7 +120,7 @@ extension MockData {
|
|||
HTTPURLResponse(url: url,
|
||||
statusCode: status,
|
||||
httpVersion: "HTTP/1.1",
|
||||
headerFields: [:])!
|
||||
headerFields: ["Link":#"<https://api.buildkite.com/v2/organizations/my-great-org/pipelines/my-pipeline/builds?api_key=f8582f070276d764ce3dd4c6d57be92574dccf86&page=3>; rel="prev",<https://api.buildkite.com/v2/organizations/my-great-org/pipelines/my-pipeline/builds?api_key=f8582f070276d764ce3dd4c6d57be92574dccf86&page=5>; rel="next",<https://api.buildkite.com/v2/organizations/my-great-org/pipelines/my-pipeline/builds?api_key=f8582f070276d764ce3dd4c6d57be92574dccf86&page=1>; rel="first", <https://api.buildkite.com/v2/organizations/my-great-org/pipelines/my-pipeline/builds?api_key=f8582f070276d764ce3dd4c6d57be92574dccf86&page=10>; rel="last""#])!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue