-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PIA-882: Add unit and integration tests for Login feature on tvOs
- Loading branch information
1 parent
9925103
commit 9eca3a8
Showing
10 changed files
with
727 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// | ||
// CheckLoginAvailabilityTests.swift | ||
// PIA VPN-tvOSTests | ||
// | ||
// Created by Said Rehouni on 29/11/23. | ||
// Copyright © 2023 Private Internet Access Inc. All rights reserved. | ||
// | ||
|
||
import XCTest | ||
@testable import PIA_VPN_tvOS | ||
|
||
final class CheckLoginAvailabilityTests: XCTestCase { | ||
|
||
func test_checkLoginAvailability_returns_success_when_there_is_no_delay() { | ||
// GIVEN | ||
let sut = CheckLoginAvailability() | ||
|
||
// WHEN | ||
let result = sut() | ||
|
||
// THEN | ||
guard case .success = result else { | ||
XCTFail("Expected success, got failure") | ||
return | ||
} | ||
} | ||
|
||
func test_checkLoginAvailability_returns_success_when_delay_expired() { | ||
// GIVEN | ||
let sut = CheckLoginAvailability() | ||
|
||
// WHEN | ||
sut.disableLoginFor(Date().timeIntervalSince1970 - 1) | ||
let result = sut() | ||
|
||
// THEN | ||
guard case .success = result else { | ||
XCTFail("Expected success, got failure") | ||
return | ||
} | ||
} | ||
|
||
func test_checkLoginAvailability_returns_failure_when_delay_has_not_expired_yet() { | ||
// GIVEN | ||
let date = Date() | ||
let sut = CheckLoginAvailability() | ||
|
||
// WHEN | ||
sut.disableLoginFor(date.timeIntervalSince1970 + 10) | ||
let result = sut() | ||
|
||
// THEN | ||
guard case .failure(let error) = result else { | ||
XCTFail("Expected success, got failure") | ||
return | ||
} | ||
|
||
guard case .throttled = error else { | ||
XCTFail("Expected throttled error, got \(error)") | ||
return | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
PIA VPN-tvOSTests/Login/Helpers/CheckLoginAvailabilityMock.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// | ||
// CheckLoginAvailabilityMock.swift | ||
// PIA VPN-tvOSTests | ||
// | ||
// Created by Said Rehouni on 29/11/23. | ||
// Copyright © 2023 Private Internet Access Inc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
@testable import PIA_VPN_tvOS | ||
|
||
class CheckLoginAvailabilityMock: CheckLoginAvailabilityType { | ||
private let result: Result<Void, LoginError> | ||
|
||
init(result: Result<Void, LoginError>) { | ||
self.result = result | ||
} | ||
|
||
func disableLoginFor(_ delay: Double) {} | ||
|
||
func callAsFunction() -> Result<Void, LoginError> { | ||
return result | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// | ||
// Equatable.swift | ||
// PIA VPN-tvOSTests | ||
// | ||
// Created by Said Rehouni on 29/11/23. | ||
// Copyright © 2023 Private Internet Access Inc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
@testable import PIA_VPN_tvOS | ||
import PIALibrary | ||
|
||
extension LoginStatus: Equatable { | ||
public static func == (lhs: LoginStatus, rhs: LoginStatus) -> Bool { | ||
switch (lhs, rhs) { | ||
case (.none, .none), (.isLogging, .isLogging): | ||
return true | ||
case let (.failed(lhsError), .failed(rhsError)): | ||
return lhsError == rhsError | ||
case let (.succeeded(lhsAccount), .succeeded(rhsAccount)): | ||
return lhsAccount == rhsAccount | ||
default: | ||
return false | ||
} | ||
} | ||
} | ||
|
||
extension LoginError: Equatable { | ||
public static func == (lhs: LoginError, rhs: LoginError) -> Bool { | ||
switch (lhs, rhs) { | ||
case (.unauthorized, .unauthorized), (.expired, .expired), (.usernameWrongFormat, .usernameWrongFormat), (.passwordWrongFormat, .passwordWrongFormat): | ||
return true | ||
case let (.throttled(lhsDelay), .throttled(rhsDelay)): | ||
return lhsDelay == rhsDelay | ||
default: | ||
return false | ||
} | ||
} | ||
} | ||
|
||
extension UserAccount: Equatable { | ||
public static func == (lhs: PIALibrary.UserAccount, rhs: PIALibrary.UserAccount) -> Bool { | ||
lhs.credentials == rhs.credentials | ||
&& lhs.info == rhs.info | ||
} | ||
} | ||
|
||
extension Credentials: Equatable { | ||
public static func == (lhs: Credentials, rhs: Credentials) -> Bool { | ||
lhs.username == rhs.username && lhs.password == rhs.password | ||
} | ||
} | ||
|
||
extension AccountInfo: Equatable { | ||
public static func == (lhs: AccountInfo, rhs: AccountInfo) -> Bool { | ||
lhs.email == rhs.email | ||
&& lhs.username == rhs.username | ||
&& lhs.plan == rhs.plan | ||
&& lhs.productId == rhs.productId | ||
&& lhs.isRenewable == rhs.isRenewable | ||
&& lhs.isRecurring == rhs.isRecurring | ||
&& lhs.expirationDate == rhs.expirationDate | ||
&& lhs.canInvite == rhs.canInvite | ||
&& lhs.isExpired == rhs.isExpired | ||
&& lhs.shouldPresentExpirationAlert == rhs.shouldPresentExpirationAlert | ||
&& lhs.renewUrl == rhs.renewUrl | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// | ||
// LoginProviderMock.swift | ||
// PIA VPN-tvOSTests | ||
// | ||
// Created by Said Rehouni on 4/12/23. | ||
// Copyright © 2023 Private Internet Access Inc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import PIALibrary | ||
@testable import PIA_VPN_tvOS | ||
|
||
class LoginProviderMock: LoginProviderType { | ||
private let userResult: UserAccount? | ||
private let errorResult: Error? | ||
|
||
init(userResult: UserAccount?, errorResult: Error?) { | ||
self.userResult = userResult | ||
self.errorResult = errorResult | ||
} | ||
|
||
func login(with request: LoginRequest, _ callback: LibraryCallback<UserAccount>?) { | ||
callback?(userResult, errorResult) | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
PIA VPN-tvOSTests/Login/Helpers/LoginWithCredentialsUseCaseMock.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// | ||
// LoginWithCredentialsUseCaseMock.swift | ||
// PIA VPN-tvOSTests | ||
// | ||
// Created by Said Rehouni on 29/11/23. | ||
// Copyright © 2023 Private Internet Access Inc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
@testable import PIA_VPN_tvOS | ||
import PIALibrary | ||
|
||
class LoginWithCredentialsUseCaseMock: LoginWithCredentialsUseCaseType { | ||
private let result: Result<UserAccount, LoginError> | ||
|
||
init(result: Result<UserAccount, LoginError>) { | ||
self.result = result | ||
} | ||
|
||
func execute(username: String, password: String, completion: @escaping (Result<UserAccount, LoginError>) -> Void) { | ||
completion(result) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// | ||
// Stubs.swift | ||
// PIA VPN-tvOSTests | ||
// | ||
// Created by Said Rehouni on 29/11/23. | ||
// Copyright © 2023 Private Internet Access Inc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import PIALibrary | ||
import account | ||
|
||
extension UserAccount { | ||
static func makeStub() -> UserAccount { | ||
let credentials = Credentials(username: "username", | ||
password: "password") | ||
return UserAccount(credentials: credentials, | ||
info: AccountInfo.makeStub()) | ||
} | ||
} | ||
|
||
extension AccountInfo { | ||
static func makeStub() -> AccountInfo { | ||
let account = AccountInformation(active: true, | ||
canInvite: true, | ||
canceled: true, | ||
daysRemaining: 0, | ||
email: "email", | ||
expirationTime: 0, | ||
expireAlert: true, | ||
expired: true, | ||
needsPayment: true, | ||
plan: "monthly", | ||
productId: "productId", | ||
recurring: true, | ||
renewUrl: "renewUrl", | ||
renewable: true, | ||
username: "username") | ||
|
||
return AccountInfo(accountInformation: account) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// | ||
// LoginIntegrationTests.swift | ||
// PIA VPN-tvOSTests | ||
// | ||
// Created by Said Rehouni on 11/12/23. | ||
// Copyright © 2023 Private Internet Access Inc. All rights reserved. | ||
// | ||
|
||
import XCTest | ||
import PIALibrary | ||
@testable import PIA_VPN_tvOS | ||
|
||
final class LoginIntegrationTests: XCTestCase { | ||
|
||
func test_login_succeeds() async throws { | ||
// GIVEN | ||
let userAccount = UserAccount.makeStub() | ||
let loginProviderMock = LoginProviderMock(userResult: userAccount, errorResult: nil) | ||
let loginWithCredentialsUseCase = LoginWithCredentialsUseCase(loginProvider: loginProviderMock, | ||
errorMapper: LoginDomainErrorMapper()) | ||
|
||
let sut = LoginViewModel(loginWithCredentialsUseCase: loginWithCredentialsUseCase, | ||
checkLoginAvailability: CheckLoginAvailability(), | ||
validateLoginCredentials: ValidateCredentialsFormat(), | ||
errorMapper: LoginPresentableErrorMapper()) | ||
|
||
XCTAssertEqual(sut.loginStatus, .none) | ||
|
||
// WHEN | ||
await sut.login(username: "username", password: "password") | ||
|
||
// THEN | ||
XCTAssertEqual(sut.loginStatus, LoginStatus.succeeded(userAccount: userAccount)) | ||
} | ||
|
||
func test_login_fails() async throws { | ||
// GIVEN | ||
let userAccount = UserAccount.makeStub() | ||
let loginProviderMock = LoginProviderMock(userResult: userAccount, errorResult: ClientError.expired) | ||
let loginWithCredentialsUseCase = LoginWithCredentialsUseCase(loginProvider: loginProviderMock, | ||
errorMapper: LoginDomainErrorMapper()) | ||
|
||
let sut = LoginViewModel(loginWithCredentialsUseCase: loginWithCredentialsUseCase, | ||
checkLoginAvailability: CheckLoginAvailability(), | ||
validateLoginCredentials: ValidateCredentialsFormat(), | ||
errorMapper: LoginPresentableErrorMapper()) | ||
|
||
XCTAssertEqual(sut.loginStatus, .none) | ||
|
||
// WHEN | ||
await sut.login(username: "username", password: "password") | ||
|
||
// THEN | ||
XCTAssertEqual(sut.loginStatus, .failed(error: .expired)) | ||
} | ||
} |
Oops, something went wrong.