From 47d4476a027e1c6569a348d0fb4d05de1780ca55 Mon Sep 17 00:00:00 2001 From: Jon Cravotta Date: Sun, 14 Oct 2018 12:58:24 -0400 Subject: [PATCH 1/7] Fix bidirectional dependencies (#13) * Bug fix for resources with bidirectional dependancies * updated cached resource to include type, wrote test for bidirectional relationships * making cache value a set of ids * should be checking should load of resource in inner loop * using set literal and no need for nil coalescing * renamed signature for caching resources * keeping cached resource contained in method so client does not need to implement their own empty cache --- SwiftyJSONAPI.xcodeproj/project.pbxproj | 4 ++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 +++ SwiftyJSONAPI/JSONAPIResource.swift | 57 ++++++++++++--- SwiftyJSONAPITests/JSONAPIDocumentTests.swift | 41 ++++++++++- .../example-bidirectional-relationship.json | 72 +++++++++++++++++++ 5 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 SwiftyJSONAPI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 SwiftyJSONAPITests/example-bidirectional-relationship.json diff --git a/SwiftyJSONAPI.xcodeproj/project.pbxproj b/SwiftyJSONAPI.xcodeproj/project.pbxproj index 7d54a36..21427f9 100644 --- a/SwiftyJSONAPI.xcodeproj/project.pbxproj +++ b/SwiftyJSONAPI.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1C04AAC521370E2000547976 /* example-bidirectional-relationship.json in Resources */ = {isa = PBXBuildFile; fileRef = 1C04AAC421370E2000547976 /* example-bidirectional-relationship.json */; }; 217C53B61BD042E300E82E37 /* JSONAPIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 217C53B51BD042E300E82E37 /* JSONAPIError.swift */; }; 21B93C981C8E593F00F67D9C /* JSONAPIErrorSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21B93C971C8E593F00F67D9C /* JSONAPIErrorSource.swift */; }; 21E3BD5E1BD53DAE000E4E39 /* example-error.json in Resources */ = {isa = PBXBuildFile; fileRef = 21E3BD5D1BD53DAE000E4E39 /* example-error.json */; }; @@ -32,6 +33,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1C04AAC421370E2000547976 /* example-bidirectional-relationship.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "example-bidirectional-relationship.json"; sourceTree = ""; }; 217C53B51BD042E300E82E37 /* JSONAPIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = JSONAPIError.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 21B93C971C8E593F00F67D9C /* JSONAPIErrorSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = JSONAPIErrorSource.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 21E3BD5D1BD53DAE000E4E39 /* example-error.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "example-error.json"; sourceTree = ""; }; @@ -109,6 +111,7 @@ E9D236E31BA2D40A00286911 /* Info.plist */, E9D236F61BA2D7B900286911 /* example-document-1.json */, 21E3BD5D1BD53DAE000E4E39 /* example-error.json */, + 1C04AAC421370E2000547976 /* example-bidirectional-relationship.json */, ); path = SwiftyJSONAPITests; sourceTree = ""; @@ -212,6 +215,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1C04AAC521370E2000547976 /* example-bidirectional-relationship.json in Resources */, E9D236F71BA2D7B900286911 /* example-document-1.json in Resources */, 21E3BD5E1BD53DAE000E4E39 /* example-error.json in Resources */, ); diff --git a/SwiftyJSONAPI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftyJSONAPI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/SwiftyJSONAPI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SwiftyJSONAPI/JSONAPIResource.swift b/SwiftyJSONAPI/JSONAPIResource.swift index f876abc..57282a5 100644 --- a/SwiftyJSONAPI/JSONAPIResource.swift +++ b/SwiftyJSONAPI/JSONAPIResource.swift @@ -14,6 +14,9 @@ public enum JSONAPIResourceLoaded { case NotLoaded } +typealias ResourceType = String +typealias ResourceIds = Set +typealias CachedResources = [ResourceType : ResourceIds] public class JSONAPIResource: JSONPrinter { public var id = "" @@ -94,21 +97,53 @@ public class JSONAPIResource: JSONPrinter { func loadResources(withIncludedResources includedResources: ResourcesByTypeAndId) { - for relationship in self.relationships { - - for resource in relationship.resources { + func _loadResources(withIncludedResources includedResources: ResourcesByTypeAndId, cachedResources: inout CachedResources) { + for relationship in self.relationships { - guard let includedResource = includedResources[resource] else { continue } + for resource in relationship.resources { + + guard let includedResource = includedResources[resource] else { continue } + + resource.attributes = includedResource.attributes + resource.relationships = includedResource.relationships + + + if !resource.relationships.isEmpty, resource.cacheIfNeeded(&cachedResources) { + + resource.parent = self.parent + _loadResources(withIncludedResources: includedResources, cachedResources: &cachedResources) + } + + resource.loaded = .Loaded + } + } + } + + var cachedResources = CachedResources() + _loadResources(withIncludedResources: includedResources, cachedResources: &cachedResources) + } +} + +private extension JSONAPIResource { + + // Checks if a resource has been loaded already, prevents bidirectional relationships from being recursively called + @discardableResult func cacheIfNeeded(_ cache: inout CachedResources) -> Bool { + + if var cachedIds = cache[type] { + + if cachedIds.contains(id) { - resource.attributes = includedResource.attributes - resource.relationships = includedResource.relationships + return false + } else { - if !resource.relationships.isEmpty { - resource.parent = self.parent - resource.loadResources(withIncludedResources: includedResources) - } - resource.loaded = .Loaded + cachedIds.insert(id) + cache[type] = cachedIds + return true } + } else { + + cache[type] = [id] + return true } } } diff --git a/SwiftyJSONAPITests/JSONAPIDocumentTests.swift b/SwiftyJSONAPITests/JSONAPIDocumentTests.swift index f5424cf..844278d 100644 --- a/SwiftyJSONAPITests/JSONAPIDocumentTests.swift +++ b/SwiftyJSONAPITests/JSONAPIDocumentTests.swift @@ -62,7 +62,7 @@ class JSONAPIDocumentTests: XCTestCase { } - func testMeta(){ + func testMeta() { let document = try! JSONAPIDocument(self.testData) let meta = document.meta! let keys = [String](meta.keys) @@ -72,7 +72,7 @@ class JSONAPIDocumentTests: XCTestCase { } - func testResourcesLoadedFromInclude () { + func testResourcesLoadedFromInclude() { let document = try! JSONAPIDocument(self.testData) var authorAttributesCount = 0 var commentsAttributesCount = 0 @@ -99,6 +99,37 @@ class JSONAPIDocumentTests: XCTestCase { XCTAssertTrue(commentsAttributesCount == 1,"Comment resource should contain 1 attribute") } + func testbidirectionalRelationship() { + if let bidirectionalFile = Bundle(for: JSONAPIDocumentTests.self).path(forResource: "example-bidirectional-relationship", ofType: "json") { + self.testData = try? Data(contentsOf: URL(fileURLWithPath: bidirectionalFile)) + } else { + XCTFail("Could not find error test file") + } + + var userHasAdressRelationship = false + var addressHasUserRelationship = false + + let document = try! JSONAPIDocument(self.testData) + document.loadIncludedResources() + + let resource = document.data.first + + resource?.relationships.forEach { relationship in + switch relationship.type { + case "user": + userHasAdressRelationship = relationship.hasRelationship(toType: "address") + case "address": + addressHasUserRelationship = relationship.hasRelationship(toType: "user") + default: + // For now we are only handling these 2 cases + break + } + } + + XCTAssertTrue(userHasAdressRelationship, "Expected user to have a relationship to addess") + XCTAssertTrue(addressHasUserRelationship, "Expected address to have a relationship to a user") + } + // func testPerformanceExample() { // This is an example of a performance test case. @@ -108,3 +139,9 @@ class JSONAPIDocumentTests: XCTestCase { } } + +private extension JSONAPIRelationship { + func hasRelationship(toType type: String) -> Bool { + return resources.first?.relationships.contains(where: { $0.type == type }) == true + } +} diff --git a/SwiftyJSONAPITests/example-bidirectional-relationship.json b/SwiftyJSONAPITests/example-bidirectional-relationship.json new file mode 100644 index 0000000..00339c2 --- /dev/null +++ b/SwiftyJSONAPITests/example-bidirectional-relationship.json @@ -0,0 +1,72 @@ +{ + "data":[ + { + "type":"profile", + "id":"1", + "attributes":{ + "type":"member" + }, + "relationships":{ + "user":{ + "data":[ + { + "type":"user", + "id":"32" + } + ] + }, + "address":{ + "data":[ + { + "type":"address", + "id":"5" + } + ] + } + } + } + ], + "included":[ + { + "type":"user", + "id":"32", + "attributes":{ + "first-name":"Johnny", + "last-name":"Appleseed", + "twitter":"jappleseed" + }, + "relationships":{ + "address":{ + "data":{ + "type":"address", + "id":"5" + } + } + } + }, + { + "type":"address", + "id":"5", + "attributes":{ + "street":"Apple tree lane" + }, + "relationships":{ + "user":{ + "data":{ + "type":"user", + "id":"32" + } + } + } + } + ], + "meta":{ + "copyright":"Copyright 2015 Example Corp.", + "authors":[ + "Yehuda Katz", + "Steve Klabnik", + "Dan Gebhardt", + "Tyler Kellen" + ] + } +} From 40e54515777f1e852590622c66f9a384d1d2e32f Mon Sep 17 00:00:00 2001 From: thomassnielsen Date: Sun, 14 Oct 2018 19:00:22 +0200 Subject: [PATCH 2/7] Update version to 0.0.20 --- SwiftyJSONAPI.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftyJSONAPI.podspec b/SwiftyJSONAPI.podspec index 24865c1..0de0b44 100644 --- a/SwiftyJSONAPI.podspec +++ b/SwiftyJSONAPI.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "SwiftyJSONAPI" - s.version = "0.0.19" + s.version = "0.0.20" s.summary = "JSONAPI document representation and serializing in Swift." s.swift_version = "4.0" From 4e185851fe12890f35a876b0974708cd019f3d8f Mon Sep 17 00:00:00 2001 From: Ken Ackerson Date: Mon, 15 Oct 2018 11:18:56 -0400 Subject: [PATCH 3/7] Calling the correct method recursively --- SwiftyJSONAPI/JSONAPIResource.swift | 39 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/SwiftyJSONAPI/JSONAPIResource.swift b/SwiftyJSONAPI/JSONAPIResource.swift index 57282a5..fccc3f2 100644 --- a/SwiftyJSONAPI/JSONAPIResource.swift +++ b/SwiftyJSONAPI/JSONAPIResource.swift @@ -96,31 +96,30 @@ public class JSONAPIResource: JSONPrinter { } func loadResources(withIncludedResources includedResources: ResourcesByTypeAndId) { - - func _loadResources(withIncludedResources includedResources: ResourcesByTypeAndId, cachedResources: inout CachedResources) { - for relationship in self.relationships { + var cachedResources = CachedResources() + _loadResources(withIncludedResources: includedResources, cachedResources: &cachedResources) + } + + fileprivate func _loadResources(withIncludedResources includedResources: ResourcesByTypeAndId, cachedResources: inout CachedResources) { + for relationship in self.relationships { + + for resource in relationship.resources { - for resource in relationship.resources { - - guard let includedResource = includedResources[resource] else { continue } - - resource.attributes = includedResource.attributes - resource.relationships = includedResource.relationships - - - if !resource.relationships.isEmpty, resource.cacheIfNeeded(&cachedResources) { - - resource.parent = self.parent - _loadResources(withIncludedResources: includedResources, cachedResources: &cachedResources) - } + guard let includedResource = includedResources[resource] else { continue } + + resource.attributes = includedResource.attributes + resource.relationships = includedResource.relationships + + + if !resource.relationships.isEmpty, resource.cacheIfNeeded(&cachedResources) { - resource.loaded = .Loaded + resource.parent = self.parent + resource._loadResources(withIncludedResources: includedResources, cachedResources: &cachedResources) } + + resource.loaded = .Loaded } } - - var cachedResources = CachedResources() - _loadResources(withIncludedResources: includedResources, cachedResources: &cachedResources) } } From 743237e75026c38d1b2a9db66fe2b05e09a655f2 Mon Sep 17 00:00:00 2001 From: thomassnielsen Date: Mon, 15 Oct 2018 17:58:35 +0200 Subject: [PATCH 4/7] Version bump --- SwiftyJSONAPI.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftyJSONAPI.podspec b/SwiftyJSONAPI.podspec index 0de0b44..c217c84 100644 --- a/SwiftyJSONAPI.podspec +++ b/SwiftyJSONAPI.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "SwiftyJSONAPI" - s.version = "0.0.20" + s.version = "0.0.21" s.summary = "JSONAPI document representation and serializing in Swift." s.swift_version = "4.0" From 118fd6ad729b816598e53422f107045a8c1d76e8 Mon Sep 17 00:00:00 2001 From: Damien Vieira Date: Mon, 3 Jun 2019 12:01:29 -0400 Subject: [PATCH 5/7] Support Swift 5.0 (#15) * Migrate to Swift 5 * Cleanup some warnings * Updated Pod Spec with swift version 5.0 * Updating travis CI * Updating simulator runtime to iOS 12.2 --- .travis.yml | 4 +-- SwiftyJSONAPI.podspec | 2 +- SwiftyJSONAPI.xcodeproj/project.pbxproj | 25 ++++++++----------- .../xcschemes/SwiftyJSONAPI.xcscheme | 2 +- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index dedce36..dd061ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: objective-c # xcode_project: SwiftyJSONAPI.xcodeproj # xcode_scheme: SwiftyJSONAPI -osx_image: xcode9.3beta +osx_image: xcode10.2 script: - - xcodebuild clean build test -project SwiftyJSONAPI.xcodeproj -scheme SwiftyJSONAPI -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.3' + - xcodebuild clean build test -project SwiftyJSONAPI.xcodeproj -scheme SwiftyJSONAPI -destination 'platform=iOS Simulator,name=iPhone 7,OS=12.2' diff --git a/SwiftyJSONAPI.podspec b/SwiftyJSONAPI.podspec index c217c84..81cf2bf 100644 --- a/SwiftyJSONAPI.podspec +++ b/SwiftyJSONAPI.podspec @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.name = "SwiftyJSONAPI" s.version = "0.0.21" s.summary = "JSONAPI document representation and serializing in Swift." - s.swift_version = "4.0" + s.swift_version = "5.0" s.homepage = "https://github.com/thomassnielsen/SwiftyJSONAPI" # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" diff --git a/SwiftyJSONAPI.xcodeproj/project.pbxproj b/SwiftyJSONAPI.xcodeproj/project.pbxproj index 21427f9..3f89858 100644 --- a/SwiftyJSONAPI.xcodeproj/project.pbxproj +++ b/SwiftyJSONAPI.xcodeproj/project.pbxproj @@ -172,25 +172,26 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Thomas Sunde Nielsen"; TargetAttributes = { E9D236D11BA2D40A00286911 = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0930; + LastSwiftMigration = 1020; }; E9D236DB1BA2D40A00286911 = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0930; + LastSwiftMigration = 1020; }; }; }; buildConfigurationList = E9D236CC1BA2D40A00286911 /* Build configuration list for PBXProject "SwiftyJSONAPI" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = E9D236C81BA2D40A00286911; productRefGroup = E9D236D31BA2D40A00286911 /* Products */; @@ -262,6 +263,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -310,7 +312,6 @@ SDKROOT = macosx; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - VALID_ARCHS = "i386 x86_64 armv7s armv7 arm64"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -320,6 +321,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -361,7 +363,6 @@ SDKROOT = macosx; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALID_ARCHS = "i386 x86_64 armv7s armv7 arm64"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -384,8 +385,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -405,8 +405,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.thomassnielsen.SwiftyJSONAPI; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_SWIFT3_OBJC_INFERENCE = On; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -422,8 +421,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks @loader_path/Frameworks @executable_path/Frameworks "; PRODUCT_BUNDLE_IDENTIFIER = com.thomassnielsen.SwiftyJSONAPITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -439,8 +437,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks @loader_path/Frameworks @executable_path/Frameworks "; PRODUCT_BUNDLE_IDENTIFIER = com.thomassnielsen.SwiftyJSONAPITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/SwiftyJSONAPI.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAPI.xcscheme b/SwiftyJSONAPI.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAPI.xcscheme index 889ee30..a3ab9ef 100644 --- a/SwiftyJSONAPI.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAPI.xcscheme +++ b/SwiftyJSONAPI.xcodeproj/xcshareddata/xcschemes/SwiftyJSONAPI.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 3 Jun 2019 18:04:32 +0200 Subject: [PATCH 6/7] Version bump --- SwiftyJSONAPI.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwiftyJSONAPI.podspec b/SwiftyJSONAPI.podspec index 81cf2bf..cb29321 100644 --- a/SwiftyJSONAPI.podspec +++ b/SwiftyJSONAPI.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "SwiftyJSONAPI" - s.version = "0.0.21" + s.version = "0.1.0" s.summary = "JSONAPI document representation and serializing in Swift." s.swift_version = "5.0" From b6afc95bae32f0ec7283b00490e223e9dfef6dce Mon Sep 17 00:00:00 2001 From: Dylan Pearce Date: Wed, 14 Jul 2021 04:02:43 -0400 Subject: [PATCH 7/7] Add Swift Package Manager Support (#16) --- Package.swift | 34 +++++ SwiftyJSONAPITests/JSONAPIDocumentTests.swift | 128 +++++++++--------- 2 files changed, 97 insertions(+), 65 deletions(-) create mode 100644 Package.swift diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..b1d4c33 --- /dev/null +++ b/Package.swift @@ -0,0 +1,34 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SwiftyJSONAPI", + platforms: [.macOS(.v10_10), + .iOS(.v9)], + products: [ + .library( + name: "SwiftyJSONAPI", + targets: ["SwiftyJSONAPI"]), + ], + targets: [ + .target( + name: "SwiftyJSONAPI", + dependencies: [], + path: "SwiftyJSONAPI", + exclude: ["Info.plist"]), + .testTarget( + name: "SwiftyJSONAPITests", + dependencies: ["SwiftyJSONAPI"], + path: "SwiftyJSONAPITests", + exclude: ["Info.plist"], + resources: [ + .copy("example-bidirectional-relationship.json"), + .copy("example-document-1.json"), + .copy("example-error.json") + ]), + + ], + swiftLanguageVersions: [.v5] +) diff --git a/SwiftyJSONAPITests/JSONAPIDocumentTests.swift b/SwiftyJSONAPITests/JSONAPIDocumentTests.swift index 844278d..1772275 100644 --- a/SwiftyJSONAPITests/JSONAPIDocumentTests.swift +++ b/SwiftyJSONAPITests/JSONAPIDocumentTests.swift @@ -9,80 +9,89 @@ import XCTest @testable import SwiftyJSONAPI -class JSONAPIDocumentTests: XCTestCase { - - var testData: Data! - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - if let file = Bundle(for: JSONAPIDocumentTests.self).path(forResource: "example-document-1", ofType: "json") { - self.testData = try? Data(contentsOf: URL(fileURLWithPath: file)) - } else { - XCTFail("Could not find test file") +final class JSONAPIDocumentTests: XCTestCase { + + private func fetchDocument(for resource: String) -> JSONAPIDocument? { + #if SWIFT_PACKAGE + guard let url = Bundle.module.url(forResource: resource, withExtension: nil) else { + XCTFail() + return nil } - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() + #else + guard let file = Bundle(for: JSONAPIDocumentTests.self).path(forResource: resource, ofType: nil) else { + XCTFail() + return nil + } + let url = URL(fileURLWithPath: file) + #endif + let testData = try! Data(contentsOf: url) + return try? JSONAPIDocument(testData) } func testImportingDocument() { - let document = try! JSONAPIDocument(self.testData) - + guard let document = fetchDocument(for: "example-document-1.json") else { + XCTFail() + return + } + XCTAssert(document.data.count == 1, "Expected number of data elements to be 1, was \(document.data.count)") XCTAssert(document.included.count == 3, "Expected number of included documents to be 2, was \(document.included.count)") XCTAssert(document.links.count == 3, "Expected number of links to be 3, was \(document.links.count)") - + XCTAssertNotNil(document.url, "Expected document to find its own URL from the provided links") } - + func testRelationships() { - let document = try! JSONAPIDocument(self.testData) + guard let document = fetchDocument(for: "example-document-1.json") else { + XCTFail() + return + } let resource = document.data.first! - + XCTAssertNotNil(resource.url, "Resources should have an URL") XCTAssert(resource.relationships.count == 2, "Expected number of relationships to be 2, was \(resource.relationships.count)") } - + func testErrors() { - - if let errorFile = Bundle(for: JSONAPIDocumentTests.self).path(forResource: "example-error", ofType: "json") { - self.testData = try? Data(contentsOf: URL(fileURLWithPath: errorFile)) - } else { - XCTFail("Could not find error test file") + + guard let document = fetchDocument(for: "example-error.json") else { + XCTFail() + return } - - let document = try! JSONAPIDocument(self.testData) let error = document.errors.first! - + XCTAssertNotNil(error.id, "Errors should have an id") XCTAssertEqual(error.status,"422", "Expected error code to be 422") - + } - + func testMeta() { - let document = try! JSONAPIDocument(self.testData) + guard let document = fetchDocument(for: "example-document-1.json") else { + XCTFail() + return + } let meta = document.meta! let keys = [String](meta.keys) - - XCTAssertNotNil(meta, "document should have meta information") + + XCTAssertNotNil(meta, "document should have meta information") XCTAssertTrue(keys.contains("authors"),"meta should contain a authors key") - + } - + func testResourcesLoadedFromInclude() { - let document = try! JSONAPIDocument(self.testData) + guard let document = fetchDocument(for: "example-document-1.json") else { + XCTFail() + return + } var authorAttributesCount = 0 var commentsAttributesCount = 0 - + document.loadIncludedResources() - + guard let postResource = document.data.first else { XCTFail("Could not find resource of type Post"); return } - + postResource.relationships.forEach { relationship in switch relationship.type { case "author": @@ -94,30 +103,28 @@ class JSONAPIDocumentTests: XCTestCase { break } } - + XCTAssertTrue(authorAttributesCount == 3,"Author resource should contain 3 attributes") XCTAssertTrue(commentsAttributesCount == 1,"Comment resource should contain 1 attribute") } - - func testbidirectionalRelationship() { - if let bidirectionalFile = Bundle(for: JSONAPIDocumentTests.self).path(forResource: "example-bidirectional-relationship", ofType: "json") { - self.testData = try? Data(contentsOf: URL(fileURLWithPath: bidirectionalFile)) - } else { - XCTFail("Could not find error test file") + + func testBidirectionalRelationship() { + + guard let document = fetchDocument(for: "example-bidirectional-relationship.json") else { + XCTFail() + return } - var userHasAdressRelationship = false var addressHasUserRelationship = false - - let document = try! JSONAPIDocument(self.testData) + document.loadIncludedResources() - + let resource = document.data.first - + resource?.relationships.forEach { relationship in switch relationship.type { case "user": - userHasAdressRelationship = relationship.hasRelationship(toType: "address") + userHasAdressRelationship = relationship.hasRelationship(toType: "address") case "address": addressHasUserRelationship = relationship.hasRelationship(toType: "user") default: @@ -125,19 +132,10 @@ class JSONAPIDocumentTests: XCTestCase { break } } - + XCTAssertTrue(userHasAdressRelationship, "Expected user to have a relationship to addess") XCTAssertTrue(addressHasUserRelationship, "Expected address to have a relationship to a user") } - -// - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure { - _ = try! JSONAPIDocument(self.testData) - } - } - } private extension JSONAPIRelationship {