From 0f25890a08753e0997cf762354212e51f8fcf1dc Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Wed, 11 Sep 2019 18:09:33 -0700 Subject: [PATCH 01/12] test: checking if the version is present inside the user-agent header --- Kinvey/KinveyTests/NetworkStoreTests.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Kinvey/KinveyTests/NetworkStoreTests.swift b/Kinvey/KinveyTests/NetworkStoreTests.swift index 13abe5fb5..df9770210 100644 --- a/Kinvey/KinveyTests/NetworkStoreTests.swift +++ b/Kinvey/KinveyTests/NetworkStoreTests.swift @@ -2706,7 +2706,12 @@ class NetworkStoreTests: StoreTestCase { XCTAssertLessThanOrEqual(textCheckingResult.numberOfRanges, 4) if textCheckingResult.numberOfRanges > 1 { let majorVersion = kinveySdkVersion.substring(with: textCheckingResult.range(at: 1)) - XCTAssertEqual(majorVersion, "3") + let minorVersion = kinveySdkVersion.substring(with: textCheckingResult.range(at: 2)) + let patchVersion = kinveySdkVersion.substring(with: textCheckingResult.range(at: 3)) + let shortVersions = (Bundle(for: Client.self).infoDictionary?["CFBundleShortVersionString"] as? String)?.split(separator: ".").map { String($0) } + XCTAssertEqual(majorVersion, shortVersions?[0]) + XCTAssertEqual(minorVersion, shortVersions?[1]) + XCTAssertEqual(patchVersion, shortVersions?[2]) } } } From 5f9b92233282a7ba849178ab5614a007be3a970b Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Fri, 13 Sep 2019 13:53:37 -0700 Subject: [PATCH 02/12] fix: MLIBZ-3133, Missing JSON Content-Type HTTP Header (#371) * fix: MLIBZ-3133, Missing JSON Content-Type HTTP Header * refactor: MLIBZ-3133, reusing the code to set body and content-type header --- Kinvey/Kinvey/HttpRequest.swift | 104 +++++++++++++++++---- Kinvey/Kinvey/HttpResponse.swift | 2 +- Kinvey/Kinvey/RealmSync.swift | 4 +- Kinvey/KinveyTests/KinveyURLProtocol.swift | 1 + 4 files changed, 88 insertions(+), 23 deletions(-) diff --git a/Kinvey/Kinvey/HttpRequest.swift b/Kinvey/Kinvey/HttpRequest.swift index 42225ea7a..7b01f9a04 100644 --- a/Kinvey/Kinvey/HttpRequest.swift +++ b/Kinvey/Kinvey/HttpRequest.swift @@ -14,9 +14,43 @@ import Foundation import WatchKit #endif -struct HeaderField { +enum Encoding: String { - static let userAgent = "User-Agent" + case utf8 = "utf-8" + +} + +enum MimeType: String { + + case applicationJson = "application/json" + case applicationXWWWFormURLEncoded = "application/x-www-form-urlencoded" + +} + +struct MimeTypeCharset { + + let mimeType: MimeType + let encoding: Encoding + + init(_ mimeType: MimeType) { + self.init(mimeType: mimeType) + } + + init(mimeType: MimeType, encoding: Encoding = .utf8) { + self.mimeType = mimeType + self.encoding = encoding + } + + var value: String { + return "\(mimeType.rawValue); charset=\(encoding.rawValue)" + } + +} + +enum HeaderField: String { + + case userAgent = "User-Agent" + case contentType = "Content-Type" } @@ -106,7 +140,7 @@ enum HttpHeader { case .requestId: return KinveyHeaderField.requestId.rawValue case .userAgent: - return HeaderField.userAgent + return HeaderField.userAgent.rawValue case .deviceInfo: return KinveyHeaderField.deviceInfo.rawValue } @@ -174,6 +208,46 @@ extension URLRequest { addValue(value, forHTTPHeaderField: header.rawValue) } + mutating func setValue(_ value: Value?, forHTTPHeaderField header: Header) where Header.RawValue == String, Value.RawValue == String { + setValue(value?.rawValue, forHTTPHeaderField: header.rawValue) + } + + mutating func addValue(_ value: Value, forHTTPHeaderField header: Header) where Header.RawValue == String, Value.RawValue == String { + addValue(value.rawValue, forHTTPHeaderField: header.rawValue) + } + + mutating func setValue(_ mimeType: MimeTypeCharset?) { + setValue(mimeType?.value, forHTTPHeaderField: HeaderField.contentType) + } + + mutating func addValue(_ mimeType: MimeTypeCharset) { + addValue(mimeType.value, forHTTPHeaderField: HeaderField.contentType) + } + + mutating func setBody(json: JsonDictionary) throws { + setValue(MimeTypeCharset(.applicationJson)) + httpBody = try JSONSerialization.data(withJSONObject: json) + } + + mutating func setBody(json: [JsonDictionary]) throws { + setValue(MimeTypeCharset(.applicationJson)) + httpBody = try JSONSerialization.data(withJSONObject: json) + } + + mutating func setBody(xWWWFormURLEncoded: [String : String]) { + setValue(MimeTypeCharset(.applicationXWWWFormURLEncoded)) + var paramsKeyValue = [String]() + for (key, value) in xWWWFormURLEncoded { + if let key = key.stringByAddingPercentEncodingForFormData(), + let value = value.stringByAddingPercentEncodingForFormData() + { + paramsKeyValue.append("\(key)=\(value)") + } + } + let httpBody = paramsKeyValue.joined(separator: "&") + self.httpBody = httpBody.data(using: .utf8) + } + func value(forHTTPHeaderField header: Header) -> String? where Header.RawValue == String { return value(forHTTPHeaderField: header.rawValue) } @@ -231,25 +305,17 @@ public var restApiVersion = defaultRestApiVersion enum Body { case json(json: JsonDictionary) + case jsonArray(json: [JsonDictionary]) case formUrlEncoded(params: [String : String]) func attachTo(request: inout URLRequest) { switch self { case .json(let json): - request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") - request.httpBody = try! JSONSerialization.data(withJSONObject: json) + try! request.setBody(json: json) + case .jsonArray(let jsonArray): + try! request.setBody(json: jsonArray) case .formUrlEncoded(let params): - request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type") - var paramsKeyValue = [String]() - for (key, value) in params { - if let key = key.stringByAddingPercentEncodingForFormData(), - let value = value.stringByAddingPercentEncodingForFormData() - { - paramsKeyValue.append("\(key)=\(value)") - } - } - let httpBody = paramsKeyValue.joined(separator: "&") - request.httpBody = httpBody.data(using: .utf8) + request.setBody(xWWWFormURLEncoded: params) } } @@ -532,13 +598,11 @@ internal class HttpRequest: TaskProgressRequest, Request { } func setBody(json: [String : Any]) { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - request.httpBody = try! JSONSerialization.data(withJSONObject: json) + try! request.setBody(json: json) } func setBody(json: [[String : Any]]) { - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - request.httpBody = try! JSONSerialization.data(withJSONObject: json) + try! request.setBody(json: json) } } diff --git a/Kinvey/Kinvey/HttpResponse.swift b/Kinvey/Kinvey/HttpResponse.swift index da7060b40..3ebd4a116 100644 --- a/Kinvey/Kinvey/HttpResponse.swift +++ b/Kinvey/Kinvey/HttpResponse.swift @@ -67,7 +67,7 @@ struct HttpResponse: Response { } var contentTypeIsJson: Bool { - guard let contentType = allHeaderFields?["content-type"] as? String else { + guard let contentType = (allHeaderFields?["content-type"] as? String) ?? (allHeaderFields?["Content-Type"] as? String) else { return false } return contentType == "application/json" || contentType.hasPrefix("application/json;") diff --git a/Kinvey/Kinvey/RealmSync.swift b/Kinvey/Kinvey/RealmSync.swift index 3c4c6201c..a5bdc72a9 100644 --- a/Kinvey/Kinvey/RealmSync.swift +++ b/Kinvey/Kinvey/RealmSync.swift @@ -152,14 +152,14 @@ class RealmSync: SyncType where T: NSObject { let urls = Set(result.urls) guard urls.count == 1, let url = urls.first, - let data = try? JSONSerialization.data(withJSONObject: result.jsonArray) + JSONSerialization.isValidJSONObject(result.jsonArray) else { return } var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" urlRequest.setValue(UUID().uuidString, forHTTPHeaderField: KinveyHeaderField.requestId) - urlRequest.httpBody = data + try! urlRequest.setBody(json: result.jsonArray) results.append( RealmPendingOperation( request: urlRequest, diff --git a/Kinvey/KinveyTests/KinveyURLProtocol.swift b/Kinvey/KinveyTests/KinveyURLProtocol.swift index 9eb738349..6109709d6 100644 --- a/Kinvey/KinveyTests/KinveyURLProtocol.swift +++ b/Kinvey/KinveyTests/KinveyURLProtocol.swift @@ -166,6 +166,7 @@ class KinveyURLProtocol: URLProtocol { switch httpMethod { case "POST": + XCTAssertEqual(request.allHTTPHeaderFields?["Content-Type"] as? String, "application/json; charset=utf-8") let json = try! JSONSerialization.jsonObject(with: request) let kinveyApiVersion = request.allHTTPHeaderFields?["X-Kinvey-API-Version"] if var json = json as? [String : Any] { From e620c61b9a04ec800468b90fa03b55c727868e98 Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Mon, 16 Sep 2019 18:00:46 -0700 Subject: [PATCH 03/12] fix: MLIBZ-3146, fixing return when an entire batch fails --- Kinvey/Kinvey/SaveMultiOperation.swift | 29 ++++++++++---- Kinvey/KinveyTests/MultiInsertSpec.swift | 48 ++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/Kinvey/Kinvey/SaveMultiOperation.swift b/Kinvey/Kinvey/SaveMultiOperation.swift index 2dfe7c427..0598a0a88 100644 --- a/Kinvey/Kinvey/SaveMultiOperation.swift +++ b/Kinvey/Kinvey/SaveMultiOperation.swift @@ -268,7 +268,7 @@ internal class SaveMultiOperation: WriteOperation, requests: MultiRequest) -> Promise { var offsetIterator = stride(from: 0, to: persistable.count, by: maxSizePerRequest).makeIterator() - let promisesIterator = AnyIterator> { + let promisesIterator = AnyIterator> { guard let offset = offsetIterator.next() else { return nil } @@ -276,7 +276,12 @@ internal class SaveMultiOperation: WriteOperation Guarantee in + return Guarantee.value(.success(( + entities: AnyRandomAccessCollection(Array(repeating: nil, count: slice.count)), + errors: AnyRandomAccessCollection((0 ..< slice.count).map({ IndexedError(index: $0, error: error) })) + ))) + }) } let urlSessionConfiguration = options?.urlSession?.configuration ?? client.urlSession.configuration return when(fulfilled: promisesIterator, concurrently: urlSessionConfiguration.httpMaximumConnectionsPerHost).map(on: DispatchQueue.global(qos: .background)) { results -> ResultType in @@ -285,15 +290,23 @@ internal class SaveMultiOperation: WriteOperation Date: Fri, 20 Sep 2019 10:57:24 -0700 Subject: [PATCH 04/12] test: MLIBZ-3134, checking if all properties are sent correctly (#373) * test: MLIBZ-3134, checking if all properties are sent correctly * test: MLIBZ-3134, reverting wrong commit --- Kinvey/Kinvey.xcodeproj/project.pbxproj | 4 +++ Kinvey/KinveyTests/Book.swift | 9 ++++++ Kinvey/KinveyTests/MultiInsertSpec.swift | 38 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/Kinvey/Kinvey.xcodeproj/project.pbxproj b/Kinvey/Kinvey.xcodeproj/project.pbxproj index 0bf3cc014..ec12de31f 100644 --- a/Kinvey/Kinvey.xcodeproj/project.pbxproj +++ b/Kinvey/Kinvey.xcodeproj/project.pbxproj @@ -276,6 +276,8 @@ 578B80721EE746EF004D92A6 /* SyncStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5753BB3B1C23F29000EB9D3A /* SyncStoreTests.swift */; }; 578B80741EE74E46004D92A6 /* PubNub.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57E6BD001EC51F80000E5C52 /* PubNub.framework */; }; 578B80761EE876C5004D92A6 /* UserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57E1C3AC1C17EC9500578974 /* UserTests.swift */; }; + 578D9152233190BF0001152E /* Book.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572005C91D342B2800AE9AC5 /* Book.swift */; }; + 578D9153233190C20001152E /* Book.swift in Sources */ = {isa = PBXBuildFile; fileRef = 572005C91D342B2800AE9AC5 /* Book.swift */; }; 578D9FE41E8DE53900C2B280 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57BEAE2E1C98805E00479206 /* QuartzCore.framework */; }; 578D9FE51E8DE53900C2B280 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57BEAE2C1C98805600479206 /* CoreGraphics.framework */; }; 578D9FE61E8DE53900C2B280 /* Kinvey.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57A27C811C178F17000DF951 /* Kinvey.framework */; }; @@ -3342,6 +3344,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 578D9153233190C20001152E /* Book.swift in Sources */, 57529845226FB1AD002FA614 /* Person.swift in Sources */, 57529847226FB1E4002FA614 /* KinveyTestCase.swift in Sources */, 57529846226FB1C6002FA614 /* KinveyURLProtocol.swift in Sources */, @@ -3356,6 +3359,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 578D9152233190BF0001152E /* Book.swift in Sources */, 5752988E226FBADB002FA614 /* MockKinveyBackend.swift in Sources */, 5752988F226FBAFC002FA614 /* KinveyURLProtocol.swift in Sources */, 576B08DA22AEEE8800C22C95 /* MultiInsertSpec.swift in Sources */, diff --git a/Kinvey/KinveyTests/Book.swift b/Kinvey/KinveyTests/Book.swift index 66d26ee4c..367df2e8d 100644 --- a/Kinvey/KinveyTests/Book.swift +++ b/Kinvey/KinveyTests/Book.swift @@ -46,6 +46,15 @@ class Book: Entity { } +extension Book { + + convenience init(_ block: (Book) -> Void) { + self.init() + block(self) + } + +} + class BookEdition: Object, JSONDecodable, Mappable { convenience required init?(map: Map) { diff --git a/Kinvey/KinveyTests/MultiInsertSpec.swift b/Kinvey/KinveyTests/MultiInsertSpec.swift index 936186f0e..a311c97d6 100644 --- a/Kinvey/KinveyTests/MultiInsertSpec.swift +++ b/Kinvey/KinveyTests/MultiInsertSpec.swift @@ -1776,6 +1776,44 @@ class MultiInsertSpec: QuickSpec { expect(autoDataStore.pendingSyncCount()).to(equal(0)) expect(autoDataStore.pendingSyncEntities().count).to(equal(0)) } + it("push 2 new items") { + let books = [ + Book { $0.title = "This 1 book" }, + Book { $0.title = "This 2 book" }, + ] + + var postCount = 0 + mockResponse { request in + switch request.httpMethod { + case "POST": + postCount += 1 + expect(request.allHTTPHeaderFields?["Content-Type"] as? String).to(equal("application/json; charset=utf-8")) + let json = try! JSONSerialization.jsonObject(with: request) + expect(json is [[String : Any]]).to(beTrue()) + if let jsonArray = json as? [[String : Any]] { + expect(jsonArray.count).to(equal(books.count)) + expect(jsonArray.first?["title"] as? String).to(equal(books.first?.title)) + expect(jsonArray.last?["title"] as? String).to(equal(books.last?.title)) + } + fallthrough + default: + return HttpResponse(request: request, urlProcotolType: KinveyURLProtocol.self) + } + } + defer { + setURLProtocol(nil) + expect(postCount).to(equal(1)) + } + + let syncDataStore = try DataStore.collection(type: .sync) + let result = kinveySaveMulti(dataStore: syncDataStore, entities: books).result + + expect(result?.entities.count).to(equal(books.count)) + expect(result?.errors.count).to(equal(0)) + + let pushCount = kinveyPush(dataStore: syncDataStore).count + expect(pushCount).to(equal(UInt(books.count))) + } } context("Sync()") { it("create an array of 3 items, the second of which has invalid _geoloc parameters") { From 2d212b4a4a713e0e15a46e6ba987524c31b5e096 Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Mon, 23 Sep 2019 14:20:14 -0700 Subject: [PATCH 05/12] chore: update MongoDBPredicateAdapter --- .../MongoDBPredicateAdaptor/MongoDBPredicateAdaptor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Carthage/Checkouts/NSPredicate-MongoDB-Adaptor/Sources/MongoDBPredicateAdaptor/MongoDBPredicateAdaptor.swift b/Carthage/Checkouts/NSPredicate-MongoDB-Adaptor/Sources/MongoDBPredicateAdaptor/MongoDBPredicateAdaptor.swift index 8e98ae510..81f14005d 100644 --- a/Carthage/Checkouts/NSPredicate-MongoDB-Adaptor/Sources/MongoDBPredicateAdaptor/MongoDBPredicateAdaptor.swift +++ b/Carthage/Checkouts/NSPredicate-MongoDB-Adaptor/Sources/MongoDBPredicateAdaptor/MongoDBPredicateAdaptor.swift @@ -435,7 +435,7 @@ extension NSPredicate { extension NSComparisonPredicate { - var keyPathConstantTuple: (keyPathExpression: NSExpression, constantValueExpression: NSExpression)? { + public var keyPathConstantTuple: (keyPathExpression: NSExpression, constantValueExpression: NSExpression)? { switch leftExpression.expressionType { case .keyPath: switch rightExpression.expressionType { From 0d205cde722fb65c30f4d3a7a7326f010827f6bb Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Mon, 23 Sep 2019 14:20:35 -0700 Subject: [PATCH 06/12] chore: update dependencies --- Cartfile.resolved | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 35de0f9e9..7de5ec8d5 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,12 +1,12 @@ github "Hearst-DD/ObjectMapper" "3.5.1" github "Quick/Nimble" "v8.0.4" -github "Quick/Quick" "v2.1.0" +github "Quick/Quick" "v2.2.0" github "SwiftyBeaver/SwiftyBeaver" "1.7.1" github "httpswift/swifter" "70355c4e414e93a0589a0d5d4ade342534bbab38" github "kif-framework/KIF" "v3.7.8" github "kishikawakatsumi/KeychainAccess" "v3.2.0" github "mxcl/PromiseKit" "6.11.0" github "pubnub/objective-c" "v4.10.1" -github "realm/realm-cocoa" "v3.17.3" -github "tjboneman/NSPredicate-MongoDB-Adaptor" "4541dc76f9a24d69416544072e07ac945a40bf9a" +github "realm/realm-cocoa" "v3.18.0" +github "tjboneman/NSPredicate-MongoDB-Adaptor" "fce0cd01913bd4393db0c3dd33404cb7e9ebec88" github "weichsel/ZIPFoundation" "0.9.9" From 497325850827008edb96f3fd5d86995e5840d775 Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Thu, 26 Sep 2019 13:08:03 -0700 Subject: [PATCH 07/12] fix: MLIBZ-3141, auto datastore now handling network fails correctly (#374) * fix: MLIBZ-3141, auto datastore now handling network fails correctly * test: MLIBZ-3141, removing the invalid geolocation since it was not the point of failure in the test * fix: MLIBZ-3141, fixing the empty array test * chore: MLIBZ-3141, update MongoDBPredicateAdapter * chore: MLIBZ-3141, update dependencies * chore: MLIBZ-3141, updating Cirrus CI * chore: MLIBZ-3141, updating Travis CI * chore: MLIBZ-3141, updating iOS Simulator Destination * chore: MLIBZ-3141, reverting Xcode 11, going back to Xcode 10.3 for now * chore: MLIBZ-3141, fixing Makefile * chore: MLIBZ-3141, fixing Makefile * chore: MLIBZ-3141, fixing Travis CI * chore: MLIBZ-3141, fixing Cirrus CI --- .cirrus.yml | 8 +-- .travis.yml | 6 +- Kinvey/Kinvey/SaveMultiOperation.swift | 16 ++++- Kinvey/Kinvey/SaveOperation.swift | 10 ++- Kinvey/Kinvey/WriteOperation.swift | 73 ++++++++++++++++++++++ Kinvey/KinveyTests/AutoDataStoreSpec.swift | 57 +++++++---------- Kinvey/KinveyTests/MultiInsertSpec.swift | 37 +++++------ Makefile | 16 +++-- 8 files changed, 158 insertions(+), 65 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 087578c95..e9defce75 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,8 +1,8 @@ task: name: macOS osx_instance: - image: mojave-xcode-10.2 - download_dependencies_script: make travisci-cache + image: mojave-xcode-11 + download_dependencies_script: make cache brew_update_script: brew update install_carthage_script: brew install carthage xcode_version_script: xcodebuild -version @@ -11,8 +11,8 @@ task: task: name: iOS osx_instance: - image: mojave-xcode-10.2 - download_dependencies_script: make travisci-cache + image: mojave-xcode-11 + download_dependencies_script: make cache brew_update_script: brew update install_carthage_script: brew install carthage xcode_version_script: xcodebuild -version diff --git a/.travis.yml b/.travis.yml index 5238ca87e..eb383d426 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode10.2 +osx_image: xcode10.3 cache: directories: - Carthage @@ -24,7 +24,7 @@ before_script: - carthage version - xcpretty --version - if [ ! -d $( md5 Cartfile.resolved | awk '{ print "Carthage/" $4 ".zip" }' ) ]; then - make travisci-cache; + make cache; fi - if [ ! -d "Carthage/Checkouts/CwlPreconditionTesting" ] || [ ! -d "Carthage/Checkouts/KeychainAccess" ] || [ ! -d "Carthage/Checkouts/KIF" ] || [ ! -d "Carthage/Checkouts/ObjectMapper" ] || [ ! -d "Carthage/Checkouts/PromiseKit" ] || [ ! -d "Carthage/Checkouts/realm-cocoa" ]; then carthage checkout; @@ -87,4 +87,4 @@ env: - secure: nawAGSUbPzyAH/SllDj9q6IOLGaF91DQsudQYx4AJs+swwFhAvAe3hM6vWdGVuDLxqVHQ4+4AAQFecXq/mDi5WtRISPbGHWVtOx7Q6szL8Y54uZKVmKV06wnAo4nrwu8pp1+TbRLYwG+/oJIfabW2yuMgNn7nWFm5SdE0GuduVI7Ho9p0/SeaE7DCtaNKgyCLfspAA8svCYMK0N9NzBVhkTPzWRiIF174k5VE28lZox/fjN5x4j1aaMBUhElkJELjcWKdTX11MnCyybWjJZ1YTMK/A4vBtZCFmHIFuhtQiqWCQIWxeo8axRDBZEMzZ5U+9zSfaz0w0wovWI/cvtRFS0j/7UQ4o6alO7EOMdhH5rRl8atOxSS+Rl81Oz1kZiLhjJa/feAN5QGQ423L4CyfDeEBV6t1D8Cmb1jlficswFeX2rQw82qFnI2ua9p8HrpUJydDsGR6AoOI+KUamwi53OC+hsG/M1sA4MOAPEJoMGT6dyER5UVE63JB45All9TDJWV2EZz+11FQIp6P/62/QXJBQhqxu+W0u/3q7KqoSgmxFx/QSbv8hpK9aJWDQNf5cv02bT+vJnMv4Lrf+XcSVOWH0TwpL5nVcRJXyq2A6FCGdE2S0Xa0+KkgZdF7p3qk4jN32CryHImRp8T3qbkA6Q9nNdxATt7P9OjYl/XqDA= matrix: - PLATFORM=Mac PLATFORM_ALIAS=osx - - PLATFORM=iOS PLATFORM_ALIAS=ios + - PLATFORM=iOS PLATFORM_ALIAS=ios DESTINATION_OS=12.4 DESTINATION_NAME="iPhone X" diff --git a/Kinvey/Kinvey/SaveMultiOperation.swift b/Kinvey/Kinvey/SaveMultiOperation.swift index 0598a0a88..6060a9fe6 100644 --- a/Kinvey/Kinvey/SaveMultiOperation.swift +++ b/Kinvey/Kinvey/SaveMultiOperation.swift @@ -13,7 +13,7 @@ private let maxSizePerRequest = 100 public typealias MultiSaveResultTuple = (entities: AnyRandomAccessCollection, errors: AnyRandomAccessCollection) -internal class SaveMultiOperation: WriteOperation>, WriteOperationType where T: NSObject { +internal class SaveMultiOperation: WriteOperation> where T: NSObject { let persistable: AnyRandomAccessCollection let isNewItems: AnyRandomAccessCollection @@ -318,3 +318,17 @@ internal class SaveMultiOperation: WriteOperation { + let entities: [T?] = persistable.map { (entity) -> T? in + return entity + } + return MultiSaveResultTuple( + entities: AnyRandomAccessCollection(entities), + errors: AnyRandomAccessCollection([]) + ) + } + +} diff --git a/Kinvey/Kinvey/SaveOperation.swift b/Kinvey/Kinvey/SaveOperation.swift index d4acc532b..38f604fe0 100644 --- a/Kinvey/Kinvey/SaveOperation.swift +++ b/Kinvey/Kinvey/SaveOperation.swift @@ -8,7 +8,7 @@ import Foundation -internal class SaveOperation: WriteOperation, WriteOperationType where T: NSObject { +internal class SaveOperation: WriteOperation where T: NSObject { var persistable: T @@ -118,3 +118,11 @@ internal class SaveOperation: WriteOperation, WriteOperati } } + +extension SaveOperation : SaveOperationType { + + var localSuccess: T { + return persistable + } + +} diff --git a/Kinvey/Kinvey/WriteOperation.swift b/Kinvey/Kinvey/WriteOperation.swift index 245d4addb..be0983f3c 100644 --- a/Kinvey/Kinvey/WriteOperation.swift +++ b/Kinvey/Kinvey/WriteOperation.swift @@ -31,6 +31,50 @@ internal class WriteOperation: Operation where T: NSObject } +protocol SaveOperationType: WriteOperationType { + + var localSuccess: SuccessType { get } + +} + +extension SaveOperationType { + + func execute(_ completionHandler: CompletionHandler?) -> AnyRequest> { + switch writePolicy { + case .silentLocalThenNetwork: + let multiRequest = MultiRequest>() + executeLocal { + switch $0 { + case .success: + multiRequest += self.executeNetwork { + switch $0 { + case .success(let success): + completionHandler?(.success(success)) + case .failure(let failure): + if let error = failure as? Kinvey.Error, + let httpResponse = error.httpResponse, + httpResponse.statusCode == 401 + { + completionHandler?(.failure(failure)) + return + } + log.error(failure) + completionHandler?(.success(self.localSuccess)) + } + } + case .failure: + multiRequest.result = $0 + completionHandler?($0) + } + } + return AnyRequest(multiRequest) + default: + return AnyWriteOperationType(self).execute(completionHandler) + } + } + +} + protocol WriteOperationType { associatedtype SuccessType @@ -66,3 +110,32 @@ extension WriteOperationType { } } + +class AnyWriteOperationType : WriteOperationType where Failure: Swift.Error { + + typealias SuccessType = Success + typealias FailureType = Failure + + var writePolicy: WritePolicy { + return _getWritePolicy() + } + + private let _getWritePolicy: () -> WritePolicy + private let _executeLocal: (CompletionHandler?) -> AnyRequest> + private let _executeNetwork: (CompletionHandler?) -> AnyRequest> + + init(_ instance: T) where T: WriteOperationType, T.SuccessType == Success, T.FailureType == Failure { + _getWritePolicy = { instance.writePolicy } + _executeLocal = instance.executeLocal(_:) + _executeNetwork = instance.executeNetwork(_:) + } + + func executeLocal(_ completionHandler: CompletionHandler?) -> AnyRequest> { + return _executeLocal(completionHandler) + } + + func executeNetwork(_ completionHandler: CompletionHandler?) -> AnyRequest> { + return _executeNetwork(completionHandler) + } + +} diff --git a/Kinvey/KinveyTests/AutoDataStoreSpec.swift b/Kinvey/KinveyTests/AutoDataStoreSpec.swift index 8a8067445..ac2c7e28f 100644 --- a/Kinvey/KinveyTests/AutoDataStoreSpec.swift +++ b/Kinvey/KinveyTests/AutoDataStoreSpec.swift @@ -1131,13 +1131,12 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(nil) } - var error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + var entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) expect(kinveyFind(dataStore: autoDataStore).entities?.count).to(equal(1)) - error = kinveyFind(dataStore: networkDataStore).error as? NSError + let error = kinveyFind(dataStore: networkDataStore).error as? NSError expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) @@ -1162,13 +1161,11 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - var error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + var entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) - error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) let pendingSyncEntities = autoDataStore.pendingSyncEntities() expect(pendingSyncEntities.count).to(equal(2)) @@ -1177,7 +1174,7 @@ class AutoDataStoreSpec: QuickSpec { expect(kinveyFind(dataStore: autoDataStore).entities?.count).to(equal(2)) - error = kinveyFind(dataStore: networkDataStore).error as? NSError + let error = kinveyFind(dataStore: networkDataStore).error as? NSError expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) } @@ -1240,13 +1237,12 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(nil) } - var error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + var entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) expect(kinveyFind(dataStore: autoDataStore).entities?.count).to(equal(1)) - error = kinveyFind(dataStore: networkDataStore).error as? NSError + let error = kinveyFind(dataStore: networkDataStore).error as? NSError expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) @@ -1271,13 +1267,11 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - var error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + var entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) - error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) let pendingSyncEntities = autoDataStore.pendingSyncEntities() expect(pendingSyncEntities.count).to(equal(2)) @@ -1286,7 +1280,7 @@ class AutoDataStoreSpec: QuickSpec { expect(kinveyFind(dataStore: autoDataStore).entities?.count).to(equal(2)) - error = kinveyFind(dataStore: networkDataStore).error as? NSError + let error = kinveyFind(dataStore: networkDataStore).error as? NSError expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) } @@ -1349,13 +1343,12 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(nil) } - var error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + var entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) expect(kinveyFind(dataStore: autoDataStore).entities?.count).to(equal(1)) - error = kinveyFind(dataStore: networkDataStore).error as? NSError + let error = kinveyFind(dataStore: networkDataStore).error as? NSError expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) @@ -1380,13 +1373,11 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - var error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + var entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) - error = kinveySave(dataStore: autoDataStore).error as? NSError - expect(error?.domain).to(equal(NSURLErrorDomain)) - expect(error?.code).to(equal(NSURLErrorTimedOut)) + entity = kinveySave(dataStore: autoDataStore).entity + expect(entity).toNot(beNil()) let pendingSyncEntities = autoDataStore.pendingSyncEntities() expect(pendingSyncEntities.count).to(equal(2)) @@ -1395,7 +1386,7 @@ class AutoDataStoreSpec: QuickSpec { expect(kinveyFind(dataStore: autoDataStore).entities?.count).to(equal(2)) - error = kinveyFind(dataStore: networkDataStore).error as? NSError + let error = kinveyFind(dataStore: networkDataStore).error as? NSError expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) } diff --git a/Kinvey/KinveyTests/MultiInsertSpec.swift b/Kinvey/KinveyTests/MultiInsertSpec.swift index a311c97d6..391f857d0 100644 --- a/Kinvey/KinveyTests/MultiInsertSpec.swift +++ b/Kinvey/KinveyTests/MultiInsertSpec.swift @@ -1133,11 +1133,11 @@ class MultiInsertSpec: QuickSpec { defer { setURLProtocol(nil) } - let error = kinveySave( + let entity = kinveySave( dataStore: autoDataStore, - entity: Person { $0.geolocation = GeoPoint(latitude: -300, longitude: -300) } - ).error - expect(error?.localizedDescription).to(equal(timeoutError.localizedDescription)) + entity: Person { $0.name = UUID().uuidString } + ).entity + expect(entity).toNot(beNil()) let entitites = kinveyFind(dataStore: syncDataStore).entities expect(entitites?.count).to(equal(1)) @@ -1546,9 +1546,9 @@ class MultiInsertSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - let error = kinveySaveMulti(dataStore: autoDataStore, entities: Person(), Person()).error - expect(error).toNot(beNil()) - expect(error?.localizedDescription).to(equal(timeoutError.localizedDescription)) + let result = kinveySaveMulti(dataStore: autoDataStore, entities: Person(), Person()).result + expect(result).toNot(beNil()) + expect(result?.entities.count).to(equal(2)) } catch { fail(error.localizedDescription) } @@ -1573,12 +1573,12 @@ class MultiInsertSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - let error = kinveySaveMulti( + let result = kinveySaveMulti( dataStore: autoDataStore, entities: Person(), Person { $0.entityId = UUID().uuidString } - ).error - expect(error).toNot(beNil()) - expect(error?.localizedDescription).to(equal(timeoutError.localizedDescription)) + ).result + expect(result).toNot(beNil()) + expect(result?.entities.count).to(equal(2)) } catch { fail(error.localizedDescription) } @@ -1618,12 +1618,12 @@ class MultiInsertSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - let error = kinveySaveMulti( + let result = kinveySaveMulti( dataStore: autoDataStore, entities: Person(), Person { $0.entityId = UUID().uuidString } - ).error - expect(error).toNot(beNil()) - expect(error?.localizedDescription).to(equal(timeoutError.localizedDescription)) + ).result + expect(result).toNot(beNil()) + expect(result?.entities.count).to(equal(2)) } catch { fail(error.localizedDescription) } @@ -1878,15 +1878,16 @@ class MultiInsertSpec: QuickSpec { expect(postCount).to(equal(2)) } - let error = kinveySaveMulti( + let result = kinveySaveMulti( dataStore: autoDataStore, entities: [ Person { $0.geolocation = GeoPoint(latitude: 0, longitude: 0) }, Person { $0.geolocation = GeoPoint(latitude: -300, longitude: -300) }, Person { $0.geolocation = GeoPoint(latitude: 45, longitude: 45) } ] - ).error - expect(error).toNot(beNil()) + ).result + expect(result).toNot(beNil()) + expect(result?.entities.count).to(equal(3)) expect(autoDataStore.pendingSyncCount()).to(equal(3)) expect(autoDataStore.pendingSyncEntities().count).to(equal(3)) diff --git a/Makefile b/Makefile index cac77013c..1fee0b328 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,10 @@ CURRENT_BRANCH=$(shell git branch | awk '{split($$0, array, " "); if (array[1] = DEVCENTER_GIT=git@github.com:Kinvey/devcenter.git DEVCENTER_GIT_TEST=https://git.heroku.com/v3yk1n-devcenter.git DEVCENTER_GIT_PROD=https://git.heroku.com/kinvey-devcenter-prod.git -CARTFILE_RESOLVED_MD5=$(shell md5 Cartfile.resolved | awk '{ print $$4 }') +CARTFILE_RESOLVED_MD5=$(shell { cat Cartfile.resolved; swift --version | sed -e "s/Apple //" | head -1 | awk '{ print "Swift " $$3 }'; } | tr "\n" "\n" | md5) +DESTINATION_OS?=13.0 +DESTINATION_NAME?=iPhone 11 Pro +ECHO?=no all: build archive pack docs @@ -16,13 +19,16 @@ clean: rm -Rf docs rm -Rf build rm -Rf Carthage + +echo: + @echo $(ECHO) checkout-dependencies: carthage checkout build-debug: xcodebuild -workspace Kinvey.xcworkspace -scheme Kinvey -configuration Debug BUILD_DIR=build ONLY_ACTIVE_ARCH=NO -sdk iphoneos - xcodebuild -workspace Kinvey.xcworkspace -scheme Kinvey -configuration Debug BUILD_DIR=build ONLY_ACTIVE_ARCH=NO -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone SE' + xcodebuild -workspace Kinvey.xcworkspace -scheme Kinvey -configuration Debug BUILD_DIR=build ONLY_ACTIVE_ARCH=NO -sdk iphonesimulator -destination 'platform=iOS Simulator' show-destinations: xcodebuild -workspace Kinvey.xcworkspace -scheme Kinvey -showdestinations @@ -33,7 +39,7 @@ build-dependencies-ios: checkout-dependencies cartfile-md5: @echo $(CARTFILE_RESOLVED_MD5) -travisci-cache: +cache: test -s Carthage/$(CARTFILE_RESOLVED_MD5).tar.lzma || \ { \ cd Carthage; \ @@ -42,7 +48,7 @@ travisci-cache: tar -xvf $(CARTFILE_RESOLVED_MD5).tar.lzma; \ } -travisci-cache-upload: +cache-upload: cd Carthage; \ tar --exclude=Build/**/Kinvey.framework* --lzma -cvf $(CARTFILE_RESOLVED_MD5).tar.lzma Build; \ aws s3 cp $(CARTFILE_RESOLVED_MD5).tar.lzma s3://kinvey-downloads/iOS/travisci-cache/$(CARTFILE_RESOLVED_MD5).tar.lzma @@ -71,7 +77,7 @@ test: test-ios test-macos test-ios: - xcodebuild -workspace Kinvey.xcworkspace -scheme Kinvey -destination "OS=12.0,name=iPhone X" test -enableCodeCoverage YES + xcodebuild -workspace Kinvey.xcworkspace -scheme Kinvey -destination 'OS=$(DESTINATION_OS),name=$(DESTINATION_NAME)' test -enableCodeCoverage YES test-macos: xcodebuild -workspace Kinvey.xcworkspace -scheme Kinvey-macOS test -enableCodeCoverage YES From 1285fe190e50bcfb7fbf24167c7c73c00afd168a Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Tue, 1 Oct 2019 10:18:02 -0700 Subject: [PATCH 08/12] feat: MLIBZ-921, Swift Package Manager Support (#302) * chore: MLIBZ-921, support for Swift Package Manager * chore: MLIBZ-921, setting the right docker image for Cirrus CI * chore: MLIBZ-921, setting the right docker image for Cirrus CI * chore: MLIBZ-921, printing Swift version in Cirrus CI * chore: MLIBZ-921, adding unit tests * chore: MLIBZ-921, adding LinuxMain.swift * chore: MLIBZ-921, updating Travis CI * chore: MLIBZ-921, updating Cirrus CI * chore: MLIBZ-921, updating Cirrus CI * chore: MLIBZ-921, updating iOS Simulator Destination * chore: MLIBZ-921, removing unit tests for SPM * chore: MLIBZ-3141, reverting Travis CI and Cirrus CI changes * chore: MLIBZ-3141, reverting Travis CI changes --- .cirrus.yml | 7 + .gitignore | 2 + Kinvey/Kinvey.xcodeproj/project.pbxproj | 4 - Kinvey/Kinvey/HttpRequest.swift | 2 +- Kinvey/Kinvey/Kinvey.swift | 2 + Kinvey/Kinvey/Query.swift | 4 + Kinvey/Kinvey/RealmCache.swift | 4 + Kinvey/KinveyTests/AclTestCase.swift | 10 ++ Kinvey/KinveyTests/AutoDataStoreSpec.swift | 27 +-- Kinvey/KinveyTests/Book.swift | 1 + .../CacheMigrationTestCaseStep1.swift | 4 + .../CacheMigrationTestCaseStep2.swift | 4 + Kinvey/KinveyTests/Event.swift | 1 + Kinvey/KinveyTests/GetOperationTest.swift | 160 ------------------ Kinvey/KinveyTests/KIF.swift | 4 + Kinvey/KinveyTests/KinveyTestCase.swift | 11 ++ Kinvey/KinveyTests/KinveyTests.swift | 2 +- Kinvey/KinveyTests/MultiInsertSpec.swift | 27 +-- Kinvey/KinveyTests/MyFile.swift | 1 + .../PushMissingConfiguration.swift | 6 + Kinvey/KinveyTests/SaveOperationTest.swift | 82 --------- Kinvey/KinveyTests/XCTestManifests.swift | 9 + Package.swift | 82 +++++++++ Sources/Kinvey | 1 + Tests/KinveyTests | 1 + Tests/LinuxMain.swift | 7 + 26 files changed, 192 insertions(+), 273 deletions(-) delete mode 100644 Kinvey/KinveyTests/GetOperationTest.swift delete mode 100644 Kinvey/KinveyTests/SaveOperationTest.swift create mode 100644 Kinvey/KinveyTests/XCTestManifests.swift create mode 100644 Package.swift create mode 120000 Sources/Kinvey create mode 120000 Tests/KinveyTests create mode 100644 Tests/LinuxMain.swift diff --git a/.cirrus.yml b/.cirrus.yml index e9defce75..927629157 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -18,3 +18,10 @@ task: xcode_version_script: xcodebuild -version xcode_show_destinations_script: make show-destinations test_ios_script: make test-ios + +task: + name: macOS SPM + osx_instance: + image: mojave-xcode-11 + swift_version_script: swift --version + build_script: swift build diff --git a/.gitignore b/.gitignore index 106d6b7c4..6e5a0ada1 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ Carthage !Carthage/Checkouts/NSPredicate-MongoDB-Adaptor/Sources/MongoDBPredicateAdaptor/*.swift Kinvey.framework.zip scripts/RealtimeSend/Rome +Package.resolved +Kinvey.xcodeproj diff --git a/Kinvey/Kinvey.xcodeproj/project.pbxproj b/Kinvey/Kinvey.xcodeproj/project.pbxproj index ec12de31f..078fcee0e 100644 --- a/Kinvey/Kinvey.xcodeproj/project.pbxproj +++ b/Kinvey/Kinvey.xcodeproj/project.pbxproj @@ -924,7 +924,6 @@ 5706FEC21C1F9A6D0037E7D0 /* StoreTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoreTestCase.swift; sourceTree = ""; }; 57089DD61D5CE80D00A36035 /* PullOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PullOperation.swift; sourceTree = ""; }; 570BD2FC1E845E7A000341C9 /* AggregateOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AggregateOperation.swift; sourceTree = ""; }; - 5711C46C1C74F52F00073806 /* SaveOperationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveOperationTest.swift; sourceTree = ""; }; 57136F621D5D23BF00731DDB /* MockKinveyBackend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockKinveyBackend.swift; sourceTree = ""; }; 5714EBAF1CCECE35001E3ECF /* AclTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AclTestCase.swift; sourceTree = ""; }; 5714EBB11CCEEAF9001E3ECF /* RemoveByIdOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoveByIdOperation.swift; sourceTree = ""; }; @@ -969,7 +968,6 @@ 57373ABE1ECE1849002842CE /* LogTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogTestCase.swift; sourceTree = ""; }; 57375F8F1E3FD71D0015A241 /* UploadAndPlayVideoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UploadAndPlayVideoViewController.swift; sourceTree = ""; }; 57379DA41C72AAA900E240E9 /* Operation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operation.swift; sourceTree = ""; }; - 57379DA61C72AE7F00E240E9 /* GetOperationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetOperationTest.swift; sourceTree = ""; }; 573851AB1D47C7EB00E4712A /* FileCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileCache.swift; sourceTree = ""; }; 573851AD1D47C7F800E4712A /* RealmFileCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmFileCache.swift; sourceTree = ""; }; 573CC99C20D19AB900BDF726 /* CacheMigrationTestCaseData.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = CacheMigrationTestCaseData.zip; sourceTree = ""; }; @@ -1828,8 +1826,6 @@ 57882EBF219BF5CA005ECCA3 /* AutoStoreTests.swift */, 57CDF45D22653DBC006596A7 /* AutoDataStoreSpec.swift */, 57A2ED951C4D5F74006D26A9 /* Media.xcassets */, - 57379DA61C72AE7F00E240E9 /* GetOperationTest.swift */, - 5711C46C1C74F52F00073806 /* SaveOperationTest.swift */, 5781D1301CE3ADBC00369F40 /* ErrorTestCase.swift */, 571BA2601F55D9E600DE1886 /* MyFile.swift */, 5781D1351CE3D0BA00369F40 /* FileTestCase.swift */, diff --git a/Kinvey/Kinvey/HttpRequest.swift b/Kinvey/Kinvey/HttpRequest.swift index 7b01f9a04..a48b5ba07 100644 --- a/Kinvey/Kinvey/HttpRequest.swift +++ b/Kinvey/Kinvey/HttpRequest.swift @@ -155,7 +155,7 @@ enum HttpHeader { case .requestId(let requestId): return requestId case .userAgent: - return "Kinvey SDK \(Bundle(for: Client.self).infoDictionary!["CFBundleShortVersionString"]!) (Swift \(swiftVersion))" + return "Kinvey SDK \(Bundle(for: Client.self).infoDictionary?["CFBundleShortVersionString"] ?? "") (Swift \(swiftVersion))" case .deviceInfo: let data = try! jsonEncoder.encode(DeviceInfo()) return String(data: data, encoding: .utf8) diff --git a/Kinvey/Kinvey/Kinvey.swift b/Kinvey/Kinvey/Kinvey.swift index a081172ad..b12dbb666 100644 --- a/Kinvey/Kinvey/Kinvey.swift +++ b/Kinvey/Kinvey/Kinvey.swift @@ -242,6 +242,8 @@ let groupId = "_group_" #if swift(>=6) let swiftVersion = "6 or above" +#elseif swift(>=5.1) + let swiftVersion = "5.1" #elseif swift(>=5.0) let swiftVersion = "5.0" #elseif swift(>=4.2.4) diff --git a/Kinvey/Kinvey/Query.swift b/Kinvey/Kinvey/Query.swift index 2a3a4d51a..536f3834d 100644 --- a/Kinvey/Kinvey/Query.swift +++ b/Kinvey/Kinvey/Query.swift @@ -15,6 +15,10 @@ import Foundation import os #endif +#if canImport(MongoDBPredicateAdaptor) + import MongoDBPredicateAdaptor +#endif + extension NSPredicate { internal var asString: String { diff --git a/Kinvey/Kinvey/RealmCache.swift b/Kinvey/Kinvey/RealmCache.swift index 44fccdd11..a930cc142 100644 --- a/Kinvey/Kinvey/RealmCache.swift +++ b/Kinvey/Kinvey/RealmCache.swift @@ -262,6 +262,9 @@ internal class RealmCache: Cache, CacheType, RealmCascadeDele var realmResults = newRealm.objects(self.entityType) if let predicate = query.predicate { + #if SWIFT_PACKAGE + realmResults = realmResults.filter(self.translate(predicate: predicate)) + #else if let exception = tryBlock({ realmResults = realmResults.filter(self.translate(predicate: predicate)) }), let reason = exception.reason @@ -273,6 +276,7 @@ internal class RealmCache: Cache, CacheType, RealmCascadeDele fatalError(reason) } } + #endif } if let sortDescriptors = query.sortDescriptors { diff --git a/Kinvey/KinveyTests/AclTestCase.swift b/Kinvey/KinveyTests/AclTestCase.swift index c714ea749..a277e9f8d 100644 --- a/Kinvey/KinveyTests/AclTestCase.swift +++ b/Kinvey/KinveyTests/AclTestCase.swift @@ -11,6 +11,16 @@ import XCTest class AclTestCase: StoreTestCase { + static var allTests = [ + ("testNoPermissionToDelete", testNoPermissionToDelete), + ("testNoPermissionToDeletePush", testNoPermissionToDeletePush), + ("testGlobalRead", testGlobalRead), + ("testGlobalWrite", testGlobalWrite), + ("testReaders", testReaders), + ("testWriters", testWriters), + ("testValidation", testValidation), + ] + func testNoPermissionToDelete() { signUp() diff --git a/Kinvey/KinveyTests/AutoDataStoreSpec.swift b/Kinvey/KinveyTests/AutoDataStoreSpec.swift index ac2c7e28f..695a87e45 100644 --- a/Kinvey/KinveyTests/AutoDataStoreSpec.swift +++ b/Kinvey/KinveyTests/AutoDataStoreSpec.swift @@ -6,6 +6,7 @@ // Copyright © 2019 Kinvey. All rights reserved. // +import Foundation import Quick import Nimble @testable import Kinvey @@ -790,7 +791,7 @@ class AutoDataStoreSpec: QuickSpec { case "PUT": return HttpResponse(request: request) default: - fail("\(request.httpMethod!) \(request.url!)\n\(try! JSONSerialization.jsonObject(with: request))") + fail("\(request.httpMethod!) \(request.url!)\n\(try! JSONSerialization.jsonObject(with: request)!)") return HttpResponse(statusCode: 404, data: Data()) } } @@ -871,10 +872,10 @@ class AutoDataStoreSpec: QuickSpec { let errors = kinveySync(dataStore: autoDataStore).errors expect(errors?.count).to(equal(2)) - expect((errors?.first as? NSError)?.domain).to(equal(NSURLErrorDomain)) - expect((errors?.first as? NSError)?.code).to(equal(NSURLErrorTimedOut)) - expect((errors?.last as? NSError)?.domain).to(equal(NSURLErrorDomain)) - expect((errors?.last as? NSError)?.code).to(equal(NSURLErrorTimedOut)) + expect((errors?.first as NSError?)?.domain).to(equal(NSURLErrorDomain)) + expect((errors?.first as NSError?)?.code).to(equal(NSURLErrorTimedOut)) + expect((errors?.last as NSError?)?.domain).to(equal(NSURLErrorDomain)) + expect((errors?.last as NSError?)?.code).to(equal(NSURLErrorTimedOut)) expect(autoDataStore.syncCount()).to(equal(2)) @@ -902,8 +903,8 @@ class AutoDataStoreSpec: QuickSpec { let errors = kinveySync(dataStore: autoDataStore).errors expect(errors?.count).to(equal(1)) - expect((errors?.first as? NSError)?.domain).to(equal(NSURLErrorDomain)) - expect((errors?.first as? NSError)?.code).to(equal(NSURLErrorTimedOut)) + expect((errors?.first as NSError?)?.domain).to(equal(NSURLErrorDomain)) + expect((errors?.first as NSError?)?.code).to(equal(NSURLErrorTimedOut)) expect(autoDataStore.syncCount()).to(equal(0)) expect(autoDataStore.pendingSyncEntities().count).to(equal(0)) @@ -1036,7 +1037,9 @@ class AutoDataStoreSpec: QuickSpec { expect(entities?.count).to(equal(3)) expect(entities?.first).toNot(beNil()) - expect(entities?[1]).toNot(beNil()) + if let count = entities?.count, count > 1 { + expect(entities?[1]).toNot(beNil()) + } expect(entities?.last).toNot(beNil()) guard let first = entities?.first, let middle = entities?[1], @@ -1465,7 +1468,7 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - let error = kinveyRemove(dataStore: autoDataStore, query: query).error as? NSError + let error = kinveyRemove(dataStore: autoDataStore, query: query).error as NSError? expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) } @@ -1538,7 +1541,7 @@ class AutoDataStoreSpec: QuickSpec { setURLProtocol(KinveyURLProtocol.self) } - let error = kinveyRemove(dataStore: autoDataStore, id: "my_id1").error as? NSError + let error = kinveyRemove(dataStore: autoDataStore, id: "my_id1").error as NSError? expect(error?.domain).to(equal(NSURLErrorDomain)) expect(error?.code).to(equal(NSURLErrorTimedOut)) @@ -1642,7 +1645,7 @@ class AutoDataStoreSpec: QuickSpec { } -func it(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () throws -> Void) { +func it(_ description: String, flags: FilterFlags = [:], file: FileString = #file, line: UInt = #line, closure: @escaping () throws -> Void) { it(description, flags: flags, file: file, line: line) { do { try closure() @@ -1652,7 +1655,7 @@ func it(_ description: String, flags: FilterFlags = [:], file: String = #file, l } } -func fit(_ description: String, flags: FilterFlags = [:], file: String = #file, line: UInt = #line, closure: @escaping () throws -> Void) { +func fit(_ description: String, flags: FilterFlags = [:], file: FileString = #file, line: UInt = #line, closure: @escaping () throws -> Void) { fit(description, flags: flags, file: file, line: line) { do { try closure() diff --git a/Kinvey/KinveyTests/Book.swift b/Kinvey/KinveyTests/Book.swift index 367df2e8d..ce10f2d09 100644 --- a/Kinvey/KinveyTests/Book.swift +++ b/Kinvey/KinveyTests/Book.swift @@ -6,6 +6,7 @@ // Copyright © 2016 Kinvey. All rights reserved. // +import Foundation import Kinvey class Book: Entity { diff --git a/Kinvey/KinveyTests/CacheMigrationTestCaseStep1.swift b/Kinvey/KinveyTests/CacheMigrationTestCaseStep1.swift index 0c198cf95..1403cb0a2 100644 --- a/Kinvey/KinveyTests/CacheMigrationTestCaseStep1.swift +++ b/Kinvey/KinveyTests/CacheMigrationTestCaseStep1.swift @@ -6,6 +6,8 @@ // Copyright © 2016 Kinvey. All rights reserved. // +#if !SWIFT_PACKAGE + import XCTest import RealmSwift @testable import Kinvey @@ -93,3 +95,5 @@ class CacheMigrationTestCaseStep1: XCTestCase { } } + +#endif diff --git a/Kinvey/KinveyTests/CacheMigrationTestCaseStep2.swift b/Kinvey/KinveyTests/CacheMigrationTestCaseStep2.swift index 66dd106e1..bcc2da4c7 100644 --- a/Kinvey/KinveyTests/CacheMigrationTestCaseStep2.swift +++ b/Kinvey/KinveyTests/CacheMigrationTestCaseStep2.swift @@ -6,6 +6,8 @@ // Copyright © 2016 Kinvey. All rights reserved. // +#if !SWIFT_PACKAGE + import XCTest import RealmSwift @testable import Kinvey @@ -295,3 +297,5 @@ class CacheMigrationTestCaseStep2: XCTestCase { } } + +#endif diff --git a/Kinvey/KinveyTests/Event.swift b/Kinvey/KinveyTests/Event.swift index 2cefde359..5a5e3b1ae 100644 --- a/Kinvey/KinveyTests/Event.swift +++ b/Kinvey/KinveyTests/Event.swift @@ -6,6 +6,7 @@ // Copyright © 2016 Kinvey. All rights reserved. // +import Foundation import Kinvey /// Event.swift - an entity in the 'Events' collection diff --git a/Kinvey/KinveyTests/GetOperationTest.swift b/Kinvey/KinveyTests/GetOperationTest.swift deleted file mode 100644 index f7027c78b..000000000 --- a/Kinvey/KinveyTests/GetOperationTest.swift +++ /dev/null @@ -1,160 +0,0 @@ -// -// GetOperationTest.swift -// Kinvey -// -// Created by Victor Barros on 2016-02-15. -// Copyright © 2016 Kinvey. All rights reserved. -// - -import XCTest - -class GetOperationTest: StoreTestCase { - - override func tearDown() { - super.tearDown() - store.ttl = nil - } - - override func save() -> Person { - let person = self.person - - weak var expectationSave = expectationWithDescription("Save") - - store.save(person, writePolicy: .ForceNetwork) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - if let person = person { - XCTAssertEqual(person, self.person) - XCTAssertNotNil(person.personId) - } - - expectationSave?.fulfill() - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationSave = nil - } - - return person - } - - func testForceNetwork() { - let person = save() - - XCTAssertNotNil(person.personId) - if let personId = person.personId { - weak var expectationGet = expectationWithDescription("Get") - - store.findById(personId, readPolicy: .ForceNetwork) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - expectationGet?.fulfill() - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationGet = nil - } - } - } - - func testForceLocal() { - let person = save() - - XCTAssertNotNil(person.personId) - if let personId = person.personId { - weak var expectationGet = expectationWithDescription("Get") - - store.findById(personId, readPolicy: .ForceLocal) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - expectationGet?.fulfill() - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationGet = nil - } - } - } - - func testForceLocalExpiredTTL() { - let person = save() - - store.ttl = 1.seconds - - NSThread.sleepForTimeInterval(1) - - XCTAssertNotNil(person.personId) - if let personId = person.personId { - weak var expectationGet = expectationWithDescription("Get") - - store.findById(personId, readPolicy: .ForceLocal) { (person, error) -> Void in - XCTAssertNil(person) - XCTAssertNil(error) - - expectationGet?.fulfill() - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationGet = nil - } - } - } - - func testBoth() { - weak var expectationSaveLocal = expectationWithDescription("SaveLocal") - weak var expectationSaveNetwork = expectationWithDescription("SaveNetwork") - - var isLocal = true - - store.save(person, writePolicy: .LocalThenNetwork) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - if let person = person { - XCTAssertEqual(person, self.person) - XCTAssertNotNil(person.personId) - } - - if isLocal { - expectationSaveLocal?.fulfill() - isLocal = false - } else { - expectationSaveNetwork?.fulfill() - } - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationSaveLocal = nil - expectationSaveNetwork = nil - } - - XCTAssertNotNil(person.personId) - if let personId = person.personId { - weak var expectationGetLocal = expectationWithDescription("GetLocal") - weak var expectationGetNetwork = expectationWithDescription("GetNetwork") - - var isLocal = true - - store.findById(personId, readPolicy: .Both) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - if isLocal { - expectationGetLocal?.fulfill() - isLocal = false - } else { - expectationGetNetwork?.fulfill() - } - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationGetLocal = nil - expectationGetNetwork = nil - } - } - } - -} diff --git a/Kinvey/KinveyTests/KIF.swift b/Kinvey/KinveyTests/KIF.swift index 1a6852e2d..31f74258f 100644 --- a/Kinvey/KinveyTests/KIF.swift +++ b/Kinvey/KinveyTests/KIF.swift @@ -6,6 +6,8 @@ // Copyright © 2016 Kinvey. All rights reserved. // +#if canImport(KIF) + import KIF extension XCTestCase { @@ -50,3 +52,5 @@ extension XCTestCase { return fulfilled } } + +#endif diff --git a/Kinvey/KinveyTests/KinveyTestCase.swift b/Kinvey/KinveyTests/KinveyTestCase.swift index 71a081995..ffe435661 100644 --- a/Kinvey/KinveyTests/KinveyTestCase.swift +++ b/Kinvey/KinveyTests/KinveyTestCase.swift @@ -245,10 +245,12 @@ func kinveyLogout() { expect(Kinvey.sharedClient.activeUser).toEventually(beNil()) } +@discardableResult func kinveySave(dataStore: DataStore, entities: T...) -> (entities: AnyRandomAccessCollection?, errors: [Swift.Error]?) { return kinveySave(dataStore: dataStore, entities: entities) } +@discardableResult func kinveySave(dataStore: DataStore, entities: S) -> (entities: AnyRandomAccessCollection?, errors: [Swift.Error]?) where S.Element == T { var items = [T?]() var errors = [Swift.Error?]() @@ -260,10 +262,12 @@ func kinveySave(dataStore: DataStore, entities: S) -> return (entities: items.count > 0 ? AnyRandomAccessCollection(items.compactMap({ $0 })) : nil, errors: errors.count > 0 ? errors.compactMap({ $0 }) : nil) } +@discardableResult func kinveySaveMulti(dataStore: DataStore, entities: T...) -> (result: MultiSaveResultTuple?, error: Swift.Error?) { return kinveySaveMulti(dataStore: dataStore, entities: entities) } +@discardableResult func kinveySaveMulti(dataStore: DataStore, entities: S) -> (result: MultiSaveResultTuple?, error: Swift.Error?) where S.Element == T { var result: MultiSaveResultTuple? = nil var error: Swift.Error? = nil @@ -281,6 +285,7 @@ func kinveySaveMulti(dataStore: DataStore< return (result: result, error: error) } +@discardableResult func kinveySave(dataStore: DataStore, numberOfItems: Int) -> (entities: AnyRandomAccessCollection?, errors: [Swift.Error]?) { var entities = [T?]() var errors = [Swift.Error?]() @@ -292,6 +297,7 @@ func kinveySave(dataStore: DataStore, numberOfItems: Int) -> (enti return (entities: entities.count > 0 ? AnyRandomAccessCollection(entities.compactMap({ $0 })) : nil, errors: errors.count > 0 ? errors.compactMap({ $0 }) : nil) } +@discardableResult func kinveySave(dataStore: DataStore, entity: T = T()) -> (entity: T?, error: Swift.Error?) { var entityPostSave: T? = nil var error: Swift.Error? = nil @@ -386,6 +392,7 @@ func kinveySync( return (result: result, errors: errors) } +@discardableResult func kinveyPush( dataStore: DataStore, options: Options? = nil @@ -432,6 +439,7 @@ func kinveyPull( return (entities: entities, error: error) } +@discardableResult func kinveyRemove( dataStore: DataStore, query: Query = Query(), @@ -456,6 +464,7 @@ func kinveyRemove( return (count: count, error: error) } +@discardableResult func kinveyRemove( dataStore: DataStore, entity: T, @@ -485,6 +494,7 @@ func kinveyRemove( return (count: count, error: error) } +@discardableResult func kinveyRemove( dataStore: DataStore, id: String, @@ -514,6 +524,7 @@ func kinveyRemove( return (count: count, error: error) } +@discardableResult func kinveySave( dataStore: DataStore, entity: T, diff --git a/Kinvey/KinveyTests/KinveyTests.swift b/Kinvey/KinveyTests/KinveyTests.swift index 8c6e9fe81..880f91520 100644 --- a/Kinvey/KinveyTests/KinveyTests.swift +++ b/Kinvey/KinveyTests/KinveyTests.swift @@ -28,7 +28,7 @@ class KinveyTests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measureBlock { + self.measure { // Put the code you want to measure the time of here. } } diff --git a/Kinvey/KinveyTests/MultiInsertSpec.swift b/Kinvey/KinveyTests/MultiInsertSpec.swift index 391f857d0..720483434 100644 --- a/Kinvey/KinveyTests/MultiInsertSpec.swift +++ b/Kinvey/KinveyTests/MultiInsertSpec.swift @@ -6,6 +6,7 @@ // Copyright © 2019 Kinvey. All rights reserved. // +import Foundation import Quick import Nimble @testable import Kinvey @@ -512,7 +513,7 @@ class MultiInsertSpec: QuickSpec { var errors = jsonObject["errors"] as! [[String : Any]] switch count { case 0: - XCTAssertEqual(json.count, 100) + expect(json.count).to(equal(100)) let index = 10 let entity = entities[index] entities[index] = nil @@ -522,7 +523,7 @@ class MultiInsertSpec: QuickSpec { "errmsg" : "Entity not saved" ]) case 1: - XCTAssertEqual(json.count, 50) + expect(json.count).to(equal(50)) let index = 20 let entity = entities[index] entities[index] = nil @@ -532,7 +533,7 @@ class MultiInsertSpec: QuickSpec { "errmsg" : "Entity not saved" ]) default: - XCTFail("request not expected") + fail("request not expected") } jsonObject["entities"] = entities jsonObject["errors"] = errors @@ -547,25 +548,25 @@ class MultiInsertSpec: QuickSpec { entities: entities ).result - XCTAssertEqual(count, 2) - XCTAssertNotNil(result) + expect(count).to(equal(2)) + expect(result).toNot(beNil()) guard let resultUnwrapped = result else { return } - XCTAssertEqual(resultUnwrapped.entities.count, 150) - XCTAssertEqual(resultUnwrapped.entities.filter({ $0 != nil }).count, 148) - XCTAssertEqual(resultUnwrapped.entities.filter({ $0 == nil }).count, 2) + expect(resultUnwrapped.entities.count).to(equal(150)) + expect(resultUnwrapped.entities.filter({ $0 != nil }).count).to(equal(148)) + expect(resultUnwrapped.entities.filter({ $0 == nil }).count).to(equal(2)) for (offset, entity) in resultUnwrapped.entities.enumerated() { switch offset { case 10, 120: - XCTAssertNil(entity) + expect(entity).to(beNil()) default: - XCTAssertNotNil(entity) + expect(entity).toNot(beNil()) } } - XCTAssertEqual(resultUnwrapped.errors.count, 2) - XCTAssertEqual((resultUnwrapped.errors.first as? IndexableError)?.index, 10) - XCTAssertEqual((resultUnwrapped.errors.last as? IndexableError)?.index, 120) + expect(resultUnwrapped.errors.count).to(equal(2)) + expect((resultUnwrapped.errors.first as? IndexableError)?.index).to(equal(10)) + expect((resultUnwrapped.errors.last as? IndexableError)?.index).to(equal(120)) } it("whole batch fails") { let entities = Array((1 ... 100).map({ i in diff --git a/Kinvey/KinveyTests/MyFile.swift b/Kinvey/KinveyTests/MyFile.swift index 1949624f3..b6c84ceb4 100644 --- a/Kinvey/KinveyTests/MyFile.swift +++ b/Kinvey/KinveyTests/MyFile.swift @@ -6,6 +6,7 @@ // Copyright © 2017 Kinvey. All rights reserved. // +import Foundation import Kinvey class MyFile: File { diff --git a/Kinvey/KinveyTests/PushMissingConfiguration.swift b/Kinvey/KinveyTests/PushMissingConfiguration.swift index e08c1bc6e..afc49eb0b 100644 --- a/Kinvey/KinveyTests/PushMissingConfiguration.swift +++ b/Kinvey/KinveyTests/PushMissingConfiguration.swift @@ -7,11 +7,15 @@ // import XCTest +#if canImport(KIF) import KIF +#endif import Kinvey class PushMissingConfigurationTestCase: KinveyTestCase { + #if canImport(KIF) + func testMissingConfigurationError() { signUp() @@ -68,4 +72,6 @@ class PushMissingConfigurationTestCase: KinveyTestCase { } } + #endif + } diff --git a/Kinvey/KinveyTests/SaveOperationTest.swift b/Kinvey/KinveyTests/SaveOperationTest.swift deleted file mode 100644 index ac63dd498..000000000 --- a/Kinvey/KinveyTests/SaveOperationTest.swift +++ /dev/null @@ -1,82 +0,0 @@ -// -// SaveOperationTest.swift -// Kinvey -// -// Created by Victor Barros on 2016-02-17. -// Copyright © 2016 Kinvey. All rights reserved. -// - -import XCTest - -class SaveOperationTest: StoreTestCase { - - func testForceNetwork() { - weak var expectationSave = expectationWithDescription("Save") - - store.save(person, writePolicy: .ForceNetwork) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - if let person = person { - XCTAssertEqual(person, self.person) - XCTAssertNotNil(person.personId) - } - - expectationSave?.fulfill() - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationSave = nil - } - } - - func testForceLocal() { - weak var expectationSave = expectationWithDescription("Save") - - store.save(person, writePolicy: .ForceLocal) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - if let person = person { - XCTAssertEqual(person, self.person) - XCTAssertNotNil(person.personId) - } - - expectationSave?.fulfill() - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationSave = nil - } - } - - func testLocalThenNetwork() { - weak var expectationSaveLocal = expectationWithDescription("SaveLocal") - weak var expectationSaveNetwork = expectationWithDescription("SaveNetwork") - - var isLocal = true - - store.save(person, writePolicy: .LocalThenNetwork) { (person, error) -> Void in - XCTAssertNotNil(person) - XCTAssertNil(error) - - if let person = person { - XCTAssertEqual(person, self.person) - XCTAssertNotNil(person.personId) - } - - if isLocal { - expectationSaveLocal?.fulfill() - isLocal = false - } else { - expectationSaveNetwork?.fulfill() - } - } - - waitForExpectationsWithTimeout(defaultTimeout) { error in - expectationSaveLocal = nil - expectationSaveNetwork = nil - } - } - -} diff --git a/Kinvey/KinveyTests/XCTestManifests.swift b/Kinvey/KinveyTests/XCTestManifests.swift new file mode 100644 index 000000000..edec487f1 --- /dev/null +++ b/Kinvey/KinveyTests/XCTestManifests.swift @@ -0,0 +1,9 @@ +import XCTest + +#if !canImport(ObjectiveC) +public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(AclTestCase.allTests), + ] +} +#endif diff --git a/Package.swift b/Package.swift new file mode 100644 index 000000000..ddcc597ce --- /dev/null +++ b/Package.swift @@ -0,0 +1,82 @@ +// swift-tools-version:5.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Kinvey", + platforms: [ + .macOS(.v10_12), + .iOS(.v10), + .tvOS(.v10), + .watchOS(.v3) + ], + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "Kinvey", + targets: ["Kinvey"] + ), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package( + url: "https://github.com/realm/realm-cocoa.git", + .upToNextMajor(from: "3.18.0") + ), + .package( + url: "https://github.com/mxcl/PromiseKit.git", + .upToNextMajor(from: "6.10.0") + ), + .package( + url: "https://github.com/kishikawakatsumi/KeychainAccess.git", + .upToNextMajor(from: "3.2.0") + ), + .package( + url: "https://github.com/SwiftyBeaver/SwiftyBeaver.git", + .upToNextMajor(from: "1.7.1") + ), + .package( + url: "https://github.com/tristanhimmelman/ObjectMapper.git", + .upToNextMajor(from: "3.5.1") + ), + .package( + url: "https://github.com/heyzooi/objective-c.git", + .branch("master") + ), + .package( + url: "https://github.com/tjboneman/NSPredicate-MongoDB-Adaptor.git", + .branch("master") + ), + .package( + url: "https://github.com/Quick/Quick.git", + .upToNextMajor(from: "2.2.0") + ), + .package( + url: "https://github.com/Quick/Nimble.git", + .branch("master") + ), + .package( + url: "https://github.com/weichsel/ZIPFoundation.git", + .upToNextMajor(from: "0.9.9") + ), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "Kinvey", + dependencies: [ + "Realm", + "RealmSwift", + "PromiseKit", + "KeychainAccess", + "SwiftyBeaver", + "ObjectMapper", + "PubNub", + "MongoDBPredicateAdaptor", + ] + ), + ] +) diff --git a/Sources/Kinvey b/Sources/Kinvey new file mode 120000 index 000000000..5488d627a --- /dev/null +++ b/Sources/Kinvey @@ -0,0 +1 @@ +../Kinvey/Kinvey \ No newline at end of file diff --git a/Tests/KinveyTests b/Tests/KinveyTests new file mode 120000 index 000000000..6ee16179c --- /dev/null +++ b/Tests/KinveyTests @@ -0,0 +1 @@ +../Kinvey/KinveyTests/ \ No newline at end of file diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 000000000..1358abcd1 --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,7 @@ +import XCTest + +import KinveyTests + +var tests = [XCTestCaseEntry]() +tests += KinveyTests.allTests() +XCTMain(tests) From 4417f726d77db4084e14799225f08482e6b32289 Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Tue, 1 Oct 2019 17:08:52 -0700 Subject: [PATCH 09/12] chore: bumping iOS and tvOS minimum versions --- Kinvey/Kinvey.xcodeproj/project.pbxproj | 8 -------- Kinvey/Kinvey/Kinvey.xcconfig | 5 +++++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Kinvey/Kinvey.xcodeproj/project.pbxproj b/Kinvey/Kinvey.xcodeproj/project.pbxproj index 078fcee0e..e09792eca 100644 --- a/Kinvey/Kinvey.xcodeproj/project.pbxproj +++ b/Kinvey/Kinvey.xcodeproj/project.pbxproj @@ -4871,18 +4871,14 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TVOS_DEPLOYMENT_TARGET = 10.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; }; name = Debug; }; @@ -4927,18 +4923,14 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TVOS_DEPLOYMENT_TARGET = 10.0; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; }; name = Release; }; diff --git a/Kinvey/Kinvey/Kinvey.xcconfig b/Kinvey/Kinvey/Kinvey.xcconfig index 252f2c419..6a9b2f74a 100644 --- a/Kinvey/Kinvey/Kinvey.xcconfig +++ b/Kinvey/Kinvey/Kinvey.xcconfig @@ -24,4 +24,9 @@ FRAMEWORK_SEARCH_PATHS[sdk=appletvsimulator*] = $(inherited) $(PROJECT_DIR)/../C FRAMEWORK_SEARCH_PATHS[sdk=watchos*] = $(inherited) $(PROJECT_DIR)/../Carthage/Build/watchOS FRAMEWORK_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) $(PROJECT_DIR)/../Carthage/Build/watchOS +IPHONEOS_DEPLOYMENT_TARGET = 11.0 +MACOSX_DEPLOYMENT_TARGET = 10.12 +TVOS_DEPLOYMENT_TARGET = 11.0 +WATCHOS_DEPLOYMENT_TARGET = 4.0 + TARGETED_DEVICE_FAMILY = 1,2,3,4 From 898874ad94d51a92b52a3099531df8e1c5d9e15f Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Tue, 1 Oct 2019 17:09:17 -0700 Subject: [PATCH 10/12] chore: update dependencies --- Cartfile.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 7de5ec8d5..4eb014544 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,12 +1,12 @@ github "Hearst-DD/ObjectMapper" "3.5.1" github "Quick/Nimble" "v8.0.4" github "Quick/Quick" "v2.2.0" -github "SwiftyBeaver/SwiftyBeaver" "1.7.1" +github "SwiftyBeaver/SwiftyBeaver" "1.8.1" github "httpswift/swifter" "70355c4e414e93a0589a0d5d4ade342534bbab38" github "kif-framework/KIF" "v3.7.8" github "kishikawakatsumi/KeychainAccess" "v3.2.0" github "mxcl/PromiseKit" "6.11.0" github "pubnub/objective-c" "v4.10.1" -github "realm/realm-cocoa" "v3.18.0" +github "realm/realm-cocoa" "v3.19.0" github "tjboneman/NSPredicate-MongoDB-Adaptor" "fce0cd01913bd4393db0c3dd33404cb7e9ebec88" github "weichsel/ZIPFoundation" "0.9.9" From 3a199c281a70886c41dba20a4d36e609425212f9 Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Tue, 1 Oct 2019 17:09:46 -0700 Subject: [PATCH 11/12] chore: bumping iOS and tvOS minimum versions --- Kinvey.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Kinvey.podspec b/Kinvey.podspec index 03dd81ed9..a38ac831e 100644 --- a/Kinvey.podspec +++ b/Kinvey.podspec @@ -67,9 +67,9 @@ Pod::Spec.new do |s| # s.platform = :ios, "9.0" # When using multiple platforms - s.ios.deployment_target = "10.0" + s.ios.deployment_target = "11.0" s.osx.deployment_target = "10.12" - s.tvos.deployment_target = "10.0" + s.tvos.deployment_target = "11.0" s.watchos.deployment_target = "4.0" From 0eba6886ec56c06205db6b168273a84a3c813095 Mon Sep 17 00:00:00 2001 From: Victor Hugo Barros Date: Tue, 1 Oct 2019 17:10:17 -0700 Subject: [PATCH 12/12] chore: bump version to 4.1.0 --- Kinvey.podspec | 2 +- Kinvey/Kinvey/Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Kinvey.podspec b/Kinvey.podspec index a38ac831e..fab299200 100644 --- a/Kinvey.podspec +++ b/Kinvey.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "Kinvey" - s.version = "4.0.0" + s.version = "4.1.0" s.summary = "Kinvey iOS SDK" # This description is used to generate tags and improve search results. diff --git a/Kinvey/Kinvey/Info.plist b/Kinvey/Kinvey/Info.plist index 1bcfa6d13..5284837db 100644 --- a/Kinvey/Kinvey/Info.plist +++ b/Kinvey/Kinvey/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 4.0.0 + 4.1.0 CFBundleSignature ???? CFBundleVersion