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 1.2.1 #7

Merged
merged 20 commits into from Oct 28, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions Example/Pods/Pods.xcodeproj/project.pbxproj

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 44 additions & 15 deletions Example/Tests/IntegratedTest.swift
Expand Up @@ -19,7 +19,8 @@ class IntegratedTestSpec: QuickSpec {
var secondResult: URLResult?
let request = Ness(onDuplicated: .keepAllCompletion)
.httpRequest(.get, withUrl: "https://jsonplaceholder.typicode.com/todos/\(randomNumber)")
.prepareDataRequest()
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
request.then { result in
firstResult = result
}
Expand Down Expand Up @@ -47,7 +48,8 @@ class IntegratedTestSpec: QuickSpec {
var secondResult: URLResult?
let request = Ness(onDuplicated: .dropPreviousRequest)
.httpRequest(.get, withUrl: "https://jsonplaceholder.typicode.com/todos/\(randomNumber)")
.prepareDataRequest()
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
request.then { result in
firstResult = result
}
Expand All @@ -70,7 +72,8 @@ class IntegratedTestSpec: QuickSpec {
var firstResult: URLResult?
let request = Ness(onDuplicated: .keepFirstCompletion)
.httpRequest(.get, withUrl: "https://jsonplaceholder.typicode.com/todos/\(randomNumber)")
.prepareDataRequest()
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
waitUntil(timeout: 15) { done in
request.then { result in
firstResult = result
Expand All @@ -92,7 +95,8 @@ class IntegratedTestSpec: QuickSpec {
var secondResult: URLResult?
let request = Ness(onDuplicated: .keepLatestCompletion)
.httpRequest(.get, withUrl: "https://jsonplaceholder.typicode.com/todos/\(randomNumber)")
.prepareDataRequest()
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
waitUntil(timeout: 15) { done in
request.then { _ in
fail("This completion should not be executed")
Expand All @@ -115,7 +119,8 @@ class IntegratedTestSpec: QuickSpec {
waitUntil(timeout: 15) { done in
Ness.default
.httpRequest(.get, withUrl: "https://jsonplaceholder.typicode.com/todos/\(randomNumber)")
.prepareDataRequest()
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
.then { result in
requestResult = result
done()
Expand Down Expand Up @@ -154,7 +159,8 @@ class IntegratedTestSpec: QuickSpec {
waitUntil(timeout: 15) { done in
Ness.default
.httpRequest(.get, withUrl: "https://jsonplaceholder.typicode.com/posts")
.prepareDataRequest()
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
.then { result in
requestResult = result
done()
Expand Down Expand Up @@ -199,7 +205,8 @@ class IntegratedTestSpec: QuickSpec {
Ness.default
.httpRequest(.post, withUrl: "https://jsonplaceholder.typicode.com/posts")
.set(jsonEncodable: JSONPlaceholder(title: "foo", body: "bar", userId: randomNumber))
.prepareDataRequest()
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
.then { result in
requestResult = result
done()
Expand Down Expand Up @@ -233,13 +240,35 @@ class IntegratedTestSpec: QuickSpec {
expect(obj.body).to(equal("bar"))
expect(obj.completed).to(beNil())
}
it("should aggregate request") {
let firstRealUrl: URL = try! "https://jsonplaceholder.typicode.com/todos/\(Int.random(in: 0..<10))".asUrl()
let secondRealUrl: URL = try! "https://jsonplaceholder.typicode.com/todos/\(Int.random(in: 10..<20))".asUrl()
let firstRequest = Ness.default
.httpRequest(.get, withUrl: firstRealUrl)
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
let secondRequest = Ness.default
.httpRequest(.get, withUrl: secondRealUrl)
.prepareDataRequest(with: CounterRetryControl(maxRetryCount: 3))
.validate(statusCodes: 200..<300)
var firstResult: URLResult?
var secondResult: URLResult?
waitUntil(timeout: 15) { done in
firstRequest.aggregate(with: secondRequest).then { result in
expect(result.areCompleted).to(beTrue())
expect(result.results.count).to(equal(2))
firstResult = result.results[0]
secondResult = result.results[1]
done()
}
}
let firstUrl = try! firstResult?.httpMessage?.url.asUrl()
let secondUrl = try! secondResult?.httpMessage?.url.asUrl()
expect(firstUrl).toNot(beNil())
expect(secondUrl).toNot(beNil())
expect(firstUrl).toNot(equal(secondUrl))
expect(firstUrl == firstRealUrl || firstUrl == secondRealUrl).to(beTrue())
expect(secondUrl == firstRealUrl || secondUrl == secondRealUrl).to(beTrue())
}
}
}

struct JSONPlaceholder: Codable {
var id: Int = 0
var title: String
var body: String?
var userId: Int?
var completed: Bool? = nil
}
57 changes: 57 additions & 0 deletions Example/Tests/Mock.swift
@@ -0,0 +1,57 @@
//
// Mock.swift
// iONess_Tests
//
// Created by Nayanda Haberty (ID) on 27/10/20.
// Copyright © 2020 CocoaPods. All rights reserved.
//

import Foundation

struct JSONPlaceholder: Codable, Equatable {
var id: Int = 0
var title: String
var body: String?
var userId: Int?
var completed: Bool? = nil

static func mock() -> JSONPlaceholder {
.init(
id: .random(in: 0..<100),
title: .random(length: .random(in: 10..<100)),
body: .random(length: .random(in: 10..<100)),
userId: .random(in: 0..<100),
completed: .random()
)
}

static var `default`: JSONPlaceholder {
.init(
id: -1,
title: "",
body: nil,
userId: nil,
completed: nil
)
}
}

struct RandomJSON: Codable {
var randomInt: Int = .random(in: 0..<100)
var randomString: String = .random(length: .random(in: 10..<100))
var randomBool: Bool = .random()
}

extension String {
public static func random(length: Int = 9) -> String {
let letters : NSString = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let len = UInt32(letters.length)
var randomString = ""
for _ in 0 ..< length {
let rand = arc4random_uniform(len)
var nextChar = letters.character(at: Int(rand))
randomString += NSString(characters: &nextChar, length: 1) as String
}
return randomString
}
}
158 changes: 158 additions & 0 deletions Example/Tests/ResponseDecoderSpec.swift
@@ -0,0 +1,158 @@
//
// ResponseDecoderSpec.swift
// iONess_Tests
//
// Created by Nayanda Haberty (ID) on 27/10/20.
// Copyright © 2020 CocoaPods. All rights reserved.
//

import Foundation
import Quick
import Nimble
@testable import iONess

class ResponseDecoderSpec: QuickSpec {
override func spec() {
describe("positive case") {
it("should decode json from data") {
let mock = JSONPlaceholder.mock()
let data = try! JSONEncoder().encode(mock)
let decoded = try! JSONDecodableDecoder<JSONPlaceholder>().decode(from: data)
expect(decoded).to(equal(mock))
}
it("should decode json array from data") {
let mocks: [JSONPlaceholder] = [.mock(), .mock(), .mock(), .mock(), .mock()]
let data = try! JSONEncoder().encode(mocks)
let decodeds = try! ArrayJSONDecodableDecoder<JSONPlaceholder>().decode(from: data)
expect(decodeds).to(equal(mocks))
}
it("should decode json from data") {
let mock = JSONPlaceholder.mock()
let data = try! JSONEncoder().encode(mock)
let decoded = try! JSONResponseDecoder().decode(from: data)
expect(decoded["id"] as? Int).to(equal(mock.id))
expect(decoded["userId"] as? Int).to(equal(mock.userId))
expect(decoded["body"] as? String).to(equal(mock.body))
expect(decoded["completed"] as? Bool).to(equal(mock.completed))
expect(decoded["title"] as? String).to(equal(mock.title))
}
it("should decode json array from data") {
let mocks: [JSONPlaceholder] = [.mock(), .mock(), .mock(), .mock(), .mock()]
let data = try! JSONEncoder().encode(mocks)
let decodeds = try! ArrayJSONResponseDecoder().decode(from: data)
expect(decodeds.count).to(equal(mocks.count))
for (index, decoded) in decodeds.enumerated() {
guard let dict: [String: Any] = decoded as? [String : Any] else {
fail()
return
}
let mock = mocks[index]
expect(dict["id"] as? Int).to(equal(mock.id))
expect(dict["userId"] as? Int).to(equal(mock.userId))
expect(dict["body"] as? String).to(equal(mock.body))
expect(dict["completed"] as? Bool).to(equal(mock.completed))
expect(dict["title"] as? String).to(equal(mock.title))
}
}
it("should decode json from data") {
let mock = JSONPlaceholder.mock()
let data = try! JSONEncoder().encode(mock)
let decoded = try! PlaceholderJSONDecoder().decode(from: data)
expect(decoded).to(equal(mock))
}
it("should decode json from string") {
let mock = JSONPlaceholder.mock()
let data = try! JSONEncoder().encode(mock)
let decoded = try! PlaceholderStringDecoder().decode(from: data)
expect(decoded).to(equal(mock))
}
it("should decode array json from data") {
let mocks: [JSONPlaceholder] = [.mock(), .mock(), .mock(), .mock(), .mock()]
let data = try! JSONEncoder().encode(mocks)
let decoder = ArrayedJSONDecoder(singleDecoder: PlaceholderJSONDecoder())
let decodeds = try! decoder.decode(from: data)
expect(decodeds).to(equal(mocks))
}
}
describe("negative test") {
it("should fail decode json from data") {
let mock = RandomJSON()
let data = try! JSONEncoder().encode(mock)
expect {
let decoded = try JSONDecodableDecoder<JSONPlaceholder>().decode(from: data)
return decoded
}.to(throwError())
}
it("should fail decode json array from data") {
let mocks: [RandomJSON] = [.init(), .init(), .init(), .init(), .init()]
let data = try! JSONEncoder().encode(mocks)
expect {
let decoded = try ArrayJSONDecodableDecoder<JSONPlaceholder>().decode(from: data)
return decoded
}.to(throwError())
}
it("should fail decode json from data") {
let data = String.random().data(using: .utf8)!
expect {
let decoded = try JSONResponseDecoder().decode(from: data)
return decoded
}.to(throwError())
}
it("should fail decode array json from data") {
let data = String.random().data(using: .utf8)!
expect {
let decoded = try ArrayJSONResponseDecoder().decode(from: data)
return decoded
}.to(throwError())
}
it("should fail decode json from data") {
let data = String.random().data(using: .utf8)!
expect {
let decoded = try PlaceholderJSONDecoder().decode(from: data)
return decoded
}.to(throwError())
}
it("should fail decode json from string") {
let data = String.random().data(using: .utf8)!
expect {
let decoded = try PlaceholderStringDecoder().decode(from: data)
return decoded
}.to(throwError())
}
it("should fail decode array json from data") {
let data = String.random().data(using: .utf8)!
let decoder = ArrayedJSONDecoder(singleDecoder: PlaceholderJSONDecoder())
expect {
let decodeds = try decoder.decode(from: data)
return decodeds
}.to(throwError())
}
}
}
}

class PlaceholderJSONDecoder: BaseJSONDecoder<JSONPlaceholder> {
override func decode(from json: [String : Any]) throws -> JSONPlaceholder {
.init(
id: json["id"] as? Int ?? -1,
title: json["title"] as? String ?? "",
body: json["body"] as? String,
userId: json["userId"] as? Int,
completed: json["completed"] as? Bool
)
}
}

class PlaceholderStringDecoder: BaseStringDecoder<JSONPlaceholder> {
override func decode(from json: String) throws -> JSONPlaceholder {
let data = json.data(using: .utf8)!
let dict = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
return .init(
id: dict["id"] as? Int ?? -1,
title: dict["title"] as? String ?? "",
body: dict["body"] as? String,
userId: dict["userId"] as? Int,
completed: dict["completed"] as? Bool
)
}
}