mirror of
https://github.com/mas-cli/mas
synced 2024-11-22 03:23:08 +00:00
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:
parent
3b86deb63e
commit
388d963cd1
34 changed files with 111 additions and 331 deletions
|
@ -17,24 +17,16 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = runInternal()
|
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runInternal() -> Result<Void, MASError> {
|
|
||||||
if #available(macOS 12, *) {
|
if #available(macOS 12, *) {
|
||||||
// Account information is no longer available as of Monterey.
|
// Account information is no longer available as of Monterey.
|
||||||
// https://github.com/mas-cli/mas/issues/417
|
// https://github.com/mas-cli/mas/issues/417
|
||||||
return .failure(.notSupported)
|
throw MASError.notSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
print(try ISStoreAccount.primaryAccount.wait().identifier)
|
print(try ISStoreAccount.primaryAccount.wait().identifier)
|
||||||
return .success(())
|
|
||||||
} catch {
|
} catch {
|
||||||
return .failure(error as? MASError ?? .failed(error: error as NSError))
|
throw error as? MASError ?? MASError.failed(error: error as NSError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,38 +21,29 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
|
try run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) -> Result<Void, MASError> {
|
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) throws {
|
||||||
do {
|
do {
|
||||||
guard let result = try storeSearch.lookup(app: appId).wait() else {
|
guard let result = try storeSearch.lookup(app: appId).wait() else {
|
||||||
return .failure(.noSearchResultsFound)
|
throw MASError.noSearchResultsFound
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try openCommand.run(arguments: result.trackViewUrl)
|
try openCommand.run(arguments: result.trackViewUrl)
|
||||||
} catch {
|
} catch {
|
||||||
printError("Unable to launch open command")
|
printError("Unable to launch open command")
|
||||||
return .failure(.searchFailed)
|
throw MASError.searchFailed
|
||||||
}
|
}
|
||||||
if openCommand.failed {
|
if openCommand.failed {
|
||||||
let reason = openCommand.process.terminationReason
|
let reason = openCommand.process.terminationReason
|
||||||
printError("Open failed: (\(reason)) \(openCommand.stderr)")
|
printError("Open failed: (\(reason)) \(openCommand.stderr)")
|
||||||
return .failure(.searchFailed)
|
throw MASError.searchFailed
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Bubble up MASErrors
|
throw error as? MASError ?? .searchFailed
|
||||||
if let error = error as? MASError {
|
|
||||||
return .failure(error)
|
|
||||||
}
|
|
||||||
return .failure(.searchFailed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,28 +22,19 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(storeSearch: MasStoreSearch())
|
try run(storeSearch: MasStoreSearch())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(storeSearch: StoreSearch) -> Result<Void, MASError> {
|
func run(storeSearch: StoreSearch) throws {
|
||||||
do {
|
do {
|
||||||
guard let result = try storeSearch.lookup(app: appId).wait() else {
|
guard let result = try storeSearch.lookup(app: appId).wait() else {
|
||||||
return .failure(.noSearchResultsFound)
|
throw MASError.noSearchResultsFound
|
||||||
}
|
}
|
||||||
|
|
||||||
print(AppInfoFormatter.format(app: result))
|
print(AppInfoFormatter.format(app: result))
|
||||||
} catch {
|
} catch {
|
||||||
// Bubble up MASErrors
|
throw error as? MASError ?? .searchFailed
|
||||||
if let error = error as? MASError {
|
|
||||||
return .failure(error)
|
|
||||||
}
|
|
||||||
return .failure(.searchFailed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,10 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(appLibrary: MasAppLibrary())
|
try run(appLibrary: MasAppLibrary())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
|
func run(appLibrary: AppLibrary) throws {
|
||||||
// Try to download applications with given identifiers and collect results
|
// Try to download applications with given identifiers and collect results
|
||||||
let appIds = appIds.filter { appId in
|
let appIds = appIds.filter { appId in
|
||||||
if let product = appLibrary.installedApp(forId: appId), !force {
|
if let product = appLibrary.installedApp(forId: appId), !force {
|
||||||
|
@ -43,10 +40,8 @@ extension Mas {
|
||||||
do {
|
do {
|
||||||
try downloadAll(appIds).wait()
|
try downloadAll(appIds).wait()
|
||||||
} catch {
|
} catch {
|
||||||
return .failure(error as? MASError ?? .downloadFailed(error: error as NSError))
|
throw error as? MASError ?? .downloadFailed(error: error as NSError)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,23 +17,16 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(appLibrary: MasAppLibrary())
|
try run(appLibrary: MasAppLibrary())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
|
func run(appLibrary: AppLibrary) throws {
|
||||||
let products = appLibrary.installedApps
|
let products = appLibrary.installedApps
|
||||||
if products.isEmpty {
|
if products.isEmpty {
|
||||||
printError("No installed apps found")
|
printError("No installed apps found")
|
||||||
return .success(())
|
} else {
|
||||||
|
print(AppListFormatter.format(products: products))
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = AppListFormatter.format(products: products)
|
|
||||||
print(output)
|
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,34 +24,27 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
|
try run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) -> Result<Void, MASError> {
|
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) throws {
|
||||||
var appId: Int?
|
var appId: Int?
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let results = try storeSearch.search(for: appName).wait()
|
let results = try storeSearch.search(for: appName).wait()
|
||||||
guard let result = results.first else {
|
guard let result = results.first else {
|
||||||
printError("No results found")
|
printError("No results found")
|
||||||
return .failure(.noSearchResultsFound)
|
throw MASError.noSearchResultsFound
|
||||||
}
|
}
|
||||||
|
|
||||||
appId = result.trackId
|
appId = result.trackId
|
||||||
} catch {
|
} catch {
|
||||||
// Bubble up MASErrors
|
throw error as? MASError ?? .searchFailed
|
||||||
if let error = error as? MASError {
|
|
||||||
return .failure(error)
|
|
||||||
}
|
|
||||||
return .failure(.searchFailed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let identifier = appId else { fatalError() }
|
guard let identifier = appId else { fatalError() }
|
||||||
|
|
||||||
return install(UInt64(identifier), appLibrary: appLibrary)
|
try install(UInt64(identifier), appLibrary: appLibrary)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Installs an app.
|
/// Installs an app.
|
||||||
|
@ -59,21 +52,17 @@ extension Mas {
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - appId: App identifier
|
/// - appId: App identifier
|
||||||
/// - appLibrary: Library of installed apps
|
/// - appLibrary: Library of installed apps
|
||||||
/// - Returns: Result of the operation.
|
fileprivate func install(_ appId: UInt64, appLibrary: AppLibrary) throws {
|
||||||
fileprivate func install(_ appId: UInt64, appLibrary: AppLibrary) -> Result<Void, MASError> {
|
|
||||||
// Try to download applications with given identifiers and collect results
|
// Try to download applications with given identifiers and collect results
|
||||||
if let product = appLibrary.installedApp(forId: appId), !force {
|
if let product = appLibrary.installedApp(forId: appId), !force {
|
||||||
printWarning("\(product.appName) is already installed")
|
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(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,34 +25,31 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
|
try run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) -> Result<Void, MASError> {
|
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) throws {
|
||||||
do {
|
do {
|
||||||
if appId == markerValue {
|
if appId == markerValue {
|
||||||
// If no app ID is given, just open the MAS GUI app
|
// If no app ID is given, just open the MAS GUI app
|
||||||
try openCommand.run(arguments: masScheme + "://")
|
try openCommand.run(arguments: masScheme + "://")
|
||||||
return .success(())
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let appId = Int(appId)
|
guard let appId = Int(appId)
|
||||||
else {
|
else {
|
||||||
printError("Invalid app ID")
|
printError("Invalid app ID")
|
||||||
return .failure(.noSearchResultsFound)
|
throw MASError.noSearchResultsFound
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let result = try storeSearch.lookup(app: appId).wait()
|
guard let result = try storeSearch.lookup(app: appId).wait()
|
||||||
else {
|
else {
|
||||||
return .failure(.noSearchResultsFound)
|
throw MASError.noSearchResultsFound
|
||||||
}
|
}
|
||||||
|
|
||||||
guard var url = URLComponents(string: result.trackViewUrl)
|
guard var url = URLComponents(string: result.trackViewUrl)
|
||||||
else {
|
else {
|
||||||
return .failure(.searchFailed)
|
throw MASError.searchFailed
|
||||||
}
|
}
|
||||||
url.scheme = masScheme
|
url.scheme = masScheme
|
||||||
|
|
||||||
|
@ -60,22 +57,16 @@ extension Mas {
|
||||||
try openCommand.run(arguments: url.string!)
|
try openCommand.run(arguments: url.string!)
|
||||||
} catch {
|
} catch {
|
||||||
printError("Unable to launch open command")
|
printError("Unable to launch open command")
|
||||||
return .failure(.searchFailed)
|
throw MASError.searchFailed
|
||||||
}
|
}
|
||||||
if openCommand.failed {
|
if openCommand.failed {
|
||||||
let reason = openCommand.process.terminationReason
|
let reason = openCommand.process.terminationReason
|
||||||
printError("Open failed: (\(reason)) \(openCommand.stderr)")
|
printError("Open failed: (\(reason)) \(openCommand.stderr)")
|
||||||
return .failure(.searchFailed)
|
throw MASError.searchFailed
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Bubble up MASErrors
|
throw error as? MASError ?? .searchFailed
|
||||||
if let error = error as? MASError {
|
|
||||||
return .failure(error)
|
|
||||||
}
|
|
||||||
return .failure(.searchFailed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,10 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
|
try run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) -> Result<Void, MASError> {
|
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) throws {
|
||||||
let promises = appLibrary.installedApps.map { installedApp in
|
let promises = appLibrary.installedApps.map { installedApp in
|
||||||
firstly {
|
firstly {
|
||||||
storeSearch.lookup(app: installedApp.itemIdentifier.intValue)
|
storeSearch.lookup(app: installedApp.itemIdentifier.intValue)
|
||||||
|
@ -59,12 +56,11 @@ extension Mas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstly {
|
_ = firstly {
|
||||||
when(fulfilled: promises)
|
when(fulfilled: promises)
|
||||||
}.map {
|
}.map {
|
||||||
Result<Void, MASError>.success(())
|
Result<Void, MASError>.success(())
|
||||||
}.recover { error in
|
}.recover { error in
|
||||||
// Bubble up MASErrors
|
|
||||||
.value(Result<Void, MASError>.failure(error as? MASError ?? .searchFailed))
|
.value(Result<Void, MASError>.failure(error as? MASError ?? .searchFailed))
|
||||||
}.wait()
|
}.wait()
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,10 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(appLibrary: MasAppLibrary())
|
try run(appLibrary: MasAppLibrary())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
|
func run(appLibrary: AppLibrary) throws {
|
||||||
// Try to download applications with given identifiers and collect results
|
// Try to download applications with given identifiers and collect results
|
||||||
let appIds = appIds.filter { appId in
|
let appIds = appIds.filter { appId in
|
||||||
if let product = appLibrary.installedApp(forId: appId) {
|
if let product = appLibrary.installedApp(forId: appId) {
|
||||||
|
@ -40,10 +37,8 @@ extension Mas {
|
||||||
do {
|
do {
|
||||||
try downloadAll(appIds, purchase: true).wait()
|
try downloadAll(appIds, purchase: true).wait()
|
||||||
} catch {
|
} catch {
|
||||||
return .failure(error as? MASError ?? .downloadFailed(error: error as NSError))
|
throw error as? MASError ?? .downloadFailed(error: error as NSError)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,6 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
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 "Reset Application" command in the Mac App Store debug menu performs
|
||||||
// the following steps
|
// the following steps
|
||||||
//
|
//
|
||||||
|
@ -81,8 +74,6 @@ extension Mas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,29 +22,20 @@ extension Mas {
|
||||||
var appName: String
|
var appName: String
|
||||||
|
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(storeSearch: MasStoreSearch())
|
try run(storeSearch: MasStoreSearch())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(storeSearch: StoreSearch) -> Result<Void, MASError> {
|
func run(storeSearch: StoreSearch) throws {
|
||||||
do {
|
do {
|
||||||
let results = try storeSearch.search(for: appName).wait()
|
let results = try storeSearch.search(for: appName).wait()
|
||||||
if results.isEmpty {
|
if results.isEmpty {
|
||||||
return .failure(.noSearchResultsFound)
|
throw MASError.noSearchResultsFound
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = SearchResultFormatter.format(results: results, includePrice: price)
|
let output = SearchResultFormatter.format(results: results, includePrice: price)
|
||||||
print(output)
|
print(output)
|
||||||
|
|
||||||
return .success(())
|
|
||||||
} catch {
|
} catch {
|
||||||
// Bubble up MASErrors
|
throw error as? MASError ?? .searchFailed
|
||||||
if let error = error as? MASError {
|
|
||||||
return .failure(error)
|
|
||||||
}
|
|
||||||
return .failure(.searchFailed)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,18 +25,10 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = runInternal()
|
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runInternal() -> Result<Void, MASError> {
|
|
||||||
do {
|
do {
|
||||||
_ = try ISStoreAccount.signIn(username: username, password: password, systemDialog: dialog).wait()
|
_ = try ISStoreAccount.signIn(username: username, password: password, systemDialog: dialog).wait()
|
||||||
return .success(())
|
|
||||||
} catch {
|
} catch {
|
||||||
return .failure(error as? MASError ?? .signInFailed(error: error as NSError))
|
throw error as? MASError ?? MASError.signInFailed(error: error as NSError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,6 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = runInternal()
|
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runInternal() -> Result<Void, MASError> {
|
|
||||||
if #available(macOS 10.13, *) {
|
if #available(macOS 10.13, *) {
|
||||||
ISServiceProxy.genericShared().accountService.signOut()
|
ISServiceProxy.genericShared().accountService.signOut()
|
||||||
} else {
|
} else {
|
||||||
|
@ -32,8 +25,6 @@ extension Mas {
|
||||||
// https://github.com/mas-cli/mas/issues/129
|
// https://github.com/mas-cli/mas/issues/129
|
||||||
CKAccountStore.shared().signOut()
|
CKAccountStore.shared().signOut()
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,33 +25,26 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the uninstall command.
|
/// Runs the uninstall command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(appLibrary: MasAppLibrary())
|
try run(appLibrary: MasAppLibrary())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(appLibrary: AppLibrary) -> Result<Void, MASError> {
|
func run(appLibrary: AppLibrary) throws {
|
||||||
let appId = UInt64(appId)
|
let appId = UInt64(appId)
|
||||||
|
|
||||||
guard let product = appLibrary.installedApp(forId: appId) else {
|
guard let product = appLibrary.installedApp(forId: appId) else {
|
||||||
return .failure(.notInstalled)
|
throw MASError.notInstalled
|
||||||
}
|
}
|
||||||
|
|
||||||
if dryRun {
|
if dryRun {
|
||||||
printInfo("\(product.appName) \(product.bundlePath)")
|
printInfo("\(product.appName) \(product.bundlePath)")
|
||||||
printInfo("(not removed, dry run)")
|
printInfo("(not removed, dry run)")
|
||||||
|
} else {
|
||||||
return .success(())
|
do {
|
||||||
|
try appLibrary.uninstallApp(app: product)
|
||||||
|
} catch {
|
||||||
|
throw MASError.uninstallFailed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
|
||||||
try appLibrary.uninstallApp(app: product)
|
|
||||||
} catch {
|
|
||||||
return .failure(.uninstallFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,6 @@ import ArgumentParser
|
||||||
import Foundation
|
import Foundation
|
||||||
import PromiseKit
|
import PromiseKit
|
||||||
|
|
||||||
import enum Swift.Result
|
|
||||||
|
|
||||||
extension Mas {
|
extension Mas {
|
||||||
/// Command which upgrades apps with new versions available in the Mac App Store.
|
/// Command which upgrades apps with new versions available in the Mac App Store.
|
||||||
struct Upgrade: ParsableCommand {
|
struct Upgrade: ParsableCommand {
|
||||||
|
@ -24,24 +22,20 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
|
try run(appLibrary: MasAppLibrary(), storeSearch: MasStoreSearch())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) -> Result<Void, MASError> {
|
func run(appLibrary: AppLibrary, storeSearch: StoreSearch) throws {
|
||||||
let apps: [(installedApp: SoftwareProduct, storeApp: SearchResult)]
|
let apps: [(installedApp: SoftwareProduct, storeApp: SearchResult)]
|
||||||
do {
|
do {
|
||||||
apps = try findOutdatedApps(appLibrary: appLibrary, storeSearch: storeSearch)
|
apps = try findOutdatedApps(appLibrary: appLibrary, storeSearch: storeSearch)
|
||||||
} catch {
|
} catch {
|
||||||
// Bubble up MASErrors
|
throw error as? MASError ?? .searchFailed
|
||||||
return .failure(error as? MASError ?? .searchFailed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guard apps.count > 0 else {
|
guard apps.count > 0 else {
|
||||||
printWarning("Nothing found to upgrade")
|
printWarning("Nothing found to upgrade")
|
||||||
return .success(())
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Upgrading \(apps.count) outdated application\(apps.count > 1 ? "s" : ""):")
|
print("Upgrading \(apps.count) outdated application\(apps.count > 1 ? "s" : ""):")
|
||||||
|
@ -53,10 +47,8 @@ extension Mas {
|
||||||
do {
|
do {
|
||||||
try downloadAll(appIds).wait()
|
try downloadAll(appIds).wait()
|
||||||
} catch {
|
} 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(
|
private func findOutdatedApps(
|
||||||
|
|
|
@ -21,17 +21,14 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
|
try run(storeSearch: MasStoreSearch(), openCommand: OpenSystemCommand())
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) -> Result<Void, MASError> {
|
func run(storeSearch: StoreSearch, openCommand: ExternalCommand) throws {
|
||||||
do {
|
do {
|
||||||
guard let result = try storeSearch.lookup(app: appId).wait()
|
guard let result = try storeSearch.lookup(app: appId).wait()
|
||||||
else {
|
else {
|
||||||
return .failure(.noSearchResultsFound)
|
throw MASError.noSearchResultsFound
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let vendorWebsite = result.sellerUrl
|
guard let vendorWebsite = result.sellerUrl
|
||||||
|
@ -41,22 +38,16 @@ extension Mas {
|
||||||
try openCommand.run(arguments: vendorWebsite)
|
try openCommand.run(arguments: vendorWebsite)
|
||||||
} catch {
|
} catch {
|
||||||
printError("Unable to launch open command")
|
printError("Unable to launch open command")
|
||||||
return .failure(.searchFailed)
|
throw MASError.searchFailed
|
||||||
}
|
}
|
||||||
if openCommand.failed {
|
if openCommand.failed {
|
||||||
let reason = openCommand.process.terminationReason
|
let reason = openCommand.process.terminationReason
|
||||||
printError("Open failed: (\(reason)) \(openCommand.stderr)")
|
printError("Open failed: (\(reason)) \(openCommand.stderr)")
|
||||||
return .failure(.searchFailed)
|
throw MASError.searchFailed
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Bubble up MASErrors
|
throw error as? MASError ?? .searchFailed
|
||||||
if let error = error as? MASError {
|
|
||||||
return .failure(error)
|
|
||||||
}
|
|
||||||
return .failure(.searchFailed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,7 @@ extension Mas {
|
||||||
|
|
||||||
/// Runs the command.
|
/// Runs the command.
|
||||||
func run() throws {
|
func run() throws {
|
||||||
let result = runInternal()
|
|
||||||
if case .failure = result {
|
|
||||||
try result.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runInternal() -> Result<Void, MASError> {
|
|
||||||
print(Package.version)
|
print(Package.version)
|
||||||
return .success(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ public class AccountSpec: QuickSpec {
|
||||||
xdescribe("Account command") {
|
xdescribe("Account command") {
|
||||||
xit("displays active account") {
|
xit("displays active account") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Account.parse([]).runInternal()
|
try Mas.Account.parse([]).run()
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,29 +32,20 @@ public class HomeSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Home.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Home.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.searchFailed))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .searchFailed
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("can't find app with unknown ID") {
|
it("can't find app with unknown ID") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Home.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Home.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.noSearchResultsFound))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .noSearchResultsFound
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("opens app on MAS Preview") {
|
it("opens app on MAS Preview") {
|
||||||
storeSearch.apps[result.trackId] = result
|
storeSearch.apps[result.trackId] = result
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
try Mas.Home.parse([String(result.trackId)]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Home.parse([String(result.trackId)]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
expect(openCommand.arguments).toNot(beNil())
|
expect(openCommand.arguments).toNot(beNil())
|
||||||
expect(openCommand.arguments!.first!) == result.trackViewUrl
|
expect(openCommand.arguments!.first!) == result.trackViewUrl
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,30 +46,21 @@ public class InfoSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Info.parse(["--", "-999"]).run(storeSearch: storeSearch)
|
try Mas.Info.parse(["--", "-999"]).run(storeSearch: storeSearch)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.searchFailed))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .searchFailed
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("can't find app with unknown ID") {
|
it("can't find app with unknown ID") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Info.parse(["999"]).run(storeSearch: storeSearch)
|
try Mas.Info.parse(["999"]).run(storeSearch: storeSearch)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.noSearchResultsFound))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .noSearchResultsFound
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("displays app details") {
|
it("displays app details") {
|
||||||
storeSearch.apps[result.trackId] = result
|
storeSearch.apps[result.trackId] = result
|
||||||
let output = OutputListener()
|
let output = OutputListener()
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
try Mas.Info.parse([String(result.trackId)]).run(storeSearch: storeSearch)
|
try Mas.Info.parse([String(result.trackId)]).run(storeSearch: storeSearch)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
expect(output.contents) == expectedOutput
|
expect(output.contents) == expectedOutput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class InstallSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Install.parse([]).run(appLibrary: AppLibraryMock())
|
try Mas.Install.parse([]).run(appLibrary: AppLibraryMock())
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class ListSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.List.parse([]).run(appLibrary: AppLibraryMock())
|
try Mas.List.parse([]).run(appLibrary: AppLibraryMock())
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class LuckySpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Lucky.parse(["Slack"]).run(appLibrary: AppLibraryMock(), storeSearch: storeSearch)
|
try Mas.Lucky.parse(["Slack"]).run(appLibrary: AppLibraryMock(), storeSearch: storeSearch)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,30 +33,21 @@ public class OpenSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Open.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Open.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.searchFailed))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .searchFailed
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("can't find app with unknown ID") {
|
it("can't find app with unknown ID") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Open.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Open.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.noSearchResultsFound))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .noSearchResultsFound
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("opens app in MAS") {
|
it("opens app in MAS") {
|
||||||
storeSearch.apps[result.trackId] = result
|
storeSearch.apps[result.trackId] = result
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
try Mas.Open.parse([result.trackId.description])
|
try Mas.Open.parse([result.trackId.description])
|
||||||
.run(storeSearch: storeSearch, openCommand: openCommand)
|
.run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
expect(openCommand.arguments).toNot(beNil())
|
expect(openCommand.arguments).toNot(beNil())
|
||||||
let url = URL(string: openCommand.arguments!.first!)
|
let url = URL(string: openCommand.arguments!.first!)
|
||||||
expect(url).toNot(beNil())
|
expect(url).toNot(beNil())
|
||||||
|
@ -66,7 +57,7 @@ public class OpenSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Open.parse(["appstore"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Open.parse(["appstore"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
expect(openCommand.arguments).toNot(beNil())
|
expect(openCommand.arguments).toNot(beNil())
|
||||||
let url = URL(string: openCommand.arguments!.first!)
|
let url = URL(string: openCommand.arguments!.first!)
|
||||||
expect(url).toNot(beNil())
|
expect(url).toNot(beNil())
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class OutdatedSpec: QuickSpec {
|
||||||
try Mas.Outdated.parse(["--verbose"])
|
try Mas.Outdated.parse(["--verbose"])
|
||||||
.run(appLibrary: AppLibraryMock(), storeSearch: StoreSearchMock())
|
.run(appLibrary: AppLibraryMock(), storeSearch: StoreSearchMock())
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@ public class ResetSpec: QuickSpec {
|
||||||
describe("reset command") {
|
describe("reset command") {
|
||||||
it("resets the App Store state") {
|
it("resets the App Store state") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Reset.parse([]).runInternal()
|
try Mas.Reset.parse([]).run()
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,17 +33,13 @@ public class SearchSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Search.parse(["slack"]).run(storeSearch: storeSearch)
|
try Mas.Search.parse(["slack"]).run(storeSearch: storeSearch)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
it("fails when searching for nonexistent app") {
|
it("fails when searching for nonexistent app") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Search.parse(["nonexistent"]).run(storeSearch: storeSearch)
|
try Mas.Search.parse(["nonexistent"]).run(storeSearch: storeSearch)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.noSearchResultsFound))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .noSearchResultsFound
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@ public class SignInSpec: QuickSpec {
|
||||||
xdescribe("signin command") {
|
xdescribe("signin command") {
|
||||||
xit("signs in") {
|
xit("signs in") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.SignIn.parse(["", ""]).runInternal()
|
try Mas.SignIn.parse(["", ""]).run()
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@ public class SignOutSpec: QuickSpec {
|
||||||
describe("signout command") {
|
describe("signout command") {
|
||||||
it("signs out") {
|
it("signs out") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.SignOut.parse([]).runInternal()
|
try Mas.SignOut.parse([]).run()
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,21 +36,16 @@ public class UninstallSpec: QuickSpec {
|
||||||
}
|
}
|
||||||
it("can't remove a missing app") {
|
it("can't remove a missing app") {
|
||||||
expect {
|
expect {
|
||||||
uninstall.run(appLibrary: mockLibrary)
|
try uninstall.run(appLibrary: mockLibrary)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.notInstalled))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .notInstalled
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("finds an app") {
|
it("finds an app") {
|
||||||
mockLibrary.installedApps.append(app)
|
mockLibrary.installedApps.append(app)
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
uninstall.run(appLibrary: mockLibrary)
|
try uninstall.run(appLibrary: mockLibrary)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context("wet run") {
|
context("wet run") {
|
||||||
|
@ -61,35 +56,25 @@ public class UninstallSpec: QuickSpec {
|
||||||
}
|
}
|
||||||
it("can't remove a missing app") {
|
it("can't remove a missing app") {
|
||||||
expect {
|
expect {
|
||||||
uninstall.run(appLibrary: mockLibrary)
|
try uninstall.run(appLibrary: mockLibrary)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.notInstalled))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .notInstalled
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("removes an app") {
|
it("removes an app") {
|
||||||
mockLibrary.installedApps.append(app)
|
mockLibrary.installedApps.append(app)
|
||||||
|
|
||||||
expect {
|
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") {
|
it("fails if there is a problem with the trash command") {
|
||||||
var brokenUninstall = app // make mutable copy
|
var brokenUninstall = app // make mutable copy
|
||||||
brokenUninstall.bundlePath = "/dev/null"
|
brokenUninstall.bundlePath = "/dev/null"
|
||||||
mockLibrary.installedApps.append(brokenUninstall)
|
mockLibrary.installedApps.append(brokenUninstall)
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
uninstall.run(appLibrary: mockLibrary)
|
try uninstall.run(appLibrary: mockLibrary)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.uninstallFailed))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .uninstallFailed
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class UpgradeSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Upgrade.parse([]).run(appLibrary: AppLibraryMock(), storeSearch: StoreSearchMock())
|
try Mas.Upgrade.parse([]).run(appLibrary: AppLibraryMock(), storeSearch: StoreSearchMock())
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,21 +32,13 @@ public class VendorSpec: QuickSpec {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Vendor.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Vendor.parse(["--", "-999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.searchFailed))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .searchFailed
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("can't find app with unknown ID") {
|
it("can't find app with unknown ID") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Vendor.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
try Mas.Vendor.parse(["999"]).run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(
|
.to(throwError(MASError.noSearchResultsFound))
|
||||||
beFailure { error in
|
|
||||||
expect(error) == .noSearchResultsFound
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
it("opens vendor app page in browser") {
|
it("opens vendor app page in browser") {
|
||||||
storeSearch.apps[result.trackId] = result
|
storeSearch.apps[result.trackId] = result
|
||||||
|
@ -54,7 +46,7 @@ public class VendorSpec: QuickSpec {
|
||||||
try Mas.Vendor.parse([String(result.trackId)])
|
try Mas.Vendor.parse([String(result.trackId)])
|
||||||
.run(storeSearch: storeSearch, openCommand: openCommand)
|
.run(storeSearch: storeSearch, openCommand: openCommand)
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
expect(openCommand.arguments).toNot(beNil())
|
expect(openCommand.arguments).toNot(beNil())
|
||||||
expect(openCommand.arguments!.first!) == result.sellerUrl
|
expect(openCommand.arguments!.first!) == result.sellerUrl
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@ public class VersionSpec: QuickSpec {
|
||||||
describe("version command") {
|
describe("version command") {
|
||||||
it("displays the current version") {
|
it("displays the current version") {
|
||||||
expect {
|
expect {
|
||||||
try Mas.Version.parse([]).runInternal()
|
try Mas.Version.parse([]).run()
|
||||||
}
|
}
|
||||||
.to(beSuccess())
|
.toNot(throwError())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue