diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 619319c..d56943c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,51 +12,216 @@ on:
- "Package.swift"
- "Source/**"
- "Tests/**"
+
jobs:
- SwiftLint:
- runs-on: ubuntu-latest
+ macOS:
+ name: ${{ matrix.name }}
+ runs-on: ${{ matrix.runsOn }}
+ env:
+ DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer"
+ timeout-minutes: 20
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - xcode: "Xcode_16.0"
+ runsOn: macOS-14
+ name: "macOS 14, Xcode 16.0, Swift 6.0"
+ - xcode: "Xcode_15.4"
+ runsOn: macOS-14
+ name: "macOS 14, Xcode 15.4, Swift 5.10"
+ - xcode: "Xcode_15.0"
+ runsOn: macos-13
+ name: "macOS 13, Xcode 15.0, Swift 5.9.0"
+ - xcode: "Xcode_14.3.1"
+ runsOn: macos-13
+ name: "macOS 13, Xcode 14.3.1, Swift 5.8.0"
+ steps:
+ - uses: actions/checkout@v4
+ - name: ${{ matrix.name }}
+ run: xcodebuild test -scheme "NetworkLayer" -destination "platform=macOS" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1
+ - name: Upload test coverage reports to Codecov
+ uses: space-code/oss-common-actions/.github/actions/upload_test_coverage_report@main
+ with:
+ scheme_name: NetworkLayer
+ filename: ${{ matrix.name }}
+ token: ${{ secrets.CODECOV_TOKEN }}
+
+ iOS:
+ name: ${{ matrix.name }}
+ runs-on: ${{ matrix.runsOn }}
+ env:
+ DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer"
+ timeout-minutes: 20
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - destination: "OS=18.1,name=iPhone 16 Pro"
+ name: "iOS 18.1"
+ xcode: "Xcode_16.1"
+ runsOn: macOS-14
+ - destination: "OS=18.0,name=iPhone 16 Pro"
+ name: "iOS 18.0"
+ xcode: "Xcode_16.0"
+ runsOn: macOS-14
+ - destination: "OS=17.5,name=iPhone 15 Pro"
+ name: "iOS 17.5"
+ xcode: "Xcode_15.4"
+ runsOn: macOS-14
+ - destination: "OS=17.0.1,name=iPhone 14 Pro"
+ name: "iOS 17.0.1"
+ xcode: "Xcode_15.0"
+ runsOn: macos-13
+ - destination: "OS=16.4,name=iPhone 14 Pro"
+ name: "iOS 16.4"
+ xcode: "Xcode_14.3.1"
+ runsOn: macos-13
+ steps:
+ - uses: actions/checkout@v4
+ - name: ${{ matrix.name }}
+ run: xcodebuild test -scheme "NetworkLayer" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1
+ - name: Upload test coverage reports to Codecov
+ uses: space-code/oss-common-actions/.github/actions/upload_test_coverage_report@main
+ with:
+ scheme_name: NetworkLayer
+ filename: ${{ matrix.name }}
+ token: ${{ secrets.CODECOV_TOKEN }}
+
+ tvOS:
+ name: ${{ matrix.name }}
+ runs-on: ${{ matrix.runsOn }}
+ env:
+ DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer"
+ timeout-minutes: 20
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - destination: "OS=18.1,name=Apple TV"
+ name: "tvOS 18.1"
+ xcode: "Xcode_16.1"
+ runsOn: macOS-14
+ - destination: "OS=18.0,name=Apple TV"
+ name: "tvOS 18.0"
+ xcode: "Xcode_16.0"
+ runsOn: macOS-14
+ - destination: "OS=17.5,name=Apple TV"
+ name: "tvOS 17.5"
+ xcode: "Xcode_15.4"
+ runsOn: macOS-14
+ - destination: "OS=17.0,name=Apple TV"
+ name: "tvOS 17.0"
+ xcode: "Xcode_15.0"
+ runsOn: macos-13
+ - destination: "OS=16.4,name=Apple TV"
+ name: "tvOS 16.4"
+ xcode: "Xcode_14.3.1"
+ runsOn: macos-13
steps:
- - uses: actions/checkout@v3
- - name: GitHub Action for SwiftLint
- uses: norio-nomura/action-swiftlint@3.2.1
+ - uses: actions/checkout@v4
+ - name: ${{ matrix.name }}
+ run: xcodebuild test -scheme "NetworkLayer" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1
+ - name: Upload test coverage report to Codecov
+ uses: space-code/oss-common-actions/.github/actions/upload_test_coverage_report@main
with:
- args: --strict
- env:
- DIFF_BASE: ${{ github.base_ref }}
- Latest:
- name: Test Latest (iOS, macOS, tvOS, watchOS)
- runs-on: macOS-12
+ scheme_name: NetworkLayer
+ filename: ${{ matrix.name }}
+ token: ${{ secrets.CODECOV_TOKEN }}
+
+ watchOS:
+ name: ${{ matrix.name }}
+ runs-on: ${{ matrix.runsOn }}
env:
- DEVELOPER_DIR: "/Applications/Xcode_14.1.app/Contents/Developer"
- timeout-minutes: 10
+ DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer"
+ timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- - destination: "OS=16.1,name=iPhone 14 Pro"
- name: "iOS"
- scheme: "NetworkLayer"
- sdk: iphonesimulator
- - destination: "OS=16.1,name=Apple TV"
- name: "tvOS"
- scheme: "NetworkLayer"
- sdk: appletvsimulator
- - destination: "OS=9.1,name=Apple Watch Series 8 (45mm)"
- name: "watchOS"
- scheme: "NetworkLayer"
- sdk: watchsimulator
- - destination: "platform=macOS"
- name: "macOS"
- scheme: "NetworkLayer"
- sdk: macosx
+ - destination: "OS=11.1,name=Apple Watch Series 10 (46mm)"
+ name: "watchOS 11.1"
+ xcode: "Xcode_16.1"
+ runsOn: macOS-14
+ - destination: "OS=11.0,name=Apple Watch Series 10 (46mm)"
+ name: "watchOS 11.0"
+ xcode: "Xcode_16.0"
+ runsOn: macOS-14
+ - destination: "OS=10.5,name=Apple Watch Series 9 (45mm)"
+ name: "watchOS 10.5"
+ xcode: "Xcode_15.4"
+ runsOn: macOS-14
+ - destination: "OS=10.0,name=Apple Watch Series 9 (45mm)"
+ name: "watchOS 10.0"
+ xcode: "Xcode_15.0"
+ runsOn: macos-13
+ - destination: "OS=9.4,name=Apple Watch Series 8 (45mm)"
+ name: "watchOS 9.4"
+ xcode: "Xcode_14.3.1"
+ runsOn: macos-13
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: ${{ matrix.name }}
- run: xcodebuild test -scheme "${{ matrix.scheme }}" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "./${{ matrix.sdk }}.xcresult"
- - name: Upload coverage reports to Codecov
- uses: codecov/codecov-action@v3.1.0
+ run: xcodebuild test -scheme "NetworkLayer" -destination "${{ matrix.destination }}" clean -enableCodeCoverage YES -resultBundlePath "test_output/${{ matrix.name }}.xcresult" || exit 1
+ - name: Upload test coverage reports to Codecov
+ uses: space-code/oss-common-actions/.github/actions/upload_test_coverage_report@main
with:
+ scheme_name: NetworkLayer
+ filename: ${{ matrix.name }}
token: ${{ secrets.CODECOV_TOKEN }}
- xcode: true
- xcode_archive_path: "./${{ matrix.sdk }}.xcresult"
-
\ No newline at end of file
+
+ spm:
+ name: ${{ matrix.name }}
+ runs-on: ${{ matrix.runsOn }}
+ env:
+ DEVELOPER_DIR: "/Applications/${{ matrix.xcode }}.app/Contents/Developer"
+ timeout-minutes: 20
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: "macOS 14, SPM 6.0.2 Test"
+ xcode: "Xcode_16.1"
+ runsOn: macOS-14
+ - name: "macOS 14, SPM 6.0.0 Test"
+ xcode: "Xcode_16.0"
+ runsOn: macOS-14
+ - name: "macOS 14, SPM 5.9.0 Test"
+ xcode: "Xcode_15.0"
+ runsOn: macos-14
+ - name: "macOS 13, SPM 5.8.1 Test"
+ xcode: "Xcode_14.3.1"
+ runsOn: macos-13
+ steps:
+ - uses: actions/checkout@v4
+ - name: ${{ matrix.name }}
+ run: swift build -c release --target NetworkLayer
+
+ merge-test-reports:
+ needs: [iOS, macOS, watchOS, tvOS]
+ runs-on: macos-13
+ steps:
+ - name: Download artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: test_output
+ - run: xcrun xcresulttool merge test_output/**/*.xcresult --output-path test_output/final/final.xcresult
+ - name: Upload Merged Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: MergedResult
+ path: test_output/final
+
+ discover-typos:
+ name: Discover Typos
+ runs-on: macOS-13
+ env:
+ DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer
+ steps:
+ - uses: actions/checkout@v4
+ - name: Discover typos
+ run: |
+ export PATH="$PATH:/Library/Frameworks/Python.framework/Versions/3.11/bin"
+ python3 -m pip install --upgrade pip
+ python3 -m pip install codespell
+ codespell --ignore-words-list="hart,inout,msdos,sur" --skip="./.build/*,./.git/*"
diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml
index e6c6e9a..3ba7736 100644
--- a/.github/workflows/danger.yml
+++ b/.github/workflows/danger.yml
@@ -15,7 +15,7 @@ jobs:
- name: ruby setup
uses: ruby/setup-ruby@v1
with:
- ruby-version: 2.7
+ ruby-version: 3.1.4
bundler-cache: true
- name: Checkout code
uses: actions/checkout@v2
@@ -28,4 +28,4 @@ jobs:
DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
- run: bundle exec danger --verbose
\ No newline at end of file
+ run: bundle exec danger --verbose
diff --git a/.gitignore b/.gitignore
index 3b29812..5922fda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
+Package.resolved
diff --git a/.swiftlint.yml b/.swiftlint.yml
index 297f875..ccb6b1f 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -2,6 +2,9 @@ excluded:
- Tests
- Package.swift
- Package@swift-5.7.swift
+ - Package@swift-5.8.swift
+ - Package@swift-5.9.swift
+ - Package@swift-5.10.swift
- .build
# Rules
@@ -130,4 +133,4 @@ nesting:
type_name:
max_length:
warning: 40
- error: 50
\ No newline at end of file
+ error: 50
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86c4648..79cae31 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,8 +2,22 @@
All notable changes to this project will be documented in this file.
#### 1.x Releases
+- `1.1.x` Release Candidates - [1.1.0-rc.1](#110-rc1)
- `1.0.x` Releases - [1.0.0](#100)
+## [1.1.0-rc.1](https://github.com/space-code/network-layer/releases/tag/1.1.0-rc.1)
+Released on 2024-12-25.
+
+#### Added
+- Bump the Swift version to 6.0.
+ - Added in Pull Request [#3](https://github.com/space-code/network-layer/pull/3).
+
+#### Fixed
+- Fix the `inout` parameter in the `IAuthenticator` protocol
+ - Fixed in Pull Request [#2](https://github.com/space-code/network-layer/pull/2).
+- Fix the package builiding.
+ - Fixed in Pull Request [#6](https://github.com/space-code/network-layer/pull-6).
+
## [1.0.0](https://github.com/space-code/network-layer/releases/tag/1.0.0)
Released on 2023-12-04.
diff --git a/Package.resolved b/Package.resolved
deleted file mode 100644
index 418af9a..0000000
--- a/Package.resolved
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "pins" : [
- {
- "identity" : "atomic",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/space-code/atomic",
- "state" : {
- "revision" : "53fae2fc8216bb5c27c87b245f893176d0d290eb",
- "version" : "1.0.0"
- }
- },
- {
- "identity" : "mocker",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/WeTransfer/Mocker",
- "state" : {
- "revision" : "4384e015cae4916a6828252467a4437173c7ae17",
- "version" : "3.0.1"
- }
- },
- {
- "identity" : "typhoon",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/space-code/typhoon",
- "state" : {
- "revision" : "c0e2970812f4ec837fc61afd72a7ca1f0aa39306",
- "version" : "1.0.0"
- }
- }
- ],
- "version" : 2
-}
diff --git a/Package.swift b/Package.swift
index c9f72ca..382a9fb 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version: 5.9
+// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
@@ -17,9 +17,9 @@ let package = Package(
.library(name: "NetworkLayerInterfaces", targets: ["NetworkLayerInterfaces"]),
],
dependencies: [
- .package(url: "https://github.com/space-code/atomic", .upToNextMajor(from: "1.0.0")),
- .package(url: "https://github.com/space-code/typhoon", .upToNextMajor(from: "1.0.0")),
- .package(url: "https://github.com/WeTransfer/Mocker", .upToNextMajor(from: "3.0.1")),
+ .package(url: "https://github.com/space-code/atomic", exact: "1.1.0"),
+ .package(url: "https://github.com/space-code/typhoon", exact: "1.2.1"),
+ .package(url: "https://github.com/WeTransfer/Mocker", exact: "3.0.1"),
],
targets: [
.target(
diff --git a/Package@swift-5.10.swift b/Package@swift-5.10.swift
new file mode 100644
index 0000000..5c251ce
--- /dev/null
+++ b/Package@swift-5.10.swift
@@ -0,0 +1,51 @@
+// swift-tools-version: 5.10
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "NetworkLayer",
+ platforms: [
+ .macOS(.v10_15),
+ .iOS(.v13),
+ .watchOS(.v7),
+ .tvOS(.v13),
+ .visionOS(.v1),
+ ],
+ products: [
+ .library(name: "NetworkLayer", targets: ["NetworkLayer"]),
+ .library(name: "NetworkLayerInterfaces", targets: ["NetworkLayerInterfaces"]),
+ ],
+ dependencies: [
+ .package(url: "https://github.com/space-code/atomic", exact: "1.1.0"),
+ .package(url: "https://github.com/space-code/typhoon", exact: "1.2.1"),
+ .package(url: "https://github.com/WeTransfer/Mocker", exact: "3.0.1"),
+ ],
+ targets: [
+ .target(
+ name: "NetworkLayer",
+ dependencies: [
+ "NetworkLayerInterfaces",
+ .product(name: "Atomic", package: "atomic"),
+ .product(name: "Typhoon", package: "typhoon"),
+ ]
+ ),
+ .target(
+ name: "NetworkLayerInterfaces",
+ dependencies: [
+ .product(name: "Typhoon", package: "typhoon"),
+ ]
+ ),
+ .testTarget(
+ name: "NetworkLayerTests",
+ dependencies: [
+ "NetworkLayer",
+ .product(name: "Mocker", package: "Mocker"),
+ .product(name: "Typhoon", package: "typhoon"),
+ ],
+ resources: [
+ .process("Resources"),
+ ]
+ ),
+ ]
+)
diff --git a/Package@swift-5.7.swift b/Package@swift-5.7.swift
index 0a132cd..f462754 100644
--- a/Package@swift-5.7.swift
+++ b/Package@swift-5.7.swift
@@ -16,9 +16,9 @@ let package = Package(
.library(name: "NetworkLayerInterfaces", targets: ["NetworkLayerInterfaces"]),
],
dependencies: [
- .package(url: "https://github.com/space-code/atomic", .upToNextMajor(from: "1.0.0")),
- .package(url: "https://github.com/space-code/typhoon", .upToNextMajor(from: "1.0.0")),
- .package(url: "https://github.com/WeTransfer/Mocker", .upToNextMajor(from: "3.0.1")),
+ .package(url: "https://github.com/space-code/atomic", exact: "1.1.0"),
+ .package(url: "https://github.com/space-code/typhoon", exact: "1.2.1"),
+ .package(url: "https://github.com/WeTransfer/Mocker", exact: "3.0.1"),
],
targets: [
.target(
diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift
new file mode 100644
index 0000000..a0ad70b
--- /dev/null
+++ b/Package@swift-5.8.swift
@@ -0,0 +1,50 @@
+// swift-tools-version: 5.8
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "NetworkLayer",
+ platforms: [
+ .macOS(.v10_15),
+ .iOS(.v13),
+ .watchOS(.v7),
+ .tvOS(.v13),
+ ],
+ products: [
+ .library(name: "NetworkLayer", targets: ["NetworkLayer"]),
+ .library(name: "NetworkLayerInterfaces", targets: ["NetworkLayerInterfaces"]),
+ ],
+ dependencies: [
+ .package(url: "https://github.com/space-code/atomic", exact: "1.1.0"),
+ .package(url: "https://github.com/space-code/typhoon", exact: "1.2.1"),
+ .package(url: "https://github.com/WeTransfer/Mocker", exact: "3.0.1"),
+ ],
+ targets: [
+ .target(
+ name: "NetworkLayer",
+ dependencies: [
+ "NetworkLayerInterfaces",
+ .product(name: "Atomic", package: "atomic"),
+ .product(name: "Typhoon", package: "typhoon"),
+ ]
+ ),
+ .target(
+ name: "NetworkLayerInterfaces",
+ dependencies: [
+ .product(name: "Typhoon", package: "typhoon"),
+ ]
+ ),
+ .testTarget(
+ name: "NetworkLayerTests",
+ dependencies: [
+ "NetworkLayer",
+ .product(name: "Mocker", package: "Mocker"),
+ .product(name: "Typhoon", package: "typhoon"),
+ ],
+ resources: [
+ .process("Resources"),
+ ]
+ ),
+ ]
+)
diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift
new file mode 100644
index 0000000..43d2dc8
--- /dev/null
+++ b/Package@swift-5.9.swift
@@ -0,0 +1,51 @@
+// swift-tools-version: 5.9
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "NetworkLayer",
+ platforms: [
+ .macOS(.v10_15),
+ .iOS(.v13),
+ .watchOS(.v7),
+ .tvOS(.v13),
+ .visionOS(.v1),
+ ],
+ products: [
+ .library(name: "NetworkLayer", targets: ["NetworkLayer"]),
+ .library(name: "NetworkLayerInterfaces", targets: ["NetworkLayerInterfaces"]),
+ ],
+ dependencies: [
+ .package(url: "https://github.com/space-code/atomic", exact: "1.1.0"),
+ .package(url: "https://github.com/space-code/typhoon", exact: "1.2.1"),
+ .package(url: "https://github.com/WeTransfer/Mocker", exact: "3.0.1"),
+ ],
+ targets: [
+ .target(
+ name: "NetworkLayer",
+ dependencies: [
+ "NetworkLayerInterfaces",
+ .product(name: "Atomic", package: "atomic"),
+ .product(name: "Typhoon", package: "typhoon"),
+ ]
+ ),
+ .target(
+ name: "NetworkLayerInterfaces",
+ dependencies: [
+ .product(name: "Typhoon", package: "typhoon"),
+ ]
+ ),
+ .testTarget(
+ name: "NetworkLayerTests",
+ dependencies: [
+ "NetworkLayer",
+ .product(name: "Mocker", package: "Mocker"),
+ .product(name: "Typhoon", package: "typhoon"),
+ ],
+ resources: [
+ .process("Resources"),
+ ]
+ ),
+ ]
+)
diff --git a/README.md b/README.md
index 6c45a18..ca6b8fa 100644
--- a/README.md
+++ b/README.md
@@ -4,8 +4,8 @@
-
-
+
+
diff --git a/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift b/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift
index b017286..e06a944 100644
--- a/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift
+++ b/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2023 Space Code. All rights reserved.
+// Copyright © 2024 Space Code. All rights reserved.
//
import Atomic
@@ -9,7 +9,7 @@ import NetworkLayerInterfaces
/// A custom AuthenticationInterceptor implementation that works with a specific type
/// of Authenticator conforming to the IAuthenticator protocol.
-public final class AuthenticationInterceptor: IAuthenticationInterceptor {
+public final class AuthenticationInterceptor: IAuthenticationInterceptor, @unchecked Sendable {
// MARK: Types
public typealias Credential = Authenticator.Credential
@@ -46,7 +46,7 @@ public final class AuthenticationInterceptor: IAu
if credential.requiresRefresh {
try await refresh(credential, for: session)
} else {
- try await authenticator.apply(credential, to: request)
+ try await authenticator.apply(credential, to: &request)
}
}
diff --git a/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBodyEncoder/RequestBodyEncoder.swift b/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBodyEncoder/RequestBodyEncoder.swift
index db481d4..59d70ca 100644
--- a/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBodyEncoder/RequestBodyEncoder.swift
+++ b/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBodyEncoder/RequestBodyEncoder.swift
@@ -25,7 +25,7 @@ struct RequestBodyEncoder: IRequestBodyEncoder {
request.httpBody = data
case let .encodable(encodable):
request.httpBody = try jsonEncoder.encode(encodable)
- case let .dictonary(dictionary):
+ case let .dictionary(dictionary):
request.httpBody = try JSONSerialization.data(withJSONObject: dictionary)
}
}
diff --git a/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBuilder.swift b/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBuilder.swift
index 48f581f..09fe07e 100644
--- a/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBuilder.swift
+++ b/Sources/NetworkLayer/Classes/Core/Builders/RequestBuilder/RequestBuilder.swift
@@ -6,7 +6,7 @@
import Foundation
import NetworkLayerInterfaces
-final class RequestBuilder: IRequestBuilder {
+final class RequestBuilder: IRequestBuilder, @unchecked Sendable {
// MARK: Properties
private let parametersEncoder: IRequestParametersEncoder
diff --git a/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift b/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift
index 64f3400..b6fe0b9 100644
--- a/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift
+++ b/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2023 Space Code. All rights reserved.
+// Copyright © 2024 Space Code. All rights reserved.
//
import Atomic
@@ -10,13 +10,13 @@ import NetworkLayerInterfaces
// MARK: - DataRequestHandler
/// Manages data request handlers for URLSessionTasks.
-final class DataRequestHandler: NSObject {
+final class DataRequestHandler: NSObject, @unchecked Sendable {
// MARK: Properties
- private typealias HandlerDictonary = [URLSessionTask: DataTaskHandler]
+ private typealias HandlerDictionary = [URLSessionTask: DataTaskHandler]
- /// The dictonary that stores handlers.
- @Atomic private var handlers: HandlerDictonary = [:]
+ /// The dictionary that stores handlers.
+ @Atomic private var handlers: HandlerDictionary = [:]
/// A protocol that defines methods that URL session instances call on their
/// delegates to handle task-level events specific to data and upload tasks.
private var userDataDelegate: URLSessionDataDelegate?
@@ -40,7 +40,7 @@ extension DataRequestHandler: IDataRequestHandler {
try await withTaskCancellationHandler(operation: {
try await withUnsafeThrowingContinuation { continuation in
let dataTaskHandler = DataTaskHandler(delegate: delegate)
- dataTaskHandler.completion = continuation.resume(with:)
+ dataTaskHandler.completion = { continuation.resume(with: $0) }
handlers[task] = dataTaskHandler
task.resume()
}
@@ -71,15 +71,14 @@ extension DataRequestHandler {
_ session: URLSession,
dataTask: URLSessionDataTask,
willCacheResponse proposedResponse: CachedURLResponse,
- completionHandler: @escaping (CachedURLResponse?) -> Void
+ completionHandler: @escaping @Sendable (CachedURLResponse?) -> Void
) {
userDataDelegate?.urlSession?(
session,
dataTask: dataTask,
willCacheResponse: proposedResponse,
completionHandler: completionHandler
- )
- completionHandler(proposedResponse)
+ ) ?? completionHandler(proposedResponse)
}
}
@@ -114,7 +113,7 @@ extension DataRequestHandler {
task: URLSessionTask,
willPerformHTTPRedirection response: HTTPURLResponse,
newRequest request: URLRequest,
- completionHandler: @escaping (URLRequest?) -> Void
+ completionHandler: @escaping @Sendable (URLRequest?) -> Void
) {
userDataDelegate?.urlSession?(
session,
@@ -122,8 +121,7 @@ extension DataRequestHandler {
willPerformHTTPRedirection: response,
newRequest: request,
completionHandler: completionHandler
- )
- completionHandler(request)
+ ) ?? completionHandler(request)
}
func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
@@ -133,9 +131,13 @@ extension DataRequestHandler {
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
- completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
+ completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
- userDataDelegate?.urlSession?(session, didReceive: challenge, completionHandler: completionHandler)
+ userDataDelegate?.urlSession?(
+ session,
+ didReceive: challenge,
+ completionHandler: completionHandler
+ )
completionHandler(.performDefaultHandling, nil)
}
@@ -143,9 +145,14 @@ extension DataRequestHandler {
_ session: URLSession,
task: URLSessionTask,
willBeginDelayedRequest request: URLRequest,
- completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void
+ completionHandler: @escaping @Sendable (URLSession.DelayedRequestDisposition, URLRequest?) -> Void
) {
- userDataDelegate?.urlSession?(session, task: task, willBeginDelayedRequest: request, completionHandler: completionHandler)
+ userDataDelegate?.urlSession?(
+ session,
+ task: task,
+ willBeginDelayedRequest: request,
+ completionHandler: completionHandler
+ )
completionHandler(.continueLoading, nil)
}
diff --git a/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/Models/SafeRequestProcessorDelegate.swift b/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/Models/SafeRequestProcessorDelegate.swift
new file mode 100644
index 0000000..bd0a1f2
--- /dev/null
+++ b/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/Models/SafeRequestProcessorDelegate.swift
@@ -0,0 +1,19 @@
+//
+// network-layer
+// Copyright © 2024 Space Code. All rights reserved.
+//
+
+import NetworkLayerInterfaces
+
+final class SafeRequestProcessorDelegate: @unchecked Sendable {
+ private weak var delegate: RequestProcessorDelegate?
+
+ init(delegate: RequestProcessorDelegate? = nil) {
+ self.delegate = delegate
+ }
+
+ var wrappedValue: RequestProcessorDelegate? {
+ get { delegate }
+ set { delegate = newValue }
+ }
+}
diff --git a/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift b/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift
index 8754162..1375262 100644
--- a/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift
+++ b/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift
@@ -26,7 +26,7 @@ actor RequestProcessor {
/// The authenticator interceptor.
private let interceptor: IAuthenticationInterceptor?
/// The delegate.
- private weak var delegate: RequestProcessorDelegate?
+ private var delegate: SafeRequestProcessorDelegate?
// MARK: Initialization
@@ -42,7 +42,7 @@ actor RequestProcessor {
requestBuilder: IRequestBuilder,
dataRequestHandler: any IDataRequestHandler,
retryPolicyService: IRetryPolicyService,
- delegate: RequestProcessorDelegate?,
+ delegate: SafeRequestProcessorDelegate?,
interceptor: IAuthenticationInterceptor?
) {
self.configuration = configuration
@@ -83,8 +83,8 @@ actor RequestProcessor {
try await adapt(request, urlRequest: &urlRequest, session: session)
- return try await performRequest(strategy: strategy) {
- try await self.delegate?.requestProcessor(self, willSendRequest: urlRequest)
+ return try await performRequest(strategy: strategy) { [urlRequest] in
+ try await self.delegate?.wrappedValue?.requestProcessor(self, willSendRequest: urlRequest)
let task = session.dataTask(with: urlRequest)
@@ -103,7 +103,7 @@ actor RequestProcessor {
}
}
- try self.validate(response)
+ try await self.validate(response)
return response
} catch {
@@ -153,9 +153,9 @@ actor RequestProcessor {
/// - send: The closure that sends the request.
///
/// - Returns: The response from the network request.
- private func performRequest(
+ private func performRequest(
strategy: RetryPolicyStrategy? = nil,
- _ send: () async throws -> T
+ _ send: @Sendable () async throws -> T
) async throws -> T {
do {
return try await send()
@@ -166,18 +166,23 @@ actor RequestProcessor {
private func validate(_ response: Response) throws {
guard let urlResponse = response.response as? HTTPURLResponse else { return }
- try delegate?.requestProcessor(self, validateResponse: urlResponse, data: response.data, task: response.task)
+ try delegate?.wrappedValue?.requestProcessor(
+ self,
+ validateResponse: urlResponse,
+ data: response.data,
+ task: response.task
+ )
}
}
// MARK: IRequestProcessor
extension RequestProcessor: IRequestProcessor {
- func send(
+ func send(
_ request: T,
strategy: RetryPolicyStrategy? = nil,
delegate: URLSessionDelegate? = nil,
- configure: ((inout URLRequest) throws -> Void)? = nil
+ configure: (@Sendable (inout URLRequest) throws -> Void)? = nil
) async throws -> Response {
let response = try await performRequest(request, strategy: strategy, delegate: delegate, configure: configure)
return try response.map { data in try self.configuration.jsonDecoder.decode(M.self, from: data) }
diff --git a/Sources/NetworkLayer/Classes/DI/NetworkLayerAssembly.swift b/Sources/NetworkLayer/Classes/DI/NetworkLayerAssembly.swift
index 18e0bc2..00b5d39 100644
--- a/Sources/NetworkLayer/Classes/DI/NetworkLayerAssembly.swift
+++ b/Sources/NetworkLayer/Classes/DI/NetworkLayerAssembly.swift
@@ -15,7 +15,7 @@ public final class NetworkLayerAssembly: INetworkLayerAssembly {
/// The retry policy service.
private let retryPolicyStrategy: RetryPolicyStrategy?
/// The request processor delegate.
- private let delegate: RequestProcessorDelegate?
+ private var delegate: SafeRequestProcessorDelegate?
/// The authenticator interceptor.
private let interceptor: IAuthenticationInterceptor?
/// The json encoder.
@@ -37,7 +37,7 @@ public final class NetworkLayerAssembly: INetworkLayerAssembly {
) {
self.configure = configure
self.retryPolicyStrategy = retryPolicyStrategy
- self.delegate = delegate
+ self.delegate = SafeRequestProcessorDelegate(delegate: delegate)
self.interceptor = interceptor
self.jsonEncoder = jsonEncoder
}
diff --git a/Sources/NetworkLayer/NetworkLayer.docc/Articles/Authentication.md b/Sources/NetworkLayer/NetworkLayer.docc/Articles/Authentication.md
index c44f16c..ce2dc46 100644
--- a/Sources/NetworkLayer/NetworkLayer.docc/Articles/Authentication.md
+++ b/Sources/NetworkLayer/NetworkLayer.docc/Articles/Authentication.md
@@ -34,8 +34,8 @@ struct Authenticator: IAuthenticator {
/// - Parameters:
/// - credential: The `Credential`.
/// - urlRequest: The `URLRequest`.
- func apply(_ credential: Credential, to urlRequest: URLRequest) async throws {
- request.addValue("Bearer ", forHTTPHeaderField: "Authorization")
+ func apply(_ credential: Credential, to urlRequest: inout URLRequest) async throws {
+ urlRequest.addValue("Bearer ", forHTTPHeaderField: "Authorization")
}
/// Refreshes the `Credential`.
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationCredential.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationCredential.swift
index 192e55c..6911bbc 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationCredential.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationCredential.swift
@@ -6,7 +6,7 @@
import Foundation
/// A type defines an authentication credential interface.
-public protocol IAuthenticationCredential {
+public protocol IAuthenticationCredential: Sendable {
/// Determines whether the authentication credential requires a refresh.
var requiresRefresh: Bool { get }
}
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationInterceptor.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationInterceptor.swift
index 1ac679b..159d7be 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationInterceptor.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticationInterceptor.swift
@@ -6,7 +6,7 @@
import Foundation
/// A type defines the authenticator interceptor interface.
-public protocol IAuthenticationInterceptor {
+public protocol IAuthenticationInterceptor: Sendable {
/// Adapts the request with credentials.
///
/// - Parameters:
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift
index a67cd64..33f6f0b 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift
@@ -1,12 +1,12 @@
//
// network-layer
-// Copyright © 2023 Space Code. All rights reserved.
+// Copyright © 2024 Space Code. All rights reserved.
//
import Foundation
/// A protocol defining the interface for an authenticator type.
-public protocol IAuthenticator {
+public protocol IAuthenticator: Sendable {
associatedtype Credential: IAuthenticationCredential
/// Applies the `Credential` to the `URLRequest`.
@@ -14,7 +14,7 @@ public protocol IAuthenticator {
/// - Parameters:
/// - credential: The `Credential`.
/// - urlRequest: The `URLRequest`.
- func apply(_ credential: Credential, to urlRequest: URLRequest) async throws
+ func apply(_ credential: Credential, to urlRequest: inout URLRequest) async throws
/// Refreshes the `Credential`.
///
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Models/Configuration.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Models/Configuration.swift
index 1d929ac..f8a27e4 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Models/Configuration.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Models/Configuration.swift
@@ -6,7 +6,7 @@
import Foundation
/// A type that represents a configuration for the network layer.
-public struct Configuration {
+public struct Configuration: @unchecked Sendable {
// MARK: Properties
/// A configuration object that defines behavior and policies for a URL session.
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift
index 91caaae..a109d00 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2023 Space Code. All rights reserved.
+// Copyright © 2024 Space Code. All rights reserved.
//
import Foundation
@@ -8,7 +8,7 @@ import Foundation
// MARK: - IRequest
/// A type to which all requests must conform.
-public protocol IRequest {
+public protocol IRequest: Sendable {
/// The base `URL` for the resource.
var domainName: String { get }
@@ -30,7 +30,7 @@ public protocol IRequest {
/// The HTTP method.
var httpMethod: HTTPMethod { get }
- /// A dictonary that contains the request's body.
+ /// A dictionary that contains the request's body.
var httpBody: RequestBody? { get }
/// An alias for the cache policy.
@@ -58,7 +58,7 @@ public extension IRequest {
60
}
- /// A dictonary that contains the request's body.
+ /// A dictionary that contains the request's body.
var httpBody: RequestBody? {
nil
}
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Models/RequestBody.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Models/RequestBody.swift
index f884d5c..3fbd4b9 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Models/RequestBody.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Models/RequestBody.swift
@@ -8,5 +8,5 @@ import Foundation
public enum RequestBody {
case data(Data)
case encodable(Encodable)
- case dictonary([String: Any])
+ case dictionary([String: Any])
}
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift
index 1eaeba7..d7b49aa 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift
@@ -5,6 +5,8 @@
import Foundation
+// MARK: - Response
+
/// A generic struct representing an HTTP response.
public struct Response {
/// The data associated with the response.
@@ -32,3 +34,7 @@ public struct Response {
self.task = task
}
}
+
+// MARK: Sendable
+
+extension Response: @unchecked Sendable where T: Sendable {}
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift
index f47e8bf..dc3fb74 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift
@@ -6,7 +6,7 @@
import Foundation
/// A type that creates a `URLRequest`.
-public protocol IRequestBuilder {
+public protocol IRequestBuilder: Sendable {
/// Creates a new `URLRequest` using `IRequest.`
///
/// - Parameter request: The request object that defines the request details.
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift
index c3a6561..1800e40 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift
@@ -22,7 +22,7 @@ public protocol IRequestProcessor {
_ request: T,
strategy: RetryPolicyStrategy?,
delegate: URLSessionDelegate?,
- configure: ((inout URLRequest) throws -> Void)?
+ configure: (@Sendable (inout URLRequest) throws -> Void)?
) async throws -> Response
}
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Helpers/RequestProcessor+Mock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Helpers/RequestProcessor+Mock.swift
index 5385dae..39a82d0 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Helpers/RequestProcessor+Mock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Helpers/RequestProcessor+Mock.swift
@@ -27,7 +27,7 @@ extension RequestProcessor {
),
dataRequestHandler: DataRequestHandler(),
retryPolicyService: RetryPolicyService(strategy: .constant(retry: 1, duration: .seconds(0))),
- delegate: requestProcessorDelegate,
+ delegate: SafeRequestProcessorDelegate(delegate: requestProcessorDelegate),
interceptor: interceptor
)
}
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift
index 4b1d42b..d01a119 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift
@@ -1,12 +1,12 @@
//
// network-layer
-// Copyright © 2023 Space Code. All rights reserved.
+// Copyright © 2024 Space Code. All rights reserved.
//
import Foundation
import NetworkLayerInterfaces
-final class AuthenticatorMock: IAuthenticator {
+final class AuthenticatorMock: IAuthenticator, @unchecked Sendable {
typealias Credential = AuthenticationCredentialStub
var invokedApply = false
@@ -14,7 +14,7 @@ final class AuthenticatorMock: IAuthenticator {
var invokedApplyParameters: (credential: Credential, urlRequest: URLRequest)?
var invokedApplyParametersList = [(credential: Credential, urlRequest: URLRequest)]()
- func apply(_ credential: Credential, to urlRequest: URLRequest) async throws {
+ func apply(_ credential: Credential, to urlRequest: inout URLRequest) async throws {
invokedApply = true
invokedApplyCount += 1
invokedApplyParameters = (credential, urlRequest)
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthentificatorInterceptorMock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthentificatorInterceptorMock.swift
index 4313e21..7c7e051 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthentificatorInterceptorMock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthentificatorInterceptorMock.swift
@@ -6,7 +6,7 @@
import Foundation
import NetworkLayerInterfaces
-final class AuthentificatorInterceptorMock: IAuthenticationInterceptor {
+final class AuthentificatorInterceptorMock: IAuthenticationInterceptor, @unchecked Sendable {
var invokedAdapt = false
var invokedAdaptCount = 0
var invokedAdaptParameters: (request: URLRequest, session: URLSession)?
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/DataRequestHandlerMock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/DataRequestHandlerMock.swift
index 8889a5c..3b662b1 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/DataRequestHandlerMock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/DataRequestHandlerMock.swift
@@ -6,7 +6,7 @@
import Foundation
import NetworkLayerInterfaces
-final class DataRequestHandlerMock: NSObject, IDataRequestHandler {
+final class DataRequestHandlerMock: NSObject, IDataRequestHandler, @unchecked Sendable {
var invokedUrlSessionGetDelegate = false
var invokedUrlSessionGetDelegateCount = 0
var invokedUrlSessionSetDelegate = false
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestBuilderMock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestBuilderMock.swift
index bb845c2..ecfa24a 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestBuilderMock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestBuilderMock.swift
@@ -6,7 +6,7 @@
import Foundation
import NetworkLayerInterfaces
-final class RequestBuilderMock: IRequestBuilder {
+final class RequestBuilderMock: IRequestBuilder, @unchecked Sendable {
var invokedBuild = false
var invokedBuildCount = 0
var invokedBuildParameters: (request: IRequest, Void)?
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestMock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestMock.swift
index 36cc932..e37ede1 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestMock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/RequestMock.swift
@@ -6,7 +6,7 @@
import Foundation
import NetworkLayerInterfaces
-final class RequestMock: IRequest {
+final class RequestMock: IRequest, @unchecked Sendable {
var invokedDomainNameGetter = false
var invokedDomainNameGetterCount = 0
var stubbedDomainName: String! = ""
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/URLSessionDelegateMock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/URLSessionDelegateMock.swift
index 98e2694..ae06122 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/URLSessionDelegateMock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/URLSessionDelegateMock.swift
@@ -5,7 +5,7 @@
import Foundation
-final class URLSessionDelegateMock: NSObject, URLSessionDataDelegate {
+final class URLSessionDelegateMock: NSObject, URLSessionDataDelegate, @unchecked Sendable {
var invokedUrlSessionDidBecomeInvalidWithError = false
var invokedUrlSessionDidBecomeInvalidWithErrorCount = 0
var invokedUrlSessionDidBecomeInvalidWithErrorParameters: (session: URLSession, error: Error?)?
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Stubs/AuthenticationCredentialStub.swift b/Tests/NetworkLayerTests/Classes/Helpers/Stubs/AuthenticationCredentialStub.swift
index 9e9b4f3..8e09656 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Stubs/AuthenticationCredentialStub.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Stubs/AuthenticationCredentialStub.swift
@@ -6,7 +6,7 @@
import Foundation
import NetworkLayerInterfaces
-final class AuthenticationCredentialStub: IAuthenticationCredential {
+final class AuthenticationCredentialStub: IAuthenticationCredential, @unchecked Sendable {
var stubbedRequiresRefresh: Bool! = false
var requiresRefresh: Bool {
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Stubs/RequestStub.swift b/Tests/NetworkLayerTests/Classes/Helpers/Stubs/RequestStub.swift
index 148c675..fb1678f 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Stubs/RequestStub.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Stubs/RequestStub.swift
@@ -6,7 +6,7 @@
import Foundation
import NetworkLayerInterfaces
-final class RequestStub: IRequest {
+final class RequestStub: IRequest, @unchecked Sendable {
var stubbedDomainName: String! = ""
var domainName: String {
@@ -49,7 +49,7 @@ final class RequestStub: IRequest {
stubbedHttpMethod
}
- var stubbedHttpBody: RequestBody? = nil
+ var stubbedHttpBody: RequestBody?
var httpBody: RequestBody? {
stubbedHttpBody
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Stubs/StubResponse.swift b/Tests/NetworkLayerTests/Classes/Helpers/Stubs/StubResponse.swift
index 97f4471..2c6ad4a 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Stubs/StubResponse.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Stubs/StubResponse.swift
@@ -6,7 +6,7 @@
import Foundation
import Mocker
-struct StubResponse {
+struct StubResponse: @unchecked Sendable {
let name: String
let fileURL: URL
let httpMethod: Mock.HTTPMethod
diff --git a/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift b/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift
index 51821df..81b4560 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift
@@ -74,7 +74,7 @@ final class RequestProcessorAuthenicationTests: XCTestCase {
// MARK: Private
private func test_failAuthentication(adaptError: Error?, refreshError: Error?, expectedError: Error) async throws {
- class FailInterceptor: IAuthenticationInterceptor {
+ class FailInterceptor: IAuthenticationInterceptor, @unchecked Sendable {
let adaptError: Error?
let refreshError: Error?
@@ -125,7 +125,7 @@ final class RequestProcessorAuthenicationTests: XCTestCase {
// MARK: - AuthInterceptor
-private final class AuthInterceptor: IAuthenticationInterceptor {
+private final class AuthInterceptor: IAuthenticationInterceptor, @unchecked Sendable {
var token: Token!
private var attempts = 0
diff --git a/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorRequestTests.swift b/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorRequestTests.swift
index 8548539..8bd3a90 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorRequestTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorRequestTests.swift
@@ -46,12 +46,35 @@ final class RequestProcessorRequestTests: XCTestCase {
}
}
+ func test_thatRequestProcessorConfigureARequest() async throws {
+ // given
+ DynamicStubs.register(stubs: [.updateProfile])
+
+ let endpointURL = URL(string: "\(String.domain)/\(String.updateProfile)")
+ let delegateMock = RequestProcessorDelegateMock()
+
+ let sut = RequestProcessor.mock(requestProcessorDelegate: delegateMock)
+ let request = makeRequest(.user)
+
+ // when
+ let user: Response = try await sut.send(request) { urlRequest in
+ urlRequest.url = endpointURL
+ }
+
+ // then
+ XCTAssertEqual(user.data.id, 1)
+ XCTAssertNotNil(user.data.avatarUrl)
+ XCTAssertEqual(delegateMock.invokedRequestProcessorParameters?.request.httpMethod, HTTPMethod.get.rawValue)
+ XCTAssertEqual(delegateMock.invokedRequestProcessorParameters?.request.url, endpointURL)
+ }
+
// MARK: Private
private func makeRequest(_ path: String) -> IRequest {
let request = RequestStub()
- request.stubbedDomainName = "https://github.com"
+ request.stubbedDomainName = .domain
request.stubbedPath = path
+// request.httpMethod = .get
return request
}
}
@@ -75,8 +98,11 @@ private final class GitHubDelegate: RequestProcessorDelegate {
private extension StubResponse {
static let user = StubResponse(name: .user, fileURL: MockedData.userJSON, httpMethod: .get)
+ static let updateProfile = StubResponse(name: .updateProfile, fileURL: MockedData.userJSON, httpMethod: .get)
}
private extension String {
static let user = "user"
+ static let updateProfile = "updateProfile"
+ static let domain = "https://github.com"
}
diff --git a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBodyEncoderTests.swift b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBodyEncoderTests.swift
index ad3c44c..4d66378 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBodyEncoderTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBodyEncoderTests.swift
@@ -39,16 +39,16 @@ final class RequestBodyEncoderTests: XCTestCase {
XCTAssertEqual(requestFake.httpBody, data)
}
- func test_thatRequestBodyEncoderEncodesBodyIntoRequest_whenTypeIsDictonary() throws {
+ func test_thatRequestBodyEncoderEncodesBodyIntoRequest_whenTypeIsDictionary() throws {
// given
var requestFake = URLRequest.fake()
- let dictonary = ["test": "test"]
+ let dictionary = ["test": "test"]
// when
- try sut.encode(body: .dictonary(dictonary), to: &requestFake)
+ try sut.encode(body: .dictionary(dictionary), to: &requestFake)
// then
- let data = try JSONSerialization.data(withJSONObject: dictonary)
+ let data = try JSONSerialization.data(withJSONObject: dictionary)
XCTAssertEqual(requestFake.httpBody, data)
}
diff --git a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift
index ce7c383..43dd0e0 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift
@@ -59,7 +59,7 @@ final class RequestBuilderTests: XCTestCase {
requestStub.stubbedDomainName = .domainName
requestStub.stubbedHeaders = .contentType
requestStub.stubbedHttpMethod = .post
- requestStub.stubbedHttpBody = .dictonary(.item)
+ requestStub.stubbedHttpBody = .dictionary(.item)
requestStub.stubbedParameters = .contentType
// when
@@ -72,7 +72,7 @@ final class RequestBuilderTests: XCTestCase {
XCTAssertEqual(request?.httpMethod, "POST")
XCTAssertEqual(parametersEncoderMock.invokedEncodeParameters?.parameters, .contentType)
- if case let .dictonary(dict) = requestBodyEncoderMock.invokedEncodeParameters?.body {
+ if case let .dictionary(dict) = requestBodyEncoderMock.invokedEncodeParameters?.body {
XCTAssertTrue(NSDictionary(dictionary: dict).isEqual(to: Dictionary.item))
} else {
XCTFail("body should be equal to a dictionary")
diff --git a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift
index 9cb4a31..d99165a 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2023 Space Code. All rights reserved.
+// Copyright © 2024 Space Code. All rights reserved.
//
import Foundation
@@ -41,7 +41,8 @@ final class RequestParametersEncoderTests: XCTestCase {
func test_thatRequestParametersEncoderThrowsAnError_whenURLIsNotValid() {
// given
- var requestMock = URLRequest.fake(string: .wrongURL)
+ var requestMock = URLRequest.fake(string: .domainName)
+ requestMock.url = nil
// when
var receivedError: NSError?
@@ -60,7 +61,6 @@ final class RequestParametersEncoderTests: XCTestCase {
private extension String {
static let domainName = "https://google.com"
- static let wrongURL = "http://example.com:-80"
}
private extension Dictionary where Self.Key == String, Self.Value == String {
diff --git a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift
index a46d5a8..9357595 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift
@@ -43,7 +43,7 @@ final class RequestProcessorTests: XCTestCase {
requestBuilder: requestBuilderMock,
dataRequestHandler: dataRequestHandler,
retryPolicyService: retryPolicyMock,
- delegate: delegateMock,
+ delegate: SafeRequestProcessorDelegate(delegate: delegateMock),
interceptor: interceptorMock
)
}