Skip to content

Commit

Permalink
fix: allow ParseRole to save when using custom objectId's (#338)
Browse files Browse the repository at this point in the history
* fix: allow ParseRole to save when using custom objectId's

* codecov
  • Loading branch information
cbaker6 committed Jan 29, 2022
1 parent aa02ed9 commit 51e16d0
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ coverage:
status:
patch:
default:
target: 78
target: auto
changes: false
project:
default:
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

### main

[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.0.0...main)
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.0.1...main)
* _Contributing to this repo? Add info about your change here to be included in the next release_

### 4.0.1
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.0.0...4.0.1)

__Fixes__
- Allow ParseRole's to be updated when the SDK is allowing custom objectId's ([#338](https://github.com/parse-community/Parse-Swift/pull/338)), thanks to [Corey Baker](https://github.com/cbaker6).

### 4.0.0
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/3.1.2...4.0.0)

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/ParseConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

enum ParseConstants {
static let sdk = "swift"
static let version = "4.0.0"
static let version = "4.0.1"
static let fileManagementDirectory = "parse/"
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
static let fileManagementLibraryDirectory = "Library/"
Expand Down
4 changes: 2 additions & 2 deletions Sources/ParseSwift/Types/ParseOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ extension ParseOperation {
- returns: Returns saved `ParseObject`.
*/
public func save(options: API.Options = []) throws -> T {
if !target.isSaved {
guard target.objectId != nil else {
throw ParseError(code: .missingObjectId, message: "ParseObject isn't saved.")
}
return try saveCommand()
Expand All @@ -406,7 +406,7 @@ extension ParseOperation {
callbackQueue: DispatchQueue = .main,
completion: @escaping (Result<T, ParseError>) -> Void
) {
if !target.isSaved {
guard target.objectId != nil else {
callbackQueue.async {
let error = ParseError(code: .missingObjectId, message: "ParseObject isn't saved.")
completion(.failure(error))
Expand Down
6 changes: 3 additions & 3 deletions Tests/ParseSwiftTests/ParseRelationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ class ParseRelationTests: XCTestCase {
XCTAssertThrowsError(try relation.add("level", objects: [level]))
}

func testAddOperations() throws {
func testAddOperation() throws {
var score = GameScore(points: 10)
let objectId = "hello"
score.objectId = objectId
Expand Down Expand Up @@ -252,7 +252,7 @@ class ParseRelationTests: XCTestCase {
XCTAssertThrowsError(try relation.add("yolo", objects: [level]))
}

func testAddOperationsNoKey() throws {
func testAddOperationNoKey() throws {
var score = GameScore(points: 10)
let objectId = "hello"
score.objectId = objectId
Expand All @@ -274,7 +274,7 @@ class ParseRelationTests: XCTestCase {
XCTAssertEqual(decoded, expected)
}

func testAddOperationsKeyCheck() throws {
func testAddOperationKeyCheck() throws {
var score = GameScore(points: 10)
let objectId = "hello"
score.objectId = objectId
Expand Down
312 changes: 312 additions & 0 deletions Tests/ParseSwiftTests/ParseRoleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,318 @@ class ParseRoleTests: XCTestCase {
XCTAssertEqual(decoded2, expected2)
}

func testRoleAddOperationSaveSynchronous() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
let operation = try roles.add([newRole])

var serverResponse = role
serverResponse.createdAt = nil
serverResponse.updatedAt = Date()

let encoded: Data!
do {
encoded = try ParseCoding.jsonEncoder().encode(serverResponse)
//Get dates in correct format from ParseDecoding strategy
serverResponse = try serverResponse.getDecoder().decode(Role<User>.self, from: encoded)
} catch {
XCTFail("Should encode/decode. Error \(error)")
return
}

MockURLProtocol.mockRequests { _ in
return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0)
}

let updatedRole = try operation.save()
XCTAssertEqual(updatedRole.updatedAt, serverResponse.updatedAt)
XCTAssertTrue(updatedRole.hasSameObjectId(as: serverResponse))
}

func testRoleAddOperationSaveSynchronousError() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
var operation = try roles.add([newRole])
operation.target.objectId = nil

do {
_ = try operation.save()
XCTFail("Should have failed")
} catch {
XCTAssertTrue(error.containedIn([.missingObjectId]))
}
}

func testRoleAddOperationSaveSynchronousCustomObjectId() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

ParseSwift.configuration.isAllowingCustomObjectIds = true
var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
let operation = try roles.add([newRole])

var serverResponse = role
serverResponse.createdAt = nil
serverResponse.updatedAt = Date()

let encoded: Data!
do {
encoded = try ParseCoding.jsonEncoder().encode(serverResponse)
//Get dates in correct format from ParseDecoding strategy
serverResponse = try serverResponse.getDecoder().decode(Role<User>.self, from: encoded)
} catch {
XCTFail("Should encode/decode. Error \(error)")
return
}

MockURLProtocol.mockRequests { _ in
return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0)
}

let updatedRole = try operation.save()
XCTAssertEqual(updatedRole.updatedAt, serverResponse.updatedAt)
XCTAssertTrue(updatedRole.hasSameObjectId(as: serverResponse))
}

func testRoleAddOperationSaveSynchronousCustomObjectIdError() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

ParseSwift.configuration.isAllowingCustomObjectIds = true
var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
var operation = try roles.add([newRole])
operation.target.objectId = nil

do {
_ = try operation.save()
XCTFail("Should have failed")
} catch {
XCTAssertTrue(error.containedIn([.missingObjectId]))
}
}

func testRoleAddOperationSaveAsynchronous() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
let operation = try roles.add([newRole])

var serverResponse = role
serverResponse.createdAt = nil
serverResponse.updatedAt = Date()

let encoded: Data!
do {
encoded = try ParseCoding.jsonEncoder().encode(serverResponse)
//Get dates in correct format from ParseDecoding strategy
serverResponse = try serverResponse.getDecoder().decode(Role<User>.self, from: encoded)
} catch {
XCTFail("Should encode/decode. Error \(error)")
return
}

MockURLProtocol.mockRequests { _ in
return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0)
}

let expectation1 = XCTestExpectation(description: "Save object1")
operation.save { result in
switch result {
case .success(let updatedRole):
XCTAssertEqual(updatedRole.updatedAt, serverResponse.updatedAt)
XCTAssertTrue(updatedRole.hasSameObjectId(as: serverResponse))
case .failure(let error):
XCTFail(error.localizedDescription)
}
expectation1.fulfill()
}
wait(for: [expectation1], timeout: 20.0)
}

func testRoleAddOperationSaveAsynchronousError() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

ParseSwift.configuration.isAllowingCustomObjectIds = true
var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
var operation = try roles.add([newRole])
operation.target.objectId = nil

let expectation1 = XCTestExpectation(description: "Save object1")
operation.save { result in
switch result {
case .success:
XCTFail("Should have failed")
case .failure(let error):
XCTAssertEqual(error.code, .missingObjectId)
}
expectation1.fulfill()
}
wait(for: [expectation1], timeout: 20.0)
}

func testRoleAddOperationSaveAsynchronousCustomObjectId() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

ParseSwift.configuration.isAllowingCustomObjectIds = true
var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
let operation = try roles.add([newRole])

var serverResponse = role
serverResponse.createdAt = nil
serverResponse.updatedAt = Date()

let encoded: Data!
do {
encoded = try ParseCoding.jsonEncoder().encode(serverResponse)
//Get dates in correct format from ParseDecoding strategy
serverResponse = try serverResponse.getDecoder().decode(Role<User>.self, from: encoded)
} catch {
XCTFail("Should encode/decode. Error \(error)")
return
}

MockURLProtocol.mockRequests { _ in
return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0)
}

let expectation1 = XCTestExpectation(description: "Save object1")
operation.save { result in
switch result {
case .success(let updatedRole):
XCTAssertEqual(updatedRole.updatedAt, serverResponse.updatedAt)
XCTAssertTrue(updatedRole.hasSameObjectId(as: serverResponse))
case .failure(let error):
XCTFail(error.localizedDescription)
}
expectation1.fulfill()
}
wait(for: [expectation1], timeout: 20.0)
}

func testRoleAddOperationSaveAsynchronousCustomObjectIdError() throws {
var acl = ParseACL()
acl.publicWrite = false
acl.publicRead = true

var role = try Role<User>(name: "Administrator", acl: acl)
role.createdAt = Date()
role.updatedAt = Date()
XCTAssertNil(role.roles) // Shouldn't produce a relation without an objectId.
role.objectId = "yolo"
guard let roles = role.roles else {
XCTFail("Should have unwrapped")
return
}

var newRole = try Role<User>(name: "Moderator", acl: acl)
newRole.objectId = "heel"
var operation = try roles.add([newRole])
operation.target.objectId = nil

let expectation1 = XCTestExpectation(description: "Save object1")
operation.save { result in
switch result {
case .success:
XCTFail("Should have failed")
case .failure(let error):
XCTAssertEqual(error.code, .missingObjectId)
}
expectation1.fulfill()
}
wait(for: [expectation1], timeout: 20.0)
}

func testRoleAddOperationNoKey() throws {
var acl = ParseACL()
acl.publicWrite = false
Expand Down

0 comments on commit 51e16d0

Please sign in to comment.