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
17 changes: 17 additions & 0 deletions .github/actionlint-matcher.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"problemMatcher": [
{
"owner": "actionlint",
"pattern": [
{
"regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)?:(?:\\x1b\\[\\d+m)?(\\d+)(?:\\x1b\\[\\d+m)?:(?:\\x1b\\[\\d+m)?(\\d+)(?:\\x1b\\[\\d+m)?: (?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)? \\[(.+?)\\]$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
}
]
}
26 changes: 26 additions & 0 deletions .github/workflows/lint-swift.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Lint Swift

on:
pull_request:
branches:
- '*'
paths:
- '**/*.swift'
- 'Package.swift'
- 'Package.resolved'
- '.swiftlint.yml'
- '.github/workflows/lint-swift.yml'

jobs:
swiftlint:
name: SwiftLint
runs-on: macos-latest

steps:
- uses: actions/checkout@v4

- name: Install SwiftLint
run: brew install swiftlint

- name: Run SwiftLint
run: swiftlint lint --strict
30 changes: 30 additions & 0 deletions .github/workflows/lint-workflows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Lint Workflows

on:
pull_request:
branches:
- '*'
paths:
- '.github/workflows/*.yml'
- '.github/actionlint-matcher.json'

jobs:
actionlint:
name: actionlint
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- uses: actions/checkout@v4

- name: Download actionlint
id: get_actionlint
run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
shell: bash

- name: Register problem matcher
run: echo "::add-matcher::.github/actionlint-matcher.json"

- name: Run actionlint
run: ${{ steps.get_actionlint.outputs.executable }} -color
shell: bash
36 changes: 36 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Test

on:
push:
branches:
- main
paths:
- '**/*.swift'
- 'Package.swift'
- 'Package.resolved'
- '.github/workflows/test.yml'
pull_request:
branches:
- '*'
paths:
- '**/*.swift'
- 'Package.swift'
- 'Package.resolved'
- '.github/workflows/test.yml'

jobs:
macos:
name: macOS
runs-on: macos-latest

steps:
- uses: actions/checkout@v4

- name: Swift version
run: swift --version

- name: Build
run: swift build -v

- name: Run tests
run: swift test -v
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ let package = Package(
.target(
name: "GraphQLAPIKit",
dependencies: [
.product(name: "Apollo", package: "apollo-ios"),
.product(name: "Apollo", package: "apollo-ios")
]
),
.testTarget(
Expand Down
4 changes: 1 addition & 3 deletions Sources/GraphQLAPIKit/Errors/GraphQLAPIAdapterError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ public enum GraphQLAPIAdapterError: LocalizedError {
/// Errors returned by GraphQL API as part of `errors` field
case graphQl([GraphQLError])


init(error: Error) {
if let error = error as? GraphQLAPIAdapterError {
self = error
} else if let error = error as? ApolloError {
self = .graphQl(error.errors.map(GraphQLError.init))
} else if let error = error as? URLSessionClient.URLSessionClientError,
case let URLSessionClient.URLSessionClientError.networkError(_, response, underlyingError) = error
{
case let URLSessionClient.URLSessionClientError.networkError(_, response, underlyingError) = error {
if let response = response {
self = .network(code: response.statusCode, error: underlyingError)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Apollo
import ApolloAPI
import Foundation

// swiftlint:disable:next no_extension_access_modifier
public extension GraphQLAPIAdapterProtocol {
func fetch<Query: GraphQLQuery>(
query: Query,
Expand Down
4 changes: 3 additions & 1 deletion Sources/GraphQLAPIKit/GraphQLAPIAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ public protocol GraphQLAPIAdapterProtocol: AnyObject {
public final class GraphQLAPIAdapter: GraphQLAPIAdapterProtocol {
private let apollo: ApolloClientProtocol

// swiftlint:disable function_default_parameter_at_end
public init<each Observer: GraphQLNetworkObserver>(
url: URL,
urlSessionConfiguration: URLSessionConfiguration = .default,
defaultHeaders: [String: String] = [:],
networkObservers: repeat each Observer
) {
// swiftlint:enable function_default_parameter_at_end
var observers: [any GraphQLNetworkObserver] = []
repeat observers.append(each networkObservers)

Expand All @@ -68,7 +70,7 @@ public final class GraphQLAPIAdapter: GraphQLAPIAdapterProtocol {
url: URL,
urlSessionConfiguration: URLSessionConfiguration = .default,
defaultHeaders: [String: String] = [:],
networkObservers: [any GraphQLNetworkObserver]
networkObservers: [any GraphQLNetworkObserver] = []
) {
let provider = NetworkInterceptorProvider(
client: URLSessionClient(sessionConfiguration: urlSessionConfiguration),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct NetworkInterceptorProvider: InterceptorProvider {
func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
// Headers first, then before-observers, then network fetch, then after-observers
[
RequestHeaderInterceptor(defaultHeaders: defaultHeaders),
RequestHeaderInterceptor(defaultHeaders: defaultHeaders)
]
+ pairOfObserverInterceptors.map(\.before) // Before network - captures timing
+ [
Expand All @@ -35,8 +35,8 @@ struct NetworkInterceptorProvider: InterceptorProvider {
JSONResponseParsingInterceptor()
]
}
static private func makePair<T: GraphQLNetworkObserver>(of observer: T) -> (before: ApolloInterceptor, after: ApolloInterceptor) {

private static func makePair<T: GraphQLNetworkObserver>(of observer: T) -> (before: ApolloInterceptor, after: ApolloInterceptor) {
let contextStore = ObserverContextStore<T.Context>()
let beforeInterceptor = ObserverInterceptor(observer: observer, contextStore: contextStore)
let afterInterceptor = ObserverInterceptor(observer: observer, contextStore: contextStore)
Expand Down
4 changes: 3 additions & 1 deletion Tests/GraphQLAPIKitTests/GraphQLAPIAdapterErrorTests.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import XCTest
import Apollo
@testable import GraphQLAPIKit
import XCTest

final class GraphQLAPIAdapterErrorTests: XCTestCase {
func testGraphQLAPIAdapterErrorPassthrough() {
Expand Down Expand Up @@ -46,12 +46,14 @@ final class GraphQLAPIAdapterErrorTests: XCTestCase {
code: 500,
userInfo: [NSLocalizedDescriptionKey: "Server error"]
)
// swiftlint:disable force_unwrapping
let response = HTTPURLResponse(
url: URL(string: "https://example.com")!,
statusCode: 500,
httpVersion: nil,
headerFields: nil
)!
// swiftlint:enable force_unwrapping
let urlSessionError = URLSessionClient.URLSessionClientError.networkError(
data: Data(),
response: response,
Expand Down
40 changes: 26 additions & 14 deletions Tests/GraphQLAPIKitTests/GraphQLAPIAdapterIntegrationTests.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Apollo
import ApolloAPI
import XCTest
@testable import GraphQLAPIKit
import XCTest

// MARK: - MockURLProtocol

Expand All @@ -22,11 +22,11 @@ final class MockURLProtocol: URLProtocol {
mockError = nil
}

override class func canInit(with request: URLRequest) -> Bool {
override static func canInit(with request: URLRequest) -> Bool {
true
}

override class func canonicalRequest(for request: URLRequest) -> URLRequest {
override static func canonicalRequest(for request: URLRequest) -> URLRequest {
request
}

Expand All @@ -44,12 +44,16 @@ final class MockURLProtocol: URLProtocol {
statusCode: 200
)

guard let url = request.url else {
return
}

let httpResponse = HTTPURLResponse(
url: request.url!,
url: url,
statusCode: response.statusCode,
httpVersion: "HTTP/1.1",
headerFields: ["Content-Type": "application/json"]
)!
)! // swiftlint:disable:this force_unwrapping

client?.urlProtocol(self, didReceive: httpResponse, cacheStoragePolicy: .notAllowed)
client?.urlProtocol(self, didLoad: response.data)
Expand All @@ -60,9 +64,9 @@ final class MockURLProtocol: URLProtocol {

/// A valid GraphQL response with minimal data
private var validGraphQLResponse: Data {
"""
Data("""
{"data": {"__typename": "Query"}}
""".data(using: .utf8)!
""".utf8)
}
}

Expand All @@ -72,7 +76,9 @@ enum MockSchema: SchemaMetadata {
static let configuration: any SchemaConfiguration.Type = MockSchemaConfiguration.self

static func objectType(forTypename typename: String) -> Object? {
if typename == "Query" { return MockQuery.Data.self.__parentType as? Object }
if typename == "Query" {
return MockQuery.Data.self.__parentType as? Object
}
return nil
}
}
Expand All @@ -94,6 +100,7 @@ final class MockQuery: GraphQLQuery {

init() {}

// swiftlint:disable nesting identifier_name
struct MockQueryData: RootSelectionSet {
typealias Schema = MockSchema

Expand All @@ -106,6 +113,7 @@ final class MockQuery: GraphQLQuery {
self.__data = _dataDict
}
}
// swiftlint:enable nesting identifier_name
}

// MARK: - Mock Request Headers
Expand Down Expand Up @@ -172,6 +180,7 @@ final class GraphQLAPIAdapterIntegrationTests: XCTestCase {
]

let adapter = GraphQLAPIAdapter(
// swiftlint:disable:next force_unwrapping
url: URL(string: "https://api.example.com/graphql")!,
urlSessionConfiguration: mockSessionConfiguration(),
defaultHeaders: defaultHeaders,
Expand Down Expand Up @@ -207,10 +216,10 @@ final class GraphQLAPIAdapterIntegrationTests: XCTestCase {
])

let adapter = GraphQLAPIAdapter(
// swiftlint:disable:next force_unwrapping
url: URL(string: "https://api.example.com/graphql")!,
urlSessionConfiguration: mockSessionConfiguration(),
defaultHeaders: [:],
networkObservers: observer
networkObservers: [observer]
)

_ = adapter.fetch(query: MockQuery(), context: contextHeaders, queue: .main) { _ in
Expand Down Expand Up @@ -246,6 +255,7 @@ final class GraphQLAPIAdapterIntegrationTests: XCTestCase {
])

let adapter = GraphQLAPIAdapter(
// swiftlint:disable:next force_unwrapping
url: URL(string: "https://api.example.com/graphql")!,
urlSessionConfiguration: mockSessionConfiguration(),
defaultHeaders: defaultHeaders,
Expand Down Expand Up @@ -282,10 +292,13 @@ final class GraphQLAPIAdapterIntegrationTests: XCTestCase {
let defaultHeaders = ["X-Shared-Header": "shared-value"]

let adapter = GraphQLAPIAdapter(
// swiftlint:disable:next force_unwrapping
url: URL(string: "https://api.example.com/graphql")!,
urlSessionConfiguration: mockSessionConfiguration(),
defaultHeaders: defaultHeaders,
networkObservers: observer1, observer2, observer3
networkObservers: observer1,
observer2,
observer3
)

_ = adapter.fetch(query: MockQuery(), context: nil, queue: .main) { _ in
Expand Down Expand Up @@ -319,10 +332,10 @@ final class GraphQLAPIAdapterIntegrationTests: XCTestCase {
let observer = IntegrationMockObserver()

let adapter = GraphQLAPIAdapter(
// swiftlint:disable:next force_unwrapping
url: URL(string: "https://api.example.com/graphql")!,
urlSessionConfiguration: mockSessionConfiguration(),
defaultHeaders: [:],
networkObservers: observer
networkObservers: [observer]
)

_ = adapter.fetch(query: MockQuery(), context: nil, queue: .main) { _ in
Expand All @@ -340,5 +353,4 @@ final class GraphQLAPIAdapterIntegrationTests: XCTestCase {
XCTAssertEqual(capturedRequest.value(forHTTPHeaderField: "X-APOLLO-OPERATION-NAME"), "MockQuery")
XCTAssertNotNil(capturedRequest.value(forHTTPHeaderField: "Content-Type"))
}

}
4 changes: 2 additions & 2 deletions Tests/GraphQLAPIKitTests/GraphQLAPIAdapterTests.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Apollo
import ApolloAPI
import XCTest
@testable import GraphQLAPIKit
import XCTest

final class GraphQLAPIAdapterTests: XCTestCase {
// swiftlint:disable:next force_unwrapping
let testURL = URL(string: "https://api.example.com/graphql")!

// MARK: - Initialization Tests
Expand Down Expand Up @@ -37,5 +38,4 @@ final class GraphQLAPIAdapterTests: XCTestCase {
)
XCTAssertNotNil(adapter)
}

}
2 changes: 1 addition & 1 deletion Tests/GraphQLAPIKitTests/GraphQLErrorTests.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import XCTest
import Apollo
@testable import GraphQLAPIKit
import XCTest

final class GraphQLErrorTests: XCTestCase {
func testGraphQLErrorWithMessageAndCode() {
Expand Down
Loading