-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use test doubles AccountSettingsServiceTests (#20862)
- Loading branch information
Showing
9 changed files
with
217 additions
and
118 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
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
77 changes: 77 additions & 0 deletions
77
WordPress/WordPressTest/AccountSettingsRemoteInterfaceStub.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,77 @@ | ||
@testable import WordPress | ||
import WordPressKit | ||
|
||
class AccountSettingsRemoteInterfaceStub: AccountSettingsRemoteInterface { | ||
|
||
let updateSettingResult: Result<(), Error> | ||
let getSettingsResult: Result<AccountSettings, Error> | ||
let changeUsernameShouldSucceed: Bool | ||
let suggestUsernamesResult: [String] | ||
let updatePasswordResult: Result<(), Error> | ||
let closeAccountResult: Result<(), Error> | ||
|
||
init( | ||
updateSettingResult: Result<Void, Error> = .success(()), | ||
// Defaulting to failure to avoid having to create AccountSettings here, because it required an NSManagedContext | ||
getSettingsResult: Result<AccountSettings, Error> = .failure(TestError()), | ||
changeUsernameShouldSucceed: Bool = true, | ||
suggestUsernamesResult: [String] = [], | ||
updatePasswordResult: Result<Void, Error> = .success(()), | ||
closeAccountResult: Result<Void, Error> = .success(()) | ||
) { | ||
self.updateSettingResult = updateSettingResult | ||
self.getSettingsResult = getSettingsResult | ||
self.changeUsernameShouldSucceed = changeUsernameShouldSucceed | ||
self.suggestUsernamesResult = suggestUsernamesResult | ||
self.updatePasswordResult = updatePasswordResult | ||
self.closeAccountResult = closeAccountResult | ||
} | ||
|
||
func updateSetting(_ change: AccountSettingsChange, success: @escaping () -> Void, failure: @escaping (Error) -> Void) { | ||
switch updateSettingResult { | ||
case .success: | ||
success() | ||
case .failure(let error): | ||
failure(error) | ||
} | ||
} | ||
|
||
func getSettings(success: @escaping (WordPressKit.AccountSettings) -> Void, failure: @escaping (Error) -> Void) { | ||
switch getSettingsResult { | ||
case .success(let settings): | ||
success(settings) | ||
case .failure(let error): | ||
failure(error) | ||
} | ||
} | ||
|
||
func changeUsername(to username: String, success: @escaping () -> Void, failure: @escaping () -> Void) { | ||
if changeUsernameShouldSucceed { | ||
success() | ||
} else { | ||
failure() | ||
} | ||
} | ||
|
||
func suggestUsernames(base: String, finished: @escaping ([String]) -> Void) { | ||
finished(suggestUsernamesResult) | ||
} | ||
|
||
func updatePassword(_ password: String, success: @escaping () -> Void, failure: @escaping (Error) -> Void) { | ||
switch updatePasswordResult { | ||
case .success: | ||
success() | ||
case .failure(let error): | ||
failure(error) | ||
} | ||
} | ||
|
||
func closeAccount(success: @escaping () -> Void, failure: @escaping (Error) -> Void) { | ||
switch closeAccountResult { | ||
case .success: | ||
success() | ||
case .failure(let error): | ||
failure(error) | ||
} | ||
} | ||
} |
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 |
---|---|---|
|
@@ -8,25 +8,10 @@ class AccountSettingsServiceTests: CoreDataTestCase { | |
private var service: AccountSettingsService! | ||
|
||
override func setUp() { | ||
let account = WPAccount(context: mainContext) | ||
account.username = "test" | ||
account.authToken = "token" | ||
account.userID = 1 | ||
account.uuid = UUID().uuidString | ||
|
||
let settings = ManagedAccountSettings(context: mainContext) | ||
settings.account = account | ||
settings.username = "Username" | ||
settings.displayName = "Display Name" | ||
settings.primarySiteID = 1 | ||
settings.aboutMe = "<empty>" | ||
settings.email = "[email protected]" | ||
settings.firstName = "Test" | ||
settings.lastName = "User" | ||
settings.language = "en" | ||
settings.webAddress = "https://test.wordpress.com" | ||
|
||
let account = WPAccount.fixture(context: mainContext) | ||
_ = makeManagedAccountSettings(context: mainContext, account: account) | ||
contextManager.saveContextAndWait(mainContext) | ||
service = makeService(contextManager: contextManager, account: account) | ||
|
||
service = AccountSettingsService( | ||
userID: account.userID.intValue, | ||
|
@@ -35,41 +20,44 @@ class AccountSettingsServiceTests: CoreDataTestCase { | |
) | ||
} | ||
|
||
private func managedAccountSettings() -> ManagedAccountSettings? { | ||
contextManager.performQuery { context in | ||
let request = NSFetchRequest<NSFetchRequestResult>(entityName: ManagedAccountSettings.entityName()) | ||
request.predicate = NSPredicate(format: "account.userID = %d", self.service.userID) | ||
request.fetchLimit = 1 | ||
guard let results = (try? context.fetch(request)) as? [ManagedAccountSettings] else { | ||
return nil | ||
} | ||
return results.first | ||
} | ||
} | ||
|
||
func testUpdateSuccess() throws { | ||
stub(condition: isPath("/rest/v1.1/me/settings")) { _ in | ||
HTTPStubsResponse(jsonObject: [String: Any](), statusCode: 200, headers: nil) | ||
} | ||
// We've seen some flakiness in CI on this test, and therefore are using a stub object rather than stubbing the HTTP requests. | ||
// Since this approach bypasses the entire network stack, the hope is that it'll result in a more robust test. | ||
// | ||
// This is the second test in this class edited this way. | ||
// If we'll need to update a third, we shall also take the time to update the rest of the tests. | ||
let service = AccountSettingsService( | ||
userID: 1, | ||
remote: AccountSettingsRemoteInterfaceStub(updateSettingResult: .success(())), | ||
coreDataStack: contextManager | ||
) | ||
|
||
waitUntil { done in | ||
self.service.saveChange(.firstName("Updated"), finished: { success in | ||
service.saveChange(.firstName("Updated"), finished: { success in | ||
expect(success).to(beTrue()) | ||
done() | ||
}) | ||
} | ||
|
||
expect(self.managedAccountSettings()?.firstName).to(equal("Updated")) | ||
} | ||
|
||
func testUpdateFailure() throws { | ||
stub(condition: isPath("/rest/v1.1/me/settings")) { _ in | ||
HTTPStubsResponse(jsonObject: [String: Any](), statusCode: 500, headers: nil) | ||
} | ||
// We've seen some flakiness in CI on this test, and therefore are using a stub object rather than stubbing the HTTP requests. | ||
// Since this approach bypasses the entire network stack, the hope is that it'll result in a more robust test. | ||
let service = AccountSettingsService( | ||
userID: 1, | ||
remote: AccountSettingsRemoteInterfaceStub(updateSettingResult: .failure(TestError())), | ||
coreDataStack: contextManager | ||
) | ||
|
||
waitUntil { done in | ||
self.service.saveChange(.firstName("Updated"), finished: { success in | ||
service.saveChange(.firstName("Updated"), finished: { success in | ||
expect(success).to(beFalse()) | ||
done() | ||
}) | ||
} | ||
|
||
expect(self.managedAccountSettings()?.firstName).to(equal("Test")) | ||
} | ||
|
||
|
@@ -100,3 +88,44 @@ class AccountSettingsServiceTests: CoreDataTestCase { | |
wait(for: [notCrash], timeout: 0.5) | ||
} | ||
} | ||
|
||
extension AccountSettingsServiceTests { | ||
|
||
private func makeManagedAccountSettings( | ||
context: NSManagedObjectContext, | ||
account: WPAccount | ||
) -> ManagedAccountSettings { | ||
let settings = ManagedAccountSettings(context: context) | ||
settings.account = account | ||
settings.username = "Username" | ||
settings.displayName = "Display Name" | ||
settings.primarySiteID = 1 | ||
settings.aboutMe = "<empty>" | ||
settings.email = "[email protected]" | ||
settings.firstName = "Test" | ||
settings.lastName = "User" | ||
settings.language = "en" | ||
settings.webAddress = "https://test.wordpress.com" | ||
return settings | ||
} | ||
|
||
private func makeService(contextManager: ContextManager, account: WPAccount) -> AccountSettingsService { | ||
AccountSettingsService( | ||
userID: account.userID.intValue, | ||
remote: AccountSettingsRemote(wordPressComRestApi: account.wordPressComRestApi), | ||
coreDataStack: contextManager | ||
) | ||
} | ||
|
||
private func managedAccountSettings() -> ManagedAccountSettings? { | ||
contextManager.performQuery { context in | ||
let request = NSFetchRequest<NSFetchRequestResult>(entityName: ManagedAccountSettings.entityName()) | ||
request.predicate = NSPredicate(format: "account.userID = %d", self.service.userID) | ||
request.fetchLimit = 1 | ||
guard let results = (try? context.fetch(request)) as? [ManagedAccountSettings] else { | ||
return nil | ||
} | ||
return results.first | ||
} | ||
} | ||
} |
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
Oops, something went wrong.