Skip to content

Commit

Permalink
Final Release Merge for 1.1 (#82)
Browse files Browse the repository at this point in the history
* Fixes small linter warning

* updates to recommended build settings

* upgrade swift version

* Update NetworkServiceMock.swift

NetworkServiceMock now supports request response chains, where one response leads to an other request.

* Fixes tests of RetryNetworkService using the NetworkServiceMock

* Made new implementation of returnError/returnSuccess not depend on old implemention

* improves tests for RetryNetworkTask

* Update README.md

* small clean ups

* Added unit tests for NetworkServiceMock

* Resolved linter warnings

* Updated documentation of NetworkServiceMock

* Fixed an other linter warning

* bump version

* Removes unneeded file
  • Loading branch information
lightsprint09 authored and ch-one committed Jun 6, 2018
1 parent 456ee27 commit 1e35388
Show file tree
Hide file tree
Showing 15 changed files with 341 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .swift-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.0
4.1
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ matrix:
script:
- swift test --verbose
- os: osx
osx_image: xcode9.2
language: objective-c
osx_image: xcode9.3
env: "macOS"
skip-cleanup: true
before_install:
Expand Down
2 changes: 1 addition & 1 deletion DBNetworkStack.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pod::Spec.new do |s|
#

s.name = "DBNetworkStack"
s.version = "1.0.0"
s.version = "1.1.0"
s.summary = "DBNetworkStack is a network abstraction for fetching request and mapping them to model objects."

# This description is used to generate tags and improve search results.
Expand Down
6 changes: 5 additions & 1 deletion DBNetworkStack.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0900;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = DBSystel;
TargetAttributes = {
C60BE65A1D6B2BF3006B0364 = {
Expand Down Expand Up @@ -466,12 +466,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down Expand Up @@ -527,12 +529,14 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -26,8 +26,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
codeCoverageEnabled = "YES"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Create a resource with a request to fetch your data.
```swift

let url = URL(string: "https://httpbin.org")!
let request = URLRequest(path: "/", baseURL: url)
let request = URLRequest(path: "/", baseURL: url, HTTPMethod: .GET)
let resource = Resource(request: request, parse: { String(data: $0, encoding: .utf8) })

```
Expand Down Expand Up @@ -112,7 +112,7 @@ The following table shows all the protocols and their default implementations.
Specify the following in your `Cartfile`:

```ogdl
github "dbsystel/dbnetworkstack" ~> 1.0
github "dbsystel/dbnetworkstack" ~> 1.1
```

### CocoaPods
Expand Down
2 changes: 1 addition & 1 deletion Source/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<string>1.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
116 changes: 93 additions & 23 deletions Source/NetworkServiceMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ struct NetworkServiceMockCallback {
}

/**
Mocks a `NetworkService`. You can configure expected results or errors to have a fully functional mock.
Mocks a `NetworkService`.
You can configure expected results or errors to have a fully functional mock.

**Example**:
```swift
Expand All @@ -58,12 +59,46 @@ struct NetworkServiceMockCallback {
let resource: Resource<String> = //

//When
// Your test code
networkService.request(
resource,
onCompletion: { string in /*...*/ },
onError: { error in /*...*/ }
)
networkService.returnSuccess(with: "Sucess")

//Then
//Test your expectations

```

It is possible to start multiple requests at a time.
All requests and responses (or errors) are processed
in order they have been called. So, everything is serial.

**Example**:
```swift
//Given
let networkServiceMock = NetworkServiceMock()
let resource: Resource<String> = //

//When
networkService.request(
resource,
onCompletion: { string in /* Success */ },
onError: { error in /*...*/ }
)
networkService.request(
resource,
onCompletion: { string in /*...*/ },
onError: { error in /*. cancel error .*/ }
)

networkService.returnSuccess(with: "Sucess")
networkService.returnError(with: .cancelled)

//Then
//Test your expectations

```

- seealso: `NetworkService`
Expand All @@ -76,11 +111,11 @@ public final class NetworkServiceMock: NetworkService {
/// Set this to hava a custom networktask returned by the mock
public var nextNetworkTask: NetworkTask?

private var callbacks: NetworkServiceMockCallback?
private var callbacks: [NetworkServiceMockCallback] = []

/// Creates an instace of `NetworkServiceMock`
public init() {}

/**
Fetches a resource asynchronously from remote location. Execution of the requests starts immediately.
Execution happens on no specific queue. It dependes on the network access which queue is used.
Expand All @@ -93,9 +128,9 @@ public final class NetworkServiceMock: NetworkService {
let resource: Resource<String> = //

networkService.request(queue: .main, resource: resource, onCompletionWithResponse: { htmlText, response in
print(htmlText, response)
print(htmlText, response)
}, onError: { error in
// Handle errors
// Handle errors
})
```

Expand All @@ -108,11 +143,15 @@ public final class NetworkServiceMock: NetworkService {
*/
@discardableResult
public func request<Result>(queue: DispatchQueue, resource: Resource<Result>, onCompletionWithResponse: @escaping (Result, HTTPURLResponse) -> Void,
onError: @escaping (NetworkError) -> Void) -> NetworkTask {

onError: @escaping (NetworkError) -> Void) -> NetworkTask {
lastRequest = resource.request
requestCount += 1
callbacks = NetworkServiceMockCallback(resource: resource, onCompletionWithResponse: onCompletionWithResponse, onError: onError)
callbacks.append(NetworkServiceMockCallback(
resource: resource,
onCompletionWithResponse: onCompletionWithResponse,
onError: onError
))

return nextNetworkTask ?? NetworkTaskMock()
}
Expand All @@ -121,25 +160,44 @@ public final class NetworkServiceMock: NetworkService {
///
/// - Parameters:
/// - error: the error which gets passed to the caller
/// - count: the count, how often the error accours. 1 by default
public func returnError(with error: NetworkError, count: Int = 1) {
for _ in 0..<count {
callbacks?.onErrorCallback?(error)
public func returnError(with error: NetworkError) {
callbacks.removeFirst().onErrorCallback?(error)
}

/// Will return an error to the current waiting request.
///
/// - Parameters:
/// - error: the error which gets passed to the caller
/// - count: the count, how often the error occours.
@available(*, deprecated, message: "Use returnError without count parameter instead. Multiple calls can be done manually.")
public func returnError(with error: NetworkError, count: Int) {
(0..<count).forEach { _ in
precondition(!callbacks.isEmpty, "There is no request left to return an error for.")
returnError(with: error)
}
callbacks = nil
}

/// Will return a successful request, by using the given data as a server response.
///
/// - Parameters:
/// - data: the mock response from the server.
/// - httpResponse: the mock `HTTPURLResponse` from the server. `HTTPURLResponse()` by default
public func returnSuccess(with data: Data, httpResponse: HTTPURLResponse = HTTPURLResponse()) {
callbacks.removeFirst().onSuccess?(data, httpResponse)
}

/// Will return a successful request, by using the given data as a server response.
///
/// - Parameters:
/// - data: the mock response from the server. `Data()` by default
/// - httpResponse: the mock `HTTPURLResponse` from the server. `HTTPURLResponse()` by default
/// - count: the count how often the response gets triggerd. 1 by default
/// - count: the count how often the response gets triggerd.
@available(*, deprecated, message: "Use returnSuccess without count parameter instead. Multiple calls can be done manually.")
public func returnSuccess(with data: Data = Data(), httpResponse: HTTPURLResponse = HTTPURLResponse(), count: Int = 1) {
for _ in 0..<count {
callbacks?.onSuccess?(data, httpResponse)
(0..<count).forEach { _ in
precondition(!callbacks.isEmpty, "There is no request left to return a success for.")
returnSuccess(with: data, httpResponse: httpResponse)
}
callbacks = nil
}

/// Will return a successful request, by using the given type `T` as serialized result of a request.
Expand All @@ -149,12 +207,24 @@ public final class NetworkServiceMock: NetworkService {
/// - Parameters:
/// - data: the mock response from the server. `Data()` by default
/// - httpResponse: the mock `HTTPURLResponse` from the server. `HTTPURLResponse()` by default
/// - count: the count how often the response gets triggerd. 1 by default
public func returnSuccess<T>(with serializedResponse: T, httpResponse: HTTPURLResponse = HTTPURLResponse(), count: Int = 1) {
for _ in 0..<count {
callbacks?.onTypedSuccess?(serializedResponse, httpResponse)
public func returnSuccess<T>(with serializedResponse: T, httpResponse: HTTPURLResponse = HTTPURLResponse()) {
callbacks.removeFirst().onTypedSuccess?(serializedResponse, httpResponse)
}

/// Will return a successful request, by using the given type `T` as serialized result of a request.
///
/// **Warning:** This will crash if type `T` does not match your expected ResponseType of your current request
///
/// - Parameters:
/// - data: the mock response from the server. `Data()` by default
/// - httpResponse: the mock `HTTPURLResponse` from the server. `HTTPURLResponse()` by default
/// - count: the count how often the response gets triggerd.
@available(*, deprecated, message: "Use returnSuccess without count parameter instead. Multiple calls can be done manually.")
public func returnSuccess<T>(with serializedResponse: T, httpResponse: HTTPURLResponse = HTTPURLResponse(), count: Int) {
(0..<count).forEach { _ in
precondition(!callbacks.isEmpty, "There is no request left to return a typed success for.")
returnSuccess(with: serializedResponse, httpResponse: httpResponse)
}
callbacks = nil
}

}
2 changes: 1 addition & 1 deletion Source/Resource+Map.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ extension Resource {
///
/// - Parameter transform: transforms the original result of the resource
/// - Returns: the transformed resource
public func map<T>(transform: @escaping (Model) throws -> (T)) -> Resource<T> {
public func map<T>(transform: @escaping (Model) throws -> T) -> Resource<T> {
return Resource<T>(request: request, parse: { data in
return try transform(try self.parse(data))
})
Expand Down
3 changes: 2 additions & 1 deletion Source/RetryNetworkTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import Foundation
import Dispatch

/// A NetworkTaskRepresenting which can be used together with `RetryNetworkService` to keep a task alife to repeat the task after a given time
class RetryNetworkTask<T> : NetworkTask {
final class RetryNetworkTask<T>: NetworkTask {

private let maxmimumNumberOfRetries: Int
private let idleTimeInterval: TimeInterval
private let shouldRetry: (NetworkError) -> Bool
Expand Down
7 changes: 3 additions & 4 deletions Tests/DBNetworkStackTests/NetworkResponseProcessorTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class NetworkResponseProcessingTests: XCTestCase {
XCTFail("Expected cancelled error (got \(error)")
}
} catch let error {
XCTFail("Expected NetworkError (got \(type(of:error)))")
XCTFail("Expected NetworkError (got \(type(of: error)))")
}

XCTAssertNil(result, "Expected processing to fail")
Expand Down Expand Up @@ -80,12 +80,11 @@ class NetworkResponseProcessingTests: XCTestCase {
}

XCTAssertEqual(recievedData, data)
break
default:
XCTFail("Expected cancelled error (got \(error)")
}
} catch let error {
XCTFail("Expected NetworkError (got \(type(of:error)))")
XCTFail("Expected NetworkError (got \(type(of: error)))")
}
}

Expand All @@ -105,7 +104,7 @@ class NetworkResponseProcessingTests: XCTestCase {
XCTFail("Expected cancelled error (got \(error)")
}
} catch let error {
XCTFail("Expected NetworkError (got \(type(of:error)))")
XCTFail("Expected NetworkError (got \(type(of: error)))")
}

}
Expand Down
Loading

0 comments on commit 1e35388

Please sign in to comment.