Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RELEASE] Dyson/2.2.0 #13

Merged
merged 5 commits into from
Aug 28, 2023
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: 2 additions & 0 deletions Sources/Dyson/Dyson+Async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public extension Dyson {
@discardableResult
func data<S: Spec>(
_ spec: S,
responser: (any Responser)? = nil,
progress: ((Progress) -> Void)? = nil,
requestModifier: ((URLRequest) -> URLRequest)? = nil
) async throws -> S.Result {
Expand All @@ -76,6 +77,7 @@ public extension Dyson {
await cancellableTask.perform(
data(
spec,
responser: responser,
progress: progress,
requestModifier: requestModifier
) { result in
Expand Down
14 changes: 10 additions & 4 deletions Sources/Dyson/Dyson.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ open class Dyson {
// MARK: - Property
private let provider: any NetworkProvider

public let responser: any Responser
public let responser: (any Responser)?

public let defaultHeaders: HTTPHeaders
public let interceptors: [any Interceptor]

// MARK: - Initializer
public init(
provider: any NetworkProvider,
responser: any Responser,
responser: (any Responser)? = nil,
defaultHeaders: HTTPHeaders = [:],
interceptors: [any Interceptor] = []
) {
Expand Down Expand Up @@ -66,6 +66,7 @@ open class Dyson {
@discardableResult
open func data<S: Spec>(
_ spec: S,
responser: (any Responser)? = nil,
progress: ((Progress) -> Void)? = nil,
requestModifier: ((URLRequest) -> URLRequest)? = nil,
completion: @escaping (Result<S.Result, any Error>) -> Void
Expand Down Expand Up @@ -100,7 +101,7 @@ open class Dyson {
// Responser handle response.
self.response(
response,
responser: self.responser,
responser: responser ?? self.responser,
task: task,
spec: spec,
dyson: self,
Expand Down Expand Up @@ -262,13 +263,18 @@ open class Dyson {

private func response<S: Spec>(
_ response: Result<(Data, URLResponse), any Error>,
responser: any Responser,
responser: (any Responser)?,
task: ContainerSessionTask,
spec: S,
dyson: Dyson,
interceptors: [any Interceptor],
completion: @escaping (Result<S.Result, any Error>) -> Void
) {
guard let responser else {
completion(.failure(DysonError.responserNotRegistered))
return
}

// Process network response through an reponser.
let result: Result<S.Result, any Error>
do {
Expand Down
1 change: 1 addition & 0 deletions Sources/Dyson/Model/DysonError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Foundation

public enum DysonError: Error {
case responserNotRegistered
case invalidURL
case failedToParse(Error?)
case failedToLoadData
Expand Down
74 changes: 74 additions & 0 deletions Sources/Dyson/Model/GraphQLQuery.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// GraphQLQuery.swift
//
//
// Created by JSilver on 2023/08/21.
//

import Foundation

public struct GraphQLQuery: Encodable {
struct AnyEncodable: Encodable {
// MARK: - Property
let value: Any

// MARK: - Initializer
init<Value: Encodable>(_ value: Value) {
self.value = value
}

// MARK: - Lifecycle
func encode(to encoder: Swift.Encoder) throws {
guard let value = value as? Encodable else { return }

var container = encoder.singleValueContainer()
try container.encode(value)
}

// MARK: - Public

// MARK: - Private
}

enum CodingKeys: String, CodingKey {
case query
case operationName
case variables
}

// MARK: - Property
public let query: String
public let operationName: String
public let variables: [String: any Encodable]

// MARK: - Initializer
public init(
query: String,
operationName: String = "",
variables: [String: any Encodable] = [:]
) {
self.query = query
self.operationName = operationName
self.variables = variables

}

// MARK: - Lifecycle
public func encode(to encoder: Swift.Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encode(query, forKey: .query)

if !operationName.isEmpty {
try container.encode(operationName, forKey: .operationName)
}

if !variables.isEmpty {
try container.encode(variables.mapValues { AnyEncodable($0) }, forKey: .variables)
}
}

// MARK: - Public

// MARK: - Private
}
83 changes: 83 additions & 0 deletions Tests/DysonTests/DysonTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,87 @@ final class DysonTests: XCTestCase {
// Then
XCTAssertEqual(response, person)
}

func test_that_dyson_throw_error_when_response_data_without_responser() async throws {
// Give
let person = Person(name: "dyson")

let jsonEncoder = JSONEncoder()
let data = try jsonEncoder.encode(person)

let sut = Dyson(
provider: .mock(
dataTask: { request, completion in
completion(.success((data, .http(request, status: 200))))
}
)
)
let spec = MockSpec<Empty, Person, Empty>(
result: .codable
)

// When
do {
try await sut.data(spec)
XCTFail()
} catch {

}

// Then
}

func test_that_dyson_response_data_when_request_with_responser_even_if_responser_not_registered() async throws {
// Give
let person = Person(name: "dyson")

let jsonEncoder = JSONEncoder()
let data = try jsonEncoder.encode(person)

let sut = Dyson(
provider: .mock(
dataTask: { request, completion in
completion(.success((data, .http(request, status: 200))))
}
)
)
let spec = MockSpec<Empty, Person, Empty>(
result: .codable
)

// When
try await sut.data(spec, responser: .default)

// Then
}

func test_that_dyson_throw_error_when_response_data_even_if_responser_registered() async throws {
// Give
let person = Person(name: "dyson")

let jsonEncoder = JSONEncoder()
let data = try jsonEncoder.encode(person)

let sut = Dyson(
provider: .mock(
dataTask: { request, completion in
completion(.success((data, .http(request, status: 200))))
}
),
responser: .default
)
let spec = MockSpec<Empty, Person, Empty>(
result: .codable
)

// When
do {
try await sut.data(spec, responser: .error(TestError(message: "error")))
XCTFail()
} catch {

}

// Then
}
}
35 changes: 35 additions & 0 deletions Tests/DysonTests/Model/Responser/ErrorResponser.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// ErrorResponser.swift
//
//
// Created by jsilver on 2022/01/23.
//

import Foundation
import Dyson

extension Responser {
static func error(_ error: any Error) -> Self where Self == ErrorResponser { ErrorResponser(error) }
}

struct ErrorResponser: Responser {
// MARK: - Property
private let error: any Error

// MARK: - Initializer
init(_ error: any Error) {
self.error = error
}

// MARK: - Lifecycle
func response<S: Spec>(
_ response: Result<(Data, URLResponse), any Error>,
spec: S
) throws -> S.Result {
throw error
}

// MARK: - Public

// MARK: - Private
}