-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PIA-1932: Migrate delete account API to native
- Loading branch information
1 parent
48ea3f2
commit a0321c5
Showing
7 changed files
with
245 additions
and
23 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
24 changes: 24 additions & 0 deletions
24
Sources/PIALibrary/Account/Data/Networking/DeleteAccountRequestConfiguration.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 @@ | ||
|
||
|
||
import Foundation | ||
import NWHttpConnection | ||
|
||
struct DeleteAccountRequestConfiguration: NetworkRequestConfigurationType { | ||
|
||
let networkRequestModule: NetworkRequestModule = .account | ||
let path: RequestAPI.Path = .deleteAccount | ||
let httpMethod: NWHttpConnection.NWConnectionHTTPMethod = .delete | ||
let contentType: NetworkRequestContentType = .json | ||
let inlcudeAuthHeaders: Bool = true | ||
let urlQueryParameters: [String : String]? = nil | ||
let responseDataType: NWDataResponseType = .jsonData | ||
|
||
var otherHeaders: [String : String]? = nil | ||
var body: Data? = nil | ||
|
||
let timeout: TimeInterval = 10 | ||
let requestQueue: DispatchQueue? = DispatchQueue(label: "deleteAccount_request.queue") | ||
} | ||
|
||
|
||
|
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
57 changes: 57 additions & 0 deletions
57
Sources/PIALibrary/Account/Domain/UseCases/DeleteAccountUseCase.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,57 @@ | ||
|
||
import Foundation | ||
|
||
|
||
protocol DeleteAccountUseCaseType { | ||
typealias Completion = ((NetworkRequestError?) -> Void) | ||
func callAsFunction(completion: @escaping Completion) | ||
} | ||
|
||
|
||
class DeleteAccountUseCase: DeleteAccountUseCaseType { | ||
|
||
let networkClient: NetworkRequestClientType | ||
let refreshAuthTokenChecker: RefreshAuthTokensCheckerType | ||
let apiTokenProvider: APITokenProviderType | ||
let vpnTokenProvider: VpnTokenProviderType | ||
|
||
init(networkClient: NetworkRequestClientType, refreshAuthTokenChecker: RefreshAuthTokensCheckerType, apiTokenProvider: APITokenProviderType, vpnTokenProvider: VpnTokenProviderType) { | ||
self.networkClient = networkClient | ||
self.refreshAuthTokenChecker = refreshAuthTokenChecker | ||
self.apiTokenProvider = apiTokenProvider | ||
self.vpnTokenProvider = vpnTokenProvider | ||
} | ||
|
||
|
||
func callAsFunction(completion: @escaping Completion) { | ||
refreshAuthTokenChecker.refreshIfNeeded { [weak self] error in | ||
guard let self else { return } | ||
if let error { | ||
completion(error) | ||
} else { | ||
self.executeRequest(with: completion) | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
extension DeleteAccountUseCase { | ||
func executeRequest(with completion: @escaping Completion) { | ||
let configuration = DeleteAccountRequestConfiguration() | ||
networkClient.executeRequest(with: configuration) { [weak self] error, response in | ||
|
||
guard let self else { return } | ||
|
||
if let error { | ||
completion(error) | ||
} else { | ||
self.apiTokenProvider.clearAPIToken() | ||
self.vpnTokenProvider.clearVpnToken() | ||
completion(nil) | ||
} | ||
|
||
|
||
} | ||
} | ||
} |
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
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
149 changes: 149 additions & 0 deletions
149
Tests/PIALibraryTests/Accounts/DeleteAccountUseCaseTests.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,149 @@ | ||
import XCTest | ||
@testable import PIALibrary | ||
|
||
class DeleteAccountUseCaseTests: XCTestCase { | ||
class Fixture { | ||
let networkClientMock = NetworkRequestClientMock() | ||
let refreshAuthTokenCheckerMock = RefreshAuthTokensCheckerMock() | ||
let apiTokenProviderMock = APITokenProviderMock() | ||
let vpnTokenProviderMock = VpnTokenProviderMock() | ||
|
||
func stubNetworkRequestSuccessfulResponse() { | ||
networkClientMock.executeRequestResponse = NetworkRequestResponseMock(statusCode: 200) | ||
networkClientMock.executeRequestError = nil | ||
} | ||
|
||
func stubNetworkRequestResponseWithError(_ error: NetworkRequestError) { | ||
networkClientMock.executeRequestError = error | ||
} | ||
|
||
func stubRefreshAuthTokensWithSuccess() { | ||
refreshAuthTokenCheckerMock.refreshIfNeededError = nil | ||
} | ||
|
||
func stubRefreshAuthTokensFailsWithError(_ error: NetworkRequestError) { | ||
refreshAuthTokenCheckerMock.refreshIfNeededError = error | ||
} | ||
} | ||
|
||
var fixture: Fixture! | ||
var sut: DeleteAccountUseCase! | ||
|
||
override func setUp() { | ||
fixture = Fixture() | ||
} | ||
|
||
override func tearDown() { | ||
fixture = nil | ||
sut = nil | ||
} | ||
|
||
private func instantiateSut() { | ||
sut = DeleteAccountUseCase(networkClient: fixture.networkClientMock, refreshAuthTokenChecker: fixture.refreshAuthTokenCheckerMock, apiTokenProvider: fixture.apiTokenProviderMock, vpnTokenProvider: fixture.vpnTokenProviderMock) | ||
} | ||
|
||
func test_delete_account_when_network_request_succeeds() { | ||
// GIVEN that the network request succeeds | ||
fixture.stubNetworkRequestSuccessfulResponse() | ||
// AND refreshing the auth tokens also succeeds | ||
fixture.stubRefreshAuthTokensWithSuccess() | ||
|
||
instantiateSut() | ||
|
||
let expectation = expectation(description: "Delete account request is executed") | ||
var capturedError: NetworkRequestError? | ||
// WHEN exectuting the delete account request | ||
sut() { error in | ||
capturedError = error | ||
expectation.fulfill() | ||
} | ||
|
||
wait(for: [expectation], timeout: 3) | ||
|
||
// THEN the refresh auth tokens if needed request is called | ||
XCTAssertEqual(fixture.refreshAuthTokenCheckerMock.refreshIfNeededCalledAttempt, 1) | ||
|
||
let executedRequest = fixture.networkClientMock.executeRequestWithConfiguation! | ||
// AND the delete account request is executed | ||
XCTAssertEqual(fixture.networkClientMock.executeRequestCalledAttempt, 1) | ||
XCTAssertEqual(executedRequest.path, RequestAPI.Path.deleteAccount) | ||
XCTAssertEqual(executedRequest.httpMethod, .delete) | ||
|
||
// AND no error is retured | ||
XCTAssertNil(capturedError) | ||
|
||
// AND the auth tokens ARE removed | ||
XCTAssertEqual(fixture.apiTokenProviderMock.clearAPITokenCalledAttempt, 1) | ||
XCTAssertEqual(fixture.vpnTokenProviderMock.clearVpnTokenCalledAttempt, 1) | ||
|
||
} | ||
|
||
func test_delete_account_when_network_request_fails() { | ||
// GIVEN that the network request fails | ||
fixture.stubNetworkRequestResponseWithError(.allConnectionAttemptsFailed(statusCode: 401)) | ||
// AND refreshing the auth tokens succeeds | ||
fixture.stubRefreshAuthTokensWithSuccess() | ||
|
||
instantiateSut() | ||
|
||
let expectation = expectation(description: "Delete account request is executed") | ||
var capturedError: NetworkRequestError? | ||
// WHEN exectuting the delete account request | ||
sut() { error in | ||
capturedError = error | ||
expectation.fulfill() | ||
} | ||
|
||
wait(for: [expectation], timeout: 3) | ||
|
||
// THEN the refresh auth tokens if needed request is called | ||
XCTAssertEqual(fixture.refreshAuthTokenCheckerMock.refreshIfNeededCalledAttempt, 1) | ||
|
||
let executedRequest = fixture.networkClientMock.executeRequestWithConfiguation! | ||
// AND the delete account request is executed | ||
XCTAssertEqual(fixture.networkClientMock.executeRequestCalledAttempt, 1) | ||
XCTAssertEqual(executedRequest.path, RequestAPI.Path.deleteAccount) | ||
XCTAssertEqual(executedRequest.httpMethod, .delete) | ||
|
||
// AND an error IS retured | ||
XCTAssertNotNil(capturedError) | ||
|
||
// AND the auth tokens are NOT removed | ||
XCTAssertEqual(fixture.apiTokenProviderMock.clearAPITokenCalledAttempt, 0) | ||
XCTAssertEqual(fixture.vpnTokenProviderMock.clearVpnTokenCalledAttempt, 0) | ||
|
||
} | ||
|
||
func test_delete_account_when_refreshAuthTokens_request_fails() { | ||
|
||
// GIVEN that refreshing the auth tokens fails | ||
fixture.stubRefreshAuthTokensFailsWithError(.allConnectionAttemptsFailed(statusCode: 401)) | ||
|
||
instantiateSut() | ||
|
||
let expectation = expectation(description: "Delete account request is executed") | ||
var capturedError: NetworkRequestError? | ||
// WHEN exectuting the delete account request | ||
sut() { error in | ||
capturedError = error | ||
expectation.fulfill() | ||
} | ||
|
||
wait(for: [expectation], timeout: 3) | ||
|
||
// THEN the refresh auth tokens if needed request is called | ||
XCTAssertEqual(fixture.refreshAuthTokenCheckerMock.refreshIfNeededCalledAttempt, 1) | ||
|
||
// AND the delete account request is NOT executed | ||
XCTAssertEqual(fixture.networkClientMock.executeRequestCalledAttempt, 0) | ||
|
||
// AND an error IS retured | ||
XCTAssertNotNil(capturedError) | ||
|
||
// AND the auth tokens are NOT removed | ||
XCTAssertEqual(fixture.apiTokenProviderMock.clearAPITokenCalledAttempt, 0) | ||
XCTAssertEqual(fixture.vpnTokenProviderMock.clearVpnTokenCalledAttempt, 0) | ||
|
||
} | ||
|
||
} |