diff --git a/HTTPService.xcodeproj/project.pbxproj b/HTTPService.xcodeproj/project.pbxproj index 7dffcd9..fff0cbf 100644 --- a/HTTPService.xcodeproj/project.pbxproj +++ b/HTTPService.xcodeproj/project.pbxproj @@ -20,17 +20,19 @@ 1988FC7D22FA0B34000F70B3 /* HTTPServiceBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1971904222F654B300B3BDC5 /* HTTPServiceBuilder.swift */; }; 1988FC7E22FA0B34000F70B3 /* ServiceBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1971904A22F655EE00B3BDC5 /* ServiceBuilder.swift */; }; 1988FC7F22FA0B34000F70B3 /* HTTPServiceError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1971903F22F6547700B3BDC5 /* HTTPServiceError.swift */; }; - 1988FC8022FA0B5F000F70B3 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C32F1B0AAD5600AC23D4 /* Address.swift */; }; - 1988FC8122FA0B5F000F70B3 /* FloorPlan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C3301B0AAD5600AC23D4 /* FloorPlan.swift */; }; - 1988FC8222FA0B5F000F70B3 /* Listing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C3311B0AAD5600AC23D4 /* Listing.swift */; }; - 1988FC8322FA0B5F000F70B3 /* JSONSerializableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F64449D1B0A102300AD34A0 /* JSONSerializableTests.swift */; }; + 1988FC8022FA0B5F000F70B3 /* PullRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C32F1B0AAD5600AC23D4 /* PullRequest.swift */; }; + 1988FC8D22FB839B000F70B3 /* ServiceBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC8C22FB839B000F70B3 /* ServiceBuilderTests.swift */; }; + 1988FC8E22FB83A4000F70B3 /* ServiceBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC8C22FB839B000F70B3 /* ServiceBuilderTests.swift */; }; + 1988FC9122FB83CE000F70B3 /* GitHubService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC9022FB83CE000F70B3 /* GitHubService.swift */; }; + 1988FC9222FB83D2000F70B3 /* GitHubService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC9022FB83CE000F70B3 /* GitHubService.swift */; }; + 1988FC9522FBA080000F70B3 /* GitHubGetPullRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC9422FBA080000F70B3 /* GitHubGetPullRequest.swift */; }; + 1988FC9622FBA080000F70B3 /* GitHubGetPullRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC9422FBA080000F70B3 /* GitHubGetPullRequest.swift */; }; + 1988FC9822FBA227000F70B3 /* HTTPServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC9722FBA227000F70B3 /* HTTPServiceTests.swift */; }; + 1988FC9922FBA229000F70B3 /* HTTPServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1988FC9722FBA227000F70B3 /* HTTPServiceTests.swift */; }; 3F43766A1AD1A14100FFC40C /* HTTPService.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F4376691AD1A14100FFC40C /* HTTPService.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3F4376701AD1A14100FFC40C /* HTTPService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F4376641AD1A14100FFC40C /* HTTPService.framework */; }; 3F43769D1AD1A19300FFC40C /* HTTPService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F43768B1AD1A19300FFC40C /* HTTPService.swift */; }; - 3F64449E1B0A102300AD34A0 /* JSONSerializableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F64449D1B0A102300AD34A0 /* JSONSerializableTests.swift */; }; - 3F98C3321B0AAD5600AC23D4 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C32F1B0AAD5600AC23D4 /* Address.swift */; }; - 3F98C3331B0AAD5600AC23D4 /* FloorPlan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C3301B0AAD5600AC23D4 /* FloorPlan.swift */; }; - 3F98C3341B0AAD5600AC23D4 /* Listing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C3311B0AAD5600AC23D4 /* Listing.swift */; }; + 3F98C3321B0AAD5600AC23D4 /* PullRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F98C32F1B0AAD5600AC23D4 /* PullRequest.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -61,6 +63,10 @@ 1988FC6622FA0AE6000F70B3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1988FC6B22FA0AE6000F70B3 /* HTTPService macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "HTTPService macOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 1988FC7222FA0AE7000F70B3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1988FC8C22FB839B000F70B3 /* ServiceBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceBuilderTests.swift; sourceTree = ""; }; + 1988FC9022FB83CE000F70B3 /* GitHubService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHubService.swift; sourceTree = ""; }; + 1988FC9422FBA080000F70B3 /* GitHubGetPullRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHubGetPullRequest.swift; sourceTree = ""; }; + 1988FC9722FBA227000F70B3 /* HTTPServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPServiceTests.swift; sourceTree = ""; }; 3F4376641AD1A14100FFC40C /* HTTPService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTTPService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3F4376681AD1A14100FFC40C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 3F4376691AD1A14100FFC40C /* HTTPService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTTPService.h; sourceTree = ""; }; @@ -68,10 +74,7 @@ 3F4376751AD1A14100FFC40C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 3F43768B1AD1A19300FFC40C /* HTTPService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPService.swift; sourceTree = ""; }; 3F64449C1B0A102200AD34A0 /* HTTPServiceTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HTTPServiceTests-Bridging-Header.h"; sourceTree = ""; }; - 3F64449D1B0A102300AD34A0 /* JSONSerializableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONSerializableTests.swift; sourceTree = ""; }; - 3F98C32F1B0AAD5600AC23D4 /* Address.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Address.swift; sourceTree = ""; }; - 3F98C3301B0AAD5600AC23D4 /* FloorPlan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloorPlan.swift; sourceTree = ""; }; - 3F98C3311B0AAD5600AC23D4 /* Listing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Listing.swift; sourceTree = ""; }; + 3F98C32F1B0AAD5600AC23D4 /* PullRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PullRequest.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -158,6 +161,22 @@ path = "HTTPService macOSTests"; sourceTree = ""; }; + 1988FC8F22FB83BC000F70B3 /* Test Service */ = { + isa = PBXGroup; + children = ( + 1988FC9022FB83CE000F70B3 /* GitHubService.swift */, + ); + path = "Test Service"; + sourceTree = ""; + }; + 1988FC9322FBA068000F70B3 /* Test Requests */ = { + isa = PBXGroup; + children = ( + 1988FC9422FBA080000F70B3 /* GitHubGetPullRequest.swift */, + ); + path = "Test Requests"; + sourceTree = ""; + }; 3F43765A1AD1A14100FFC40C = { isa = PBXGroup; children = ( @@ -205,8 +224,11 @@ 3F4376731AD1A14100FFC40C /* HTTPServiceTests */ = { isa = PBXGroup; children = ( + 1988FC9322FBA068000F70B3 /* Test Requests */, + 1988FC8F22FB83BC000F70B3 /* Test Service */, 3F98C32E1B0AAD5600AC23D4 /* Test Models */, - 3F64449D1B0A102300AD34A0 /* JSONSerializableTests.swift */, + 1988FC8C22FB839B000F70B3 /* ServiceBuilderTests.swift */, + 1988FC9722FBA227000F70B3 /* HTTPServiceTests.swift */, 3F4376741AD1A14100FFC40C /* Supporting Files */, ); path = HTTPServiceTests; @@ -224,9 +246,7 @@ 3F98C32E1B0AAD5600AC23D4 /* Test Models */ = { isa = PBXGroup; children = ( - 3F98C32F1B0AAD5600AC23D4 /* Address.swift */, - 3F98C3301B0AAD5600AC23D4 /* FloorPlan.swift */, - 3F98C3311B0AAD5600AC23D4 /* Listing.swift */, + 3F98C32F1B0AAD5600AC23D4 /* PullRequest.swift */, ); path = "Test Models"; sourceTree = ""; @@ -424,10 +444,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1988FC8022FA0B5F000F70B3 /* Address.swift in Sources */, - 1988FC8222FA0B5F000F70B3 /* Listing.swift in Sources */, - 1988FC8322FA0B5F000F70B3 /* JSONSerializableTests.swift in Sources */, - 1988FC8122FA0B5F000F70B3 /* FloorPlan.swift in Sources */, + 1988FC8022FA0B5F000F70B3 /* PullRequest.swift in Sources */, + 1988FC9922FBA229000F70B3 /* HTTPServiceTests.swift in Sources */, + 1988FC9222FB83D2000F70B3 /* GitHubService.swift in Sources */, + 1988FC9622FBA080000F70B3 /* GitHubGetPullRequest.swift in Sources */, + 1988FC8E22FB83A4000F70B3 /* ServiceBuilderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -448,10 +469,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3F98C3321B0AAD5600AC23D4 /* Address.swift in Sources */, - 3F98C3331B0AAD5600AC23D4 /* FloorPlan.swift in Sources */, - 3F98C3341B0AAD5600AC23D4 /* Listing.swift in Sources */, - 3F64449E1B0A102300AD34A0 /* JSONSerializableTests.swift in Sources */, + 3F98C3321B0AAD5600AC23D4 /* PullRequest.swift in Sources */, + 1988FC9822FBA227000F70B3 /* HTTPServiceTests.swift in Sources */, + 1988FC9122FB83CE000F70B3 /* GitHubService.swift in Sources */, + 1988FC9522FBA080000F70B3 /* GitHubGetPullRequest.swift in Sources */, + 1988FC8D22FB839B000F70B3 /* ServiceBuilderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/HTTPServiceTests/HTTPServiceTests.swift b/HTTPServiceTests/HTTPServiceTests.swift new file mode 100644 index 0000000..8d4c7bc --- /dev/null +++ b/HTTPServiceTests/HTTPServiceTests.swift @@ -0,0 +1,26 @@ +// +// HTTPServiceTests.swift +// HTTPServiceTests +// +// Created by Jeremy Fox on 8/7/19. +// Copyright © 2019 Jeremy Fox. All rights reserved. +// + +import XCTest +import HTTPService + +class HTTPServiceTests: XCTestCase { + + func testServiceExecutesRequestAndReturnsParsedResultType() { + let service = ServiceBuilder.build() + service?.execute(request: GitHubGetPullRequest(id: "123")) { (result) in + switch result { + case let .success(pr): + XCTAssertTrue(pr?.name == "PR Name") + case .failure(_): + XCTFail() + } + } + } + +} diff --git a/HTTPServiceTests/JSONSerializableTests.swift b/HTTPServiceTests/JSONSerializableTests.swift deleted file mode 100644 index 5403d7f..0000000 --- a/HTTPServiceTests/JSONSerializableTests.swift +++ /dev/null @@ -1,96 +0,0 @@ -// -// JSONParsingTests.swift -// -// Created by Jeremy Fox on 5/18/15. -// Copyright (c) 2015 Jeremy Fox. All rights reserved. -// -// - -import XCTest -import HTTPService - -class JSONSerializableTests: XCTestCase { - - // Given - let json = JSONSerializableTests.listingJSON() - var listing: Listing! - - override func setUp() { - super.setUp() - // When - do { - listing = try JSONDecoder().decode(Listing.self, from: json) - } catch let e { - XCTFail(e.localizedDescription) - } - } - - func testJSONParsingParsesIntegerValues() { - // Then - XCTAssert(listing.id == 123, "Expected listing.id to equal (123) but got (\(listing.id))") - } - - func testJSONParsingParsesStringValues() { - // Then - XCTAssert(listing.title == "Some Property Title", "Expected listing.title to equal (Some Property Title) but got (\(listing.title))") - } - - func testJSONParsingParsesDoublevalues() { - // Then - XCTAssert(listing.latitude == 12.4444, "Expected listing.lat to equal (12.4444) but got (\(listing.latitude))") - XCTAssert(listing.longitude == 23.5555, "Expected listing.lng to equal (23.5555) but got (\(listing.longitude))") - } - - func testJSONParsingParsesBoolValues() { - // Then - XCTAssert(listing.petsAllowed == true, "Expected listing.cats_allowed to equal (false but got \(listing.petsAllowed)") - } - - func testJSONParsingParsesCustomObjectValues() { - // Then - XCTAssert(listing.address?.number == 42, "Expected listing.address.number to equal 42 but got \(String(describing: listing.address?.number))") - XCTAssert(listing.address?.street == "Main St", "Expected listing.address.street to equal (Main St) but got \(String(describing: listing.address?.street))") - } - - func testJSONParsingParsesArrayOfCustomObjectValues() { - // When - let floorplan = listing.floorPlans![0] - - // Then - XCTAssert(floorplan.available == true, "Expected floorplan.available to equal true but got \(floorplan.available)") - XCTAssert(floorplan.baths == 3, "Expected floorplan.baths to equal 3 but got \(String(describing: floorplan.baths))") - XCTAssert(floorplan.beds == 2, "Expected floorplan.beds to equal 2 but got \(String(describing: floorplan.beds))") - XCTAssert(floorplan.createDate == "2/2/2015", "Expected floorplan.create_date to equal 2/2/2015 but got \(String(describing: floorplan.createDate))") - XCTAssert(floorplan.id == 55, "Expected floorplan.id to equal 55 but got \(floorplan.id)") - XCTAssert(floorplan.photos![0] == "/imgr/34505d862c70474b99042cbc8a168e04/800-", "Expected floorplan.photos![0] to equal (/imgr/34505d862c70474b99042cbc8a168e04/800-) but got (\(floorplan.photos![0]))") - } -} - -extension JSONSerializableTests { - static func listingJSON() -> Data { - let json: [String: Any] = [ - "id": 123, - "title": "Some Property Title", - "latitude": 12.4444, - "longitude": 23.5555, - "pets_allowed": true, - "address": [ - "number": 42, - "street": "Main St" - ], - "expired": false, - "floorplan_set": [ - [ - "available": true, - "baths": 3, - "beds": 2, - "create_date": "2/2/2015", - "id": 55, - "photos": ["/imgr/34505d862c70474b99042cbc8a168e04/800-"] - ] - ] - ] - - return try! JSONSerialization.data(withJSONObject: json, options: .init(rawValue: 0)) - } -} diff --git a/HTTPServiceTests/ServiceBuilderTests.swift b/HTTPServiceTests/ServiceBuilderTests.swift new file mode 100644 index 0000000..a2a9b69 --- /dev/null +++ b/HTTPServiceTests/ServiceBuilderTests.swift @@ -0,0 +1,30 @@ +// +// HTTPServiceTests.swift +// HTTPServiceTests +// +// Created by Jeremy Fox on 8/7/19. +// Copyright © 2019 Jeremy Fox. All rights reserved. +// + +import XCTest +import HTTPService + +class ServiceBuilderTests: XCTestCase { + + func testReturnsCachedService() { + let ghService1 = ServiceBuilder.build() + let ghService2 = ServiceBuilder.build() + XCTAssertEqual(ghService1, ghService2) + } + + func testPurgeRemovesCachedService() { + let ghService1 = ServiceBuilder.build() + XCTAssertNotNil(ghService1) + + ServiceBuilder.purgeCache() + + let ghService2 = ServiceBuilder.build() + XCTAssertNotEqual(ghService1, ghService2) + } + +} diff --git a/HTTPServiceTests/Test Models/FloorPlan.swift b/HTTPServiceTests/Test Models/FloorPlan.swift deleted file mode 100644 index b2f18a7..0000000 --- a/HTTPServiceTests/Test Models/FloorPlan.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// FloorPlan.swift -// -// Created by Jeremy Fox on 5/18/15. -// Copyright (c) 2015 Jeremy Fox. All rights reserved. -// - -import Foundation - -struct FloorPlan: Codable { - var id: Int - var available: Bool - var baths: Int? - var beds: Int? - var photos: [String]? - var createDate: String? - - private enum CodingKeys: String, CodingKey { - case id - case available - case baths - case beds - case photos - case createDate = "create_date" - } -} diff --git a/HTTPServiceTests/Test Models/Listing.swift b/HTTPServiceTests/Test Models/Listing.swift deleted file mode 100644 index cf9e837..0000000 --- a/HTTPServiceTests/Test Models/Listing.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// Listing.swift -// -// Created by Jeremy Fox on 5/18/15. -// Copyright (c) 2015 Jeremy Fox. All rights reserved. -// - -import Foundation - -struct Listing: Codable { - var id: Int64 - var title: String - var latitude: Double - var longitude: Double - var petsAllowed: Bool - var address: Address? - var expired: Bool - var floorPlans: [FloorPlan]? - - private enum CodingKeys: String, CodingKey { - case id - case title - case latitude - case longitude - case petsAllowed = "pets_allowed" - case address - case expired - case floorPlans = "floorplan_set" - } -} diff --git a/HTTPServiceTests/Test Models/Address.swift b/HTTPServiceTests/Test Models/PullRequest.swift similarity index 67% rename from HTTPServiceTests/Test Models/Address.swift rename to HTTPServiceTests/Test Models/PullRequest.swift index a0e1f8e..9b85207 100644 --- a/HTTPServiceTests/Test Models/Address.swift +++ b/HTTPServiceTests/Test Models/PullRequest.swift @@ -7,7 +7,7 @@ import Foundation -struct Address: Codable { - var number: Int - var street: String +struct PullRequest: Codable { + let id: Int + let name: String } diff --git a/HTTPServiceTests/Test Requests/GitHubGetPullRequest.swift b/HTTPServiceTests/Test Requests/GitHubGetPullRequest.swift new file mode 100644 index 0000000..ea4ed4b --- /dev/null +++ b/HTTPServiceTests/Test Requests/GitHubGetPullRequest.swift @@ -0,0 +1,30 @@ +// +// GitHubGetPullRequest.swift +// HTTPService +// +// Created by Jeremy Fox on 8/7/19. +// Copyright © 2019 Jeremy Fox. All rights reserved. +// + +import Foundation +import HTTPService + +struct GitHubGetPullRequest: HTTPRequest { + + typealias ResultType = PullRequest + typealias BodyType = HTTPRequestNoBody + + var endpoint = "/something" + var method: HTTPMethod = .get + var params: [String : Any]? + var body: HTTPRequestNoBody? + var headers: [String : String]? + var includeServiceLevelHeaders: Bool = true + var includeServiceLevelAuthorization: Bool = true + + let prId: String? + + init(id: String?) { + prId = id + } +} diff --git a/HTTPServiceTests/Test Service/GitHubService.swift b/HTTPServiceTests/Test Service/GitHubService.swift new file mode 100644 index 0000000..4bf1354 --- /dev/null +++ b/HTTPServiceTests/Test Service/GitHubService.swift @@ -0,0 +1,55 @@ +// +// File.swift +// HTTPServiceTests +// +// Created by Jeremy Fox on 8/7/19. +// Copyright © 2019 Jeremy Fox. All rights reserved. +// + +import Foundation +import HTTPService + +final class GitHubService: HTTPService { + typealias Builder = GitHubService + typealias Authorization = HTTPTokenAuthorization + + var urlSession = URLSession.shared + var tasks = [URLSessionTask]() + var baseUrl = BaseURL(string: "https://api.github.com")! + var headers: HTTPHeaders? { + return ["Accept": "application/vnd.github.v3+json"] + } + var authorization: HTTPTokenAuthorization? + + init(authorization: HTTPTokenAuthorization?) { + self.authorization = authorization + } +} + +extension GitHubService: HTTPServiceBuilder { + static func build() -> T? { + let auth = HTTPTokenAuthorization(token: UUID().uuidString) + return GitHubService(authorization: auth) as? T + } +} + +extension GitHubService { + @discardableResult + func execute(request: T, handler: @escaping (HTTPResult) -> Void) -> URLSessionTask where T : HTTPRequest { + do { + let data = try JSONSerialization.data(withJSONObject: ["id": 123, "name": "PR Name"], options: .init(rawValue: 0)) + let pr = try JSONDecoder().decode(T.ResultType.self, from: data) + handler(.success(pr)) + } catch _ { + handler(.failure(.emptyResponseData(""))) + } + + return URLSessionDataTask() + } +} + +extension GitHubService: Equatable {} + +func ==(left: GitHubService, right: GitHubService) -> Bool { + return left.urlSession == right.urlSession && left.tasks == right.tasks && left.baseUrl == right.baseUrl && left.headers == right.headers && left.authorization?.value == right.authorization?.value +}