Skip to content

Commit

Permalink
feat: Add missing become() type methods (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
cbaker6 committed Mar 10, 2023
1 parent ed55608 commit 62eee27
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.0.1...main), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/main/documentation/parseswift)
* _Contributing to this repo? Add info about your change here to be included in the next release_

__New features__
* Add missing async/await and Combine ParseUser.become() type methods ([#66](https://github.com/netreconlab/Parse-Swift/pull/66)), thanks to [Corey Baker](https://github.com/cbaker6).

### 5.0.1
[Full Changelog](https://github.com/netreconlab/Parse-Swift/compare/5.0.0...5.0.1), [Documentation](https://swiftpackageindex.com/netreconlab/Parse-Swift/5.0.1/documentation/parseswift)

Expand Down
19 changes: 19 additions & 0 deletions Sources/ParseSwift/Objects/ParseUser+async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,25 @@ public extension ParseUser {
}
}

/**
Logs in a `ParseUser` *asynchronously* with a session token. On success, this saves the logged in
`ParseUser`with this session to the keychain, so you can retrieve the currently logged in user using
*current*.
- parameter sessionToken: The sessionToken of the user to login.
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- returns: Returns the logged in `ParseUser`.
- throws: An error of type `ParseError`.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
@discardableResult static func become(sessionToken: String,
options: API.Options = []) async throws -> Self {
try await withCheckedThrowingContinuation { continuation in
Self.become(sessionToken: sessionToken, options: options, completion: continuation.resume)
}
}

#if !os(Linux) && !os(Android) && !os(Windows)
/**
Logs in a `ParseUser` *asynchronously* using the session token from the Parse Objective-C SDK Keychain.
Expand Down
18 changes: 18 additions & 0 deletions Sources/ParseSwift/Objects/ParseUser+combine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@ public extension ParseUser {
}
}

/**
Logs in a `ParseUser` *asynchronously* with a session token. On success, this saves the logged in
`ParseUser`with this session to the keychain, so you can retrieve the currently logged in user using
*current*.
- parameter sessionToken: The sessionToken of the user to login.
- parameter options: A set of header options sent to the server. Defaults to an empty set.
- returns: A publisher that eventually produces a single value and then finishes or fails.
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
desires a different policy, it should be inserted in `options`.
*/
static func becomePublisher(sessionToken: String,
options: API.Options = []) -> Future<Self, ParseError> {
Future { promise in
Self.become(sessionToken: sessionToken, options: options, completion: promise)
}
}

#if !os(Linux) && !os(Android) && !os(Windows)
/**
Logs in a `ParseUser` *asynchronously* using the session token from the Parse Objective-C SDK Keychain.
Expand Down
67 changes: 67 additions & 0 deletions Tests/ParseSwiftTests/ParseUserCombineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,73 @@ class ParseUserCombineTests: XCTestCase { // swiftlint:disable:this type_body_le
wait(for: [expectation1], timeout: 20.0)
}

func testBecomeTypeMethod() async throws {
try await login()
MockURLProtocol.removeAll()

let user = try await User.current()
XCTAssertNotNil(user.objectId)

var serverResponse = LoginSignupResponse()
serverResponse.createdAt = user.createdAt
serverResponse.updatedAt = user.updatedAt?.addingTimeInterval(+300)
serverResponse.sessionToken = "newValue"
serverResponse.username = "stop"

var subscriptions = Set<AnyCancellable>()
MockURLProtocol.mockRequests { _ in
do {
let encoded = try serverResponse.getEncoder().encode(serverResponse, skipKeys: .none)
return MockURLResponse(data: encoded, statusCode: 200)
} catch {
return nil
}
}

let expectation1 = XCTestExpectation(description: "Become user1")
let expectation2 = XCTestExpectation(description: "Become user2")
let publisher = User.becomePublisher(sessionToken: serverResponse.sessionToken)
.sink(receiveCompletion: { result in

if case let .failure(error) = result {
XCTFail(error.localizedDescription)
expectation2.fulfill()
}
expectation1.fulfill()

}, receiveValue: { signedUp in
XCTAssertNotNil(signedUp)
XCTAssertNotNil(signedUp.createdAt)
XCTAssertNotNil(signedUp.updatedAt)
XCTAssertNotNil(signedUp.email)
XCTAssertNotNil(signedUp.username)
XCTAssertNil(signedUp.password)
XCTAssertNotNil(signedUp.objectId)
XCTAssertNotNil(signedUp.customKey)
XCTAssertNil(signedUp.ACL)

Task {
do {
let userFromKeychain = try await BaseParseUser.current()
XCTAssertNotNil(userFromKeychain.createdAt)
XCTAssertNotNil(userFromKeychain.updatedAt)
XCTAssertNotNil(userFromKeychain.email)
XCTAssertNotNil(userFromKeychain.username)
XCTAssertNil(userFromKeychain.password)
XCTAssertNotNil(userFromKeychain.objectId)
XCTAssertNil(userFromKeychain.ACL)
} catch {
XCTFail(error.localizedDescription)
}
DispatchQueue.main.async {
expectation2.fulfill()
}
}
})
publisher.store(in: &subscriptions)
wait(for: [expectation1], timeout: 20.0)
}

func testLogout() async throws {
try await login()
MockURLProtocol.removeAll()
Expand Down
47 changes: 47 additions & 0 deletions Tests/ParseSwiftTests/ParseUserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,53 @@ class ParseUserTests: XCTestCase { // swiftlint:disable:this type_body_length
XCTAssertNil(userFromKeychain.ACL)
}

@MainActor
func testBecomeTypeMethod() async throws {
try await login()
MockURLProtocol.removeAll()

let user = try await User.current()

var serverResponse = LoginSignupResponse()
serverResponse.updatedAt = user.updatedAt?.addingTimeInterval(+300)
serverResponse.sessionToken = "newValue"
serverResponse.username = "stop"

MockURLProtocol.mockRequests { _ in
do {
let encoded = try serverResponse.getEncoder().encode(serverResponse, skipKeys: .none)
return MockURLResponse(data: encoded, statusCode: 200)
} catch {
return nil
}
}

guard let sessionToken = serverResponse.sessionToken else {
XCTFail("Should have unwrapped")
return
}
let signedUp = try await User.become(sessionToken: sessionToken)
XCTAssertNotNil(signedUp)
XCTAssertNotNil(signedUp.updatedAt)
XCTAssertNotNil(signedUp.email)
XCTAssertNotNil(signedUp.username)
XCTAssertNil(signedUp.password)
XCTAssertNotNil(signedUp.objectId)
XCTAssertNotNil(signedUp.customKey)
XCTAssertNil(signedUp.ACL)

let userFromKeychain = try await BaseParseUser.current()

XCTAssertNotNil(userFromKeychain.createdAt)
XCTAssertNotNil(userFromKeychain.updatedAt)
XCTAssertNotNil(userFromKeychain.email)
XCTAssertNotNil(userFromKeychain.username)
XCTAssertNil(userFromKeychain.password)
XCTAssertNotNil(userFromKeychain.objectId)
_ = try await BaseParseUser.sessionToken()
XCTAssertNil(userFromKeychain.ACL)
}

@MainActor
func testLogutCommand() async throws {
let command = User.logoutCommand()
Expand Down

0 comments on commit 62eee27

Please sign in to comment.