Do not return Result (or anything else) from command run(…) functions.

Throw when failure. Normal Void return when success.

Signed-off-by: Ross Goldberg <484615+rgoldberg@users.noreply.github.com>
This commit is contained in:
Ross Goldberg 2024-10-01 21:54:15 -04:00
parent 3b86deb63e
commit 388d963cd1
No known key found for this signature in database
34 changed files with 111 additions and 331 deletions

View file

@ -17,24 +17,16 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = runInternal()
if case .failure = result {
try result.get()
}
}
func runInternal() -> Result<Void, MASError> {
if #available(macOS 12, *) {
// Account information is no longer available as of Monterey.
// https://github.com/mas-cli/mas/issues/417
return .failure(.notSupported)
throw MASError.notSupported
}
do {
print(try ISStoreAccount.primaryAccount.wait().identifier)
return .success(())
} catch {
return .failure(error as? MASError ?? .failed(error: error as NSError))
throw error as? MASError ?? MASError.failed(error: error as NSError)
}
}
}

View file

@ -21,38 +21,29 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
if case .failure = result {
try result.get()
}
try run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
}
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) -> Result<Void, MASError> {
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) throws {
do {
guard let result = try storeSearch.lookup(app: appId).wait() else {
return .failure(.noSearchResultsFound)
throw MASError.noSearchResultsFound
}
do {
try openCommand.run(arguments: result.trackViewUrl)
} catch {
printError("Unable to launch open command")
return .failure(.searchFailed)
throw MASError.searchFailed
}
if openCommand.failed {
let reason = openCommand.process.terminationReason
printError("Open failed: (\(reason)) \(openCommand.stderr)")
return .failure(.searchFailed)
throw MASError.searchFailed
}
} catch {
// Bubble up MASErrors
if let error = error as? MASError {
return .failure(error)
}
return .failure(.searchFailed)
throw error as? MASError ?? .searchFailed
}
return .success(())
}
}
}

View file

@ -22,28 +22,19 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(storeSearch: MasStoreSearch())
if case .failure = result {
try result.get()
}
try run(storeSearch: MasStoreSearch())
}
func run(storeSearch: StoreSearch) -> Result<Void, MASError> {
func run(storeSearch: StoreSearch) throws {
do {
guard let result = try storeSearch.lookup(app: appId).wait() else {
return .failure(.noSearchResultsFound)
throw MASError.noSearchResultsFound
}
print(AppInfoFormatter.format(app: result))
} catch {
// Bubble up MASErrors
if let error = error as? MASError {
return .failure(error)
}
return .failure(.searchFailed)
throw error as? MASError ?? .searchFailed
}
return .success(())
}
}
}

View file

@ -23,13 +23,10 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(appLibrary: MasAppLibrary())
if case .failure = result {
try result.get()
}
try run(appLibrary: MasAppLibrary())
}
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
func run(appLibrary: AppLibrary) throws {
// Try to download applications with given identifiers and collect results
let appIds = appIds.filter { appId in
if let product = appLibrary.installedApp(forId: appId), !force {
@ -43,10 +40,8 @@ extension Mas {
do {
try downloadAll(appIds).wait()
} catch {
return .failure(error as? MASError ?? .downloadFailed(error: error as NSError))
throw error as? MASError ?? .downloadFailed(error: error as NSError)
}
return .success(())
}
}
}

View file

@ -17,23 +17,16 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(appLibrary: MasAppLibrary())
if case .failure = result {
try result.get()
}
try run(appLibrary: MasAppLibrary())
}
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
func run(appLibrary: AppLibrary) throws {
let products = appLibrary.installedApps
if products.isEmpty {
printError("No installed apps found")
return .success(())
} else {
print(AppListFormatter.format(products: products))
}
let output = AppListFormatter.format(products: products)
print(output)
return .success(())
}
}
}

View file

@ -24,34 +24,27 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
if case .failure = result {
try result.get()
}
try run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
}
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) -> Result<Void, MASError> {
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) throws {
var appId: Int?
do {
let results = try storeSearch.search(for: appName).wait()
guard let result = results.first else {
printError("No results found")
return .failure(.noSearchResultsFound)
throw MASError.noSearchResultsFound
}
appId = result.trackId
} catch {
// Bubble up MASErrors
if let error = error as? MASError {
return .failure(error)
}
return .failure(.searchFailed)
throw error as? MASError ?? .searchFailed
}
guard let identifier = appId else { fatalError() }
return install(UInt64(identifier), appLibrary: appLibrary)
try install(UInt64(identifier), appLibrary: appLibrary)
}
/// Installs an app.
@ -59,21 +52,17 @@ extension Mas {
/// - Parameters:
/// - appId: App identifier
/// - appLibrary: Library of installed apps
/// - Returns: Result of the operation.
fileprivate func install(_ appId: UInt64, appLibrary: AppLibrary) -> Result<Void, MASError> {
fileprivate func install(_ appId: UInt64, appLibrary: AppLibrary) throws {
// Try to download applications with given identifiers and collect results
if let product = appLibrary.installedApp(forId: appId), !force {
printWarning("\(product.appName) is already installed")
return .success(())
} else {
do {
try downloadAll([appId]).wait()
} catch {
throw error as? MASError ?? .downloadFailed(error: error as NSError)
}
}
do {
try downloadAll([appId]).wait()
} catch {
return .failure(error as? MASError ?? .downloadFailed(error: error as NSError))
}
return .success(())
}
}
}

View file

@ -25,34 +25,31 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
if case .failure = result {
try result.get()
}
try run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
}
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) -> Result<Void, MASError> {
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) throws {
do {
if appId == markerValue {
// If no app ID is given, just open the MAS GUI app
try openCommand.run(arguments: masScheme + "://")
return .success(())
return
}
guard let appId = Int(appId)
else {
printError("Invalid app ID")
return .failure(.noSearchResultsFound)
throw MASError.noSearchResultsFound
}
guard let result = try storeSearch.lookup(app: appId).wait()
else {
return .failure(.noSearchResultsFound)
throw MASError.noSearchResultsFound
}
guard var url = URLComponents(string: result.trackViewUrl)
else {
return .failure(.searchFailed)
throw MASError.searchFailed
}
url.scheme = masScheme
@ -60,22 +57,16 @@ extension Mas {
try openCommand.run(arguments: url.string!)
} catch {
printError("Unable to launch open command")
return .failure(.searchFailed)
throw MASError.searchFailed
}
if openCommand.failed {
let reason = openCommand.process.terminationReason
printError("Open failed: (\(reason)) \(openCommand.stderr)")
return .failure(.searchFailed)
throw MASError.searchFailed
}
} catch {
// Bubble up MASErrors
if let error = error as? MASError {
return .failure(error)
}
return .failure(.searchFailed)
throw error as? MASError ?? .searchFailed
}
return .success(())
}
}
}

View file

@ -25,13 +25,10 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
if case .failure = result {
try result.get()
}
try run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
}
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) -> Result<Void, MASError> {
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) throws {
let promises = appLibrary.installedApps.map { installedApp in
firstly {
storeSearch.lookup(app: installedApp.itemIdentifier.intValue)
@ -59,12 +56,11 @@ extension Mas {
}
}
return firstly {
_ = firstly {
when(fulfilled: promises)
}.map {
Result<Void, MASError>.success(())
}.recover { error in
// Bubble up MASErrors
.value(Result<Void, MASError>.failure(error as? MASError ?? .searchFailed))
}.wait()
}

View file

@ -20,13 +20,10 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(appLibrary: MasAppLibrary())
if case .failure = result {
try result.get()
}
try run(appLibrary: MasAppLibrary())
}
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
func run(appLibrary: AppLibrary) throws {
// Try to download applications with given identifiers and collect results
let appIds = appIds.filter { appId in
if let product = appLibrary.installedApp(forId: appId) {
@ -40,10 +37,8 @@ extension Mas {
do {
try downloadAll(appIds, purchase: true).wait()
} catch {
return .failure(error as? MASError ?? .downloadFailed(error: error as NSError))
throw error as? MASError ?? .downloadFailed(error: error as NSError)
}
return .success(())
}
}
}

View file

@ -21,13 +21,6 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = runInternal()
if case .failure = result {
try result.get()
}
}
func runInternal() -> Result<Void, MASError> {
// The "Reset Application" command in the Mac App Store debug menu performs
// the following steps
//
@ -81,8 +74,6 @@ extension Mas {
}
}
}
return .success(())
}
}
}

View file

@ -22,29 +22,20 @@ extension Mas {
var appName: String
func run() throws {
let result = run(storeSearch: MasStoreSearch())
if case .failure = result {
try result.get()
}
try run(storeSearch: MasStoreSearch())
}
func run(storeSearch: StoreSearch) -> Result<Void, MASError> {
func run(storeSearch: StoreSearch) throws {
do {
let results = try storeSearch.search(for: appName).wait()
if results.isEmpty {
return .failure(.noSearchResultsFound)
throw MASError.noSearchResultsFound
}
let output = SearchResultFormatter.format(results: results, includePrice: price)
print(output)
return .success(())
} catch {
// Bubble up MASErrors
if let error = error as? MASError {
return .failure(error)
}
return .failure(.searchFailed)
throw error as? MASError ?? .searchFailed
}
}
}

View file

@ -25,18 +25,10 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = runInternal()
if case .failure = result {
try result.get()
}
}
func runInternal() -> Result<Void, MASError> {
do {
_ = try ISStoreAccount.signIn(username: username, password: password, systemDialog: dialog).wait()
return .success(())
} catch {
return .failure(error as? MASError ?? .signInFailed(error: error as NSError))
throw error as? MASError ?? MASError.signInFailed(error: error as NSError)
}
}
}

View file

@ -18,13 +18,6 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = runInternal()
if case .failure = result {
try result.get()
}
}
func runInternal() -> Result<Void, MASError> {
if #available(macOS 10.13, *) {
ISServiceProxy.genericShared().accountService.signOut()
} else {
@ -32,8 +25,6 @@ extension Mas {
// https://github.com/mas-cli/mas/issues/129
CKAccountStore.shared().signOut()
}
return .success(())
}
}
}

View file

@ -25,33 +25,26 @@ extension Mas {
/// Runs the uninstall command.
func run() throws {
let result = run(appLibrary: MasAppLibrary())
if case .failure = result {
try result.get()
}
try run(appLibrary: MasAppLibrary())
}
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
func run(appLibrary: AppLibrary) throws {
let appId = UInt64(appId)
guard let product = appLibrary.installedApp(forId: appId) else {
return .failure(.notInstalled)
throw MASError.notInstalled
}
if dryRun {
printInfo("\(product.appName) \(product.bundlePath)")
printInfo("(not removed, dry run)")
return .success(())
} else {
do {
try appLibrary.uninstallApp(app: product)
} catch {
throw MASError.uninstallFailed
}
}
do {
try appLibrary.uninstallApp(app: product)
} catch {
return .failure(.uninstallFailed)
}
return .success(())
}
}
}

View file

@ -10,8 +10,6 @@ import ArgumentParser
import Foundation
import PromiseKit
import enum Swift.Result
extension Mas {
/// Command which upgrades apps with new versions available in the Mac App Store.
struct Upgrade: ParsableCommand {
@ -24,24 +22,20 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
if case .failure = result {
try result.get()
}
try run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
}
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) -> Result<Void, MASError> {
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) throws {
let apps: [(installedApp: SoftwareProduct, storeApp: SearchResult)]
do {
apps = try findOutdatedApps(appLibrary: appLibrary, storeSearch: storeSearch)
} catch {
// Bubble up MASErrors
return .failure(error as? MASError ?? .searchFailed)
throw error as? MASError ?? .searchFailed
}
guard apps.count > 0 else {
printWarning("Nothing found to upgrade")
return .success(())
return
}
print("Upgrading \(apps.count) outdated application\(apps.count > 1 ? "s" : ""):")
@ -53,10 +47,8 @@ extension Mas {
do {
try downloadAll(appIds).wait()
} catch {
return .failure(error as? MASError ?? .downloadFailed(error: error as NSError))
throw error as? MASError ?? .downloadFailed(error: error as NSError)
}
return .success(())
}
private func findOutdatedApps(

View file

@ -21,17 +21,14 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
if case .failure = result {
try result.get()
}
try run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
}
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) -> Result<Void, MASError> {
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) throws {
do {
guard let result = try storeSearch.lookup(app: appId).wait()
else {
return .failure(.noSearchResultsFound)
throw MASError.noSearchResultsFound
}
guard let vendorWebsite = result.sellerUrl
@ -41,22 +38,16 @@ extension Mas {
try openCommand.run(arguments: vendorWebsite)
} catch {
printError("Unable to launch open command")
return .failure(.searchFailed)
throw MASError.searchFailed
}
if openCommand.failed {
let reason = openCommand.process.terminationReason
printError("Open failed: (\(reason)) \(openCommand.stderr)")
return .failure(.searchFailed)
throw MASError.searchFailed
}
} catch {
// Bubble up MASErrors
if let error = error as? MASError {
return .failure(error)
}
return .failure(.searchFailed)
throw error as? MASError ?? .searchFailed
}
return .success(())
}
}
}

View file

@ -17,15 +17,7 @@ extension Mas {
/// Runs the command.
func run() throws {
let result = runInternal()
if case .failure = result {
try result.get()
}
}
func runInternal() -> Result<Void, MASError> {
print(Package.version)
return .success(())
}
}
}

View file

@ -21,9 +21,9 @@ public class AccountSpec: QuickSpec {
xdescribe("Account command") {
xit("displays active account") {
expect {
try Mas.Account.parse([]).runInternal()
try Mas.Account.parse([]).run()
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -32,29 +32,20 @@ public class HomeSpec: QuickSpec {
expect {
try Mas.Home.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(
beFailure { error in
expect(error) == .searchFailed
}
)
.to(throwError(MASError.searchFailed))
}
it("can't find app with unknown ID") {
expect {
try Mas.Home.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(
beFailure { error in
expect(error) == .noSearchResultsFound
}
)
.to(throwError(MASError.noSearchResultsFound))
}
it("opens app on MAS Preview") {
storeSearch.apps[result.trackId] = result
expect {
try Mas.Home.parse([String(result.trackId)]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(beSuccess())
.toNot(throwError())
expect(openCommand.arguments).toNot(beNil())
expect(openCommand.arguments!.first!) == result.trackViewUrl
}

View file

@ -46,30 +46,21 @@ public class InfoSpec: QuickSpec {
expect {
try Mas.Info.parse(["--", "-999"]).run(storeSearch: storeSearch)
}
.to(
beFailure { error in
expect(error) == .searchFailed
}
)
.to(throwError(MASError.searchFailed))
}
it("can't find app with unknown ID") {
expect {
try Mas.Info.parse(["999"]).run(storeSearch: storeSearch)
}
.to(
beFailure { error in
expect(error) == .noSearchResultsFound
}
)
.to(throwError(MASError.noSearchResultsFound))
}
it("displays app details") {
storeSearch.apps[result.trackId] = result
let output = OutputListener()
expect {
try Mas.Info.parse([String(result.trackId)]).run(storeSearch: storeSearch)
}
.to(beSuccess())
.toNot(throwError())
expect(output.contents) == expectedOutput
}
}

View file

@ -21,7 +21,7 @@ public class InstallSpec: QuickSpec {
expect {
try Mas.Install.parse([]).run(appLibrary: AppLibraryMock())
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -21,7 +21,7 @@ public class ListSpec: QuickSpec {
expect {
try Mas.List.parse([]).run(appLibrary: AppLibraryMock())
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -24,7 +24,7 @@ public class LuckySpec: QuickSpec {
expect {
try Mas.Lucky.parse(["Slack"]).run(appLibrary: AppLibraryMock(), storeSearch: storeSearch)
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -33,30 +33,21 @@ public class OpenSpec: QuickSpec {
expect {
try Mas.Open.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(
beFailure { error in
expect(error) == .searchFailed
}
)
.to(throwError(MASError.searchFailed))
}
it("can't find app with unknown ID") {
expect {
try Mas.Open.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(
beFailure { error in
expect(error) == .noSearchResultsFound
}
)
.to(throwError(MASError.noSearchResultsFound))
}
it("opens app in MAS") {
storeSearch.apps[result.trackId] = result
expect {
try Mas.Open.parse([result.trackId.description])
.run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(beSuccess())
.toNot(throwError())
expect(openCommand.arguments).toNot(beNil())
let url = URL(string: openCommand.arguments!.first!)
expect(url).toNot(beNil())
@ -66,7 +57,7 @@ public class OpenSpec: QuickSpec {
expect {
try Mas.Open.parse(["appstore"]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(beSuccess())
.toNot(throwError())
expect(openCommand.arguments).toNot(beNil())
let url = URL(string: openCommand.arguments!.first!)
expect(url).toNot(beNil())

View file

@ -22,7 +22,7 @@ public class OutdatedSpec: QuickSpec {
try Mas.Outdated.parse(["--verbose"])
.run(appLibrary: AppLibraryMock(), storeSearch: StoreSearchMock())
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -19,9 +19,9 @@ public class ResetSpec: QuickSpec {
describe("reset command") {
it("resets the App Store state") {
expect {
try Mas.Reset.parse([]).runInternal()
try Mas.Reset.parse([]).run()
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -33,17 +33,13 @@ public class SearchSpec: QuickSpec {
expect {
try Mas.Search.parse(["slack"]).run(storeSearch: storeSearch)
}
.to(beSuccess())
.toNot(throwError())
}
it("fails when searching for nonexistent app") {
expect {
try Mas.Search.parse(["nonexistent"]).run(storeSearch: storeSearch)
}
.to(
beFailure { error in
expect(error) == .noSearchResultsFound
}
)
.to(throwError(MASError.noSearchResultsFound))
}
}
}

View file

@ -21,9 +21,9 @@ public class SignInSpec: QuickSpec {
xdescribe("signin command") {
xit("signs in") {
expect {
try Mas.SignIn.parse(["", ""]).runInternal()
try Mas.SignIn.parse(["", ""]).run()
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -19,9 +19,9 @@ public class SignOutSpec: QuickSpec {
describe("signout command") {
it("signs out") {
expect {
try Mas.SignOut.parse([]).runInternal()
try Mas.SignOut.parse([]).run()
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -36,21 +36,16 @@ public class UninstallSpec: QuickSpec {
}
it("can't remove a missing app") {
expect {
uninstall.run(appLibrary: mockLibrary)
try uninstall.run(appLibrary: mockLibrary)
}
.to(
beFailure { error in
expect(error) == .notInstalled
}
)
.to(throwError(MASError.notInstalled))
}
it("finds an app") {
mockLibrary.installedApps.append(app)
expect {
uninstall.run(appLibrary: mockLibrary)
try uninstall.run(appLibrary: mockLibrary)
}
.to(beSuccess())
.toNot(throwError())
}
}
context("wet run") {
@ -61,35 +56,25 @@ public class UninstallSpec: QuickSpec {
}
it("can't remove a missing app") {
expect {
uninstall.run(appLibrary: mockLibrary)
try uninstall.run(appLibrary: mockLibrary)
}
.to(
beFailure { error in
expect(error) == .notInstalled
}
)
.to(throwError(MASError.notInstalled))
}
it("removes an app") {
mockLibrary.installedApps.append(app)
expect {
uninstall.run(appLibrary: mockLibrary)
try uninstall.run(appLibrary: mockLibrary)
}
.to(beSuccess())
.toNot(throwError())
}
it("fails if there is a problem with the trash command") {
var brokenUninstall = app // make mutable copy
brokenUninstall.bundlePath = "/dev/null"
mockLibrary.installedApps.append(brokenUninstall)
expect {
uninstall.run(appLibrary: mockLibrary)
try uninstall.run(appLibrary: mockLibrary)
}
.to(
beFailure { error in
expect(error) == .uninstallFailed
}
)
.to(throwError(MASError.uninstallFailed))
}
}
}

View file

@ -21,7 +21,7 @@ public class UpgradeSpec: QuickSpec {
expect {
try Mas.Upgrade.parse([]).run(appLibrary: AppLibraryMock(), storeSearch: StoreSearchMock())
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -32,21 +32,13 @@ public class VendorSpec: QuickSpec {
expect {
try Mas.Vendor.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(
beFailure { error in
expect(error) == .searchFailed
}
)
.to(throwError(MASError.searchFailed))
}
it("can't find app with unknown ID") {
expect {
try Mas.Vendor.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(
beFailure { error in
expect(error) == .noSearchResultsFound
}
)
.to(throwError(MASError.noSearchResultsFound))
}
it("opens vendor app page in browser") {
storeSearch.apps[result.trackId] = result
@ -54,7 +46,7 @@ public class VendorSpec: QuickSpec {
try Mas.Vendor.parse([String(result.trackId)])
.run(storeSearch: storeSearch, openCommand: openCommand)
}
.to(beSuccess())
.toNot(throwError())
expect(openCommand.arguments).toNot(beNil())
expect(openCommand.arguments!.first!) == result.sellerUrl
}

View file

@ -19,9 +19,9 @@ public class VersionSpec: QuickSpec {
describe("version command") {
it("displays the current version") {
expect {
try Mas.Version.parse([]).runInternal()
try Mas.Version.parse([]).run()
}
.to(beSuccess())
.toNot(throwError())
}
}
}

View file

@ -1,32 +0,0 @@
//
// ResultPredicates.swift
// masTests
//
// Created by Ben Chatelain on 12/27/18.
// Copyright © 2018 mas-cli. All rights reserved.
//
import Nimble
@testable import mas
/// Nimble predicate for result enum success case, no associated value
func beSuccess() -> Predicate<Result<Void, MASError>> {
Predicate.define("be <success>") { expression, message in
if case .success = try expression.evaluate() {
return PredicateResult(status: .matches, message: message)
}
return PredicateResult(status: .fail, message: message)
}
}
/// Nimble predicate for result enum failure with associated error
func beFailure(test: @escaping (MASError) -> Void = { _ in }) -> Predicate<Result<Void, MASError>> {
Predicate.define("be <failure>") { expression, message in
if case .failure(let error) = try expression.evaluate() {
test(error)
return PredicateResult(status: .matches, message: message)
}
return PredicateResult(status: .fail, message: message)
}
}