Skip to content

Commit c9d8c95

Browse files
authored
feat: Attempt to retreive full objects on server during POST (#197)
* feat: Attempt to retreive full objects on server during POST * increase codecov with more tests * more coverage
1 parent e4d22f7 commit c9d8c95

File tree

7 files changed

+331
-14
lines changed

7 files changed

+331
-14
lines changed

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22
# Parse-Swift Changelog
33

44
### main
5-
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.12.1...main), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/main/documentation/parseswift)
5+
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.12.2...main), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/main/documentation/parseswift)
66
* _Contributing to this repo? Add info about your change here to be included in the next release_
77

8+
### 5.12.2
9+
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.12.1...5.12.2), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.12.2/documentation/parseswift)
10+
11+
__Fixes__
12+
* When creating objects, if the server does not return the correct full object, attempt to retrieve it before returning to call-site. ([#197](https://github.com/netreconlab/Parse-Swift/pull/197)), thanks to [Corey Baker](https://github.com/cbaker6).
13+
* Fixes an issue when using `mergeable` on `ParseInstallation`'s' and properties that are automatically computed such as `appVersion` are not sent to the server. ([#197](https://github.com/netreconlab/Parse-Swift/pull/197)), thanks to [Corey Baker](https://github.com/cbaker6).
14+
815
### 5.12.1
916
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.12.0...5.12.1), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.12.1/documentation/parseswift)
1017

Sources/ParseSwift/API/API+Command.swift

+21-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,27 @@ internal extension API.Command {
436436
}
437437
let updatedObject = object
438438
let mapper = { @Sendable (data) -> V in
439-
try ParseCoding.jsonDecoder().decode(CreateResponse.self, from: data).apply(to: updatedObject)
439+
do {
440+
// Try to decode CreateResponse, if that doesn't work try Pointer
441+
let savedObject = try ParseCoding.jsonDecoder().decode(
442+
CreateResponse.self,
443+
from: data
444+
).apply(
445+
to: updatedObject
446+
)
447+
return savedObject
448+
} catch let originalError {
449+
do {
450+
let pointer = try ParseCoding.jsonDecoder().decode(
451+
Pointer<V>.self,
452+
from: data
453+
)
454+
let fetchedObject = try await pointer.fetch()
455+
return fetchedObject
456+
} catch {
457+
throw originalError
458+
}
459+
}
440460
}
441461
return API.Command<V, V>(method: .POST,
442462
path: try await object.endpoint(.POST),

Sources/ParseSwift/Objects/ParseInstallation.swift

+25-6
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,25 @@ public extension ParseInstallation {
9595
"_Installation"
9696
}
9797

98+
var mergeable: Self {
99+
guard isSaved,
100+
originalData == nil else {
101+
return self
102+
}
103+
var object = Self()
104+
object.objectId = objectId
105+
object.createdAt = createdAt
106+
object.badge = badge
107+
object.timeZone = timeZone
108+
object.appName = appName
109+
object.appIdentifier = appIdentifier
110+
object.appVersion = appVersion
111+
object.parseVersion = parseVersion
112+
object.localeIdentifier = localeIdentifier
113+
object.originalData = try? ParseCoding.jsonEncoder().encode(self)
114+
return object
115+
}
116+
98117
var endpoint: API.Endpoint {
99118
if let objectId = objectId {
100119
return .installation(objectId: objectId)
@@ -418,7 +437,7 @@ extension ParseInstallation {
418437
return
419438
}
420439
#if !os(Linux) && !os(Android) && !os(Windows)
421-
#if TARGET_OS_MACCATALYST
440+
#if targetEnvironment(macCatalyst)
422441
// If using an Xcode new enough to know about Mac Catalyst:
423442
// Mac Catalyst Apps use a prefix to the bundle ID. This should not be transmitted
424443
// to Parse Server. Catalyst apps should look like iOS apps otherwise
@@ -754,18 +773,18 @@ extension ParseInstallation {
754773
let savedObject = try ParseCoding.jsonDecoder().decode(
755774
CreateResponse.self,
756775
from: data
757-
).apply(to: updatedObject)
758-
776+
).apply(
777+
to: updatedObject
778+
)
759779
return savedObject
760780
} catch let originalError {
761781
do {
762782
let pointer = try ParseCoding.jsonDecoder().decode(
763783
Pointer<Self>.self,
764784
from: data
765785
)
766-
var objectToUpdate = updatedObject
767-
objectToUpdate.objectId = pointer.objectId
768-
return objectToUpdate
786+
let fetchedObject = try await pointer.fetch()
787+
return fetchedObject
769788
} catch {
770789
throw originalError
771790
}

Sources/ParseSwift/Objects/ParseUser.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -1223,18 +1223,18 @@ extension ParseUser {
12231223
let savedObject = try ParseCoding.jsonDecoder().decode(
12241224
CreateResponse.self,
12251225
from: data
1226-
).apply(to: updatedUser)
1227-
1226+
).apply(
1227+
to: updatedUser
1228+
)
12281229
return savedObject
12291230
} catch let originalError {
12301231
do {
12311232
let pointer = try ParseCoding.jsonDecoder().decode(
12321233
Pointer<Self>.self,
12331234
from: data
12341235
)
1235-
var objectToUpdate = updatedUser
1236-
objectToUpdate.objectId = pointer.objectId
1237-
return objectToUpdate
1236+
let fetchedObject = try await pointer.fetch()
1237+
return fetchedObject
12381238
} catch {
12391239
throw originalError
12401240
}

Sources/ParseSwift/ParseConstants.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010

1111
enum ParseConstants {
1212
static let sdk = "swift"
13-
static let version = "5.12.1"
13+
static let version = "5.12.2"
1414
static let fileManagementDirectory = "parse/"
1515
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
1616
static let fileManagementLibraryDirectory = "Library/"

Tests/ParseSwiftTests/ParseInstallationTests.swift

+87
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,93 @@ class ParseInstallationTests: XCTestCase { // swiftlint:disable:this type_body_l
483483
XCTAssertEqual(merged, original)
484484
}
485485

486+
@MainActor
487+
func testMergeableRetainsAutomaticallyComputedProperties() async throws {
488+
var original = try await Installation.current()
489+
original.objectId = "yolo"
490+
original.createdAt = Date()
491+
original.updatedAt = Date()
492+
original.badge = 10
493+
original.deviceToken = "12345"
494+
original.channels = ["halo"]
495+
original.customKey = "newKey"
496+
var acl = ParseACL()
497+
acl.publicRead = true
498+
original.ACL = acl
499+
500+
// These properties should not be nil before merge
501+
XCTAssertNotNil(original.customKey)
502+
XCTAssertNotNil(original.deviceType)
503+
XCTAssertNotNil(original.deviceToken)
504+
XCTAssertNotNil(original.channels)
505+
XCTAssertNotNil(original.installationId)
506+
XCTAssertNotNil(original.ACL)
507+
XCTAssertNotNil(original.updatedAt)
508+
509+
let mergeable = original.mergeable
510+
511+
// These should always remain in the merge
512+
XCTAssertEqual(original.badge, mergeable.badge)
513+
XCTAssertEqual(original.timeZone, mergeable.timeZone)
514+
XCTAssertEqual(original.appName, mergeable.appName)
515+
XCTAssertEqual(original.appVersion, mergeable.appVersion)
516+
XCTAssertEqual(original.appIdentifier, mergeable.appIdentifier)
517+
XCTAssertEqual(original.parseVersion, mergeable.parseVersion)
518+
XCTAssertEqual(original.localeIdentifier, mergeable.localeIdentifier)
519+
XCTAssertEqual(original.createdAt, mergeable.createdAt)
520+
521+
// All other properties should be nil
522+
XCTAssertNil(mergeable.customKey)
523+
XCTAssertNil(mergeable.deviceType)
524+
XCTAssertNil(mergeable.deviceToken)
525+
XCTAssertNil(mergeable.channels)
526+
XCTAssertNil(mergeable.installationId)
527+
XCTAssertNil(mergeable.ACL)
528+
XCTAssertNil(mergeable.updatedAt)
529+
}
530+
531+
@MainActor
532+
func testMergeableRetainsAllPropertiesWhenNotSaved() async throws {
533+
var original = try await Installation.current()
534+
original.badge = 10
535+
original.deviceToken = "12345"
536+
original.channels = ["halo"]
537+
original.customKey = "newKey"
538+
var acl = ParseACL()
539+
acl.publicRead = true
540+
original.ACL = acl
541+
542+
XCTAssertNil(original.objectId)
543+
XCTAssertNil(original.createdAt)
544+
XCTAssertNil(original.updatedAt)
545+
546+
// These properties should not be nil before merge
547+
XCTAssertNotNil(original.customKey)
548+
XCTAssertNotNil(original.deviceType)
549+
XCTAssertNotNil(original.deviceToken)
550+
XCTAssertNotNil(original.channels)
551+
XCTAssertNotNil(original.installationId)
552+
XCTAssertNotNil(original.ACL)
553+
554+
let mergeable = original.mergeable
555+
556+
XCTAssertEqual(original.badge, mergeable.badge)
557+
XCTAssertEqual(original.timeZone, mergeable.timeZone)
558+
XCTAssertEqual(original.appName, mergeable.appName)
559+
XCTAssertEqual(original.appVersion, mergeable.appVersion)
560+
XCTAssertEqual(original.appIdentifier, mergeable.appIdentifier)
561+
XCTAssertEqual(original.parseVersion, mergeable.parseVersion)
562+
XCTAssertEqual(original.localeIdentifier, mergeable.localeIdentifier)
563+
XCTAssertEqual(original.customKey, mergeable.customKey)
564+
XCTAssertEqual(original.deviceType, mergeable.deviceType)
565+
XCTAssertEqual(original.deviceToken, mergeable.deviceToken)
566+
XCTAssertEqual(original.channels, mergeable.channels)
567+
XCTAssertEqual(original.installationId, mergeable.installationId)
568+
XCTAssertEqual(original.ACL, mergeable.ACL)
569+
XCTAssertEqual(original.createdAt, mergeable.createdAt)
570+
XCTAssertEqual(original.updatedAt, mergeable.updatedAt)
571+
}
572+
486573
@MainActor
487574
func testMergeDifferentObjectId() async throws {
488575
var installation = Installation()

0 commit comments

Comments
 (0)