diff --git a/Brewer/BrewerApp.swift b/Brewer/BrewerApp.swift index 4addcd1..e7f99ca 100644 --- a/Brewer/BrewerApp.swift +++ b/Brewer/BrewerApp.swift @@ -9,34 +9,37 @@ import SwiftUI @main struct BrewerApp: App { - @AppStorage("isUpToDate") var isUpToDate: Bool = true - init() { - do { - let res = try shell("/opt/homebrew/bin/brew outdated --greedy-latest -g | wc -l") - if let number = Int(res.trimmingCharacters(in: .whitespacesAndNewlines)), number > 0 { - isUpToDate = false - } - } catch { - print(error.localizedDescription) - } - } + @AppStorage("isUpToDate") var isUpToDate: Bool = true + init() { + do { + let res = try shell( + "/opt/homebrew/bin/brew outdated --greedy-latest -g | wc -l") + if let number = Int( + res.trimmingCharacters(in: .whitespacesAndNewlines)), number > 0 + { + isUpToDate = false + } + } catch { + print(error.localizedDescription) + } + } - var body: some Scene { - WindowGroup { - EmptyView() - } - MenuBarExtra { - ContentView().padding() - } label: { - if isUpToDate { - Label("Brewer", systemImage: "sparkle.magnifyingglass") - } else { - Label("Brewer", systemImage: "sparkle.magnifyingglass") - .symbolRenderingMode(.palette) - .foregroundStyle(.orange) - } - } - .menuBarExtraStyle(.window) - } + var body: some Scene { + WindowGroup { + EmptyView() + } + MenuBarExtra { + ContentView().padding() + } label: { + if isUpToDate { + Label("Brewer", systemImage: "sparkle.magnifyingglass") + } else { + Label("Brewer", systemImage: "sparkle.magnifyingglass") + .symbolRenderingMode(.palette) + .foregroundStyle(.orange) + } + } + .menuBarExtraStyle(.window) + } } diff --git a/Brewer/CaskDetailView.swift b/Brewer/CaskDetailView.swift index 7661c47..efdbc10 100644 --- a/Brewer/CaskDetailView.swift +++ b/Brewer/CaskDetailView.swift @@ -8,31 +8,32 @@ import SwiftUI struct CaskDetailView: View { - var cask: Cask - @Bindable var brewListing: Homebrew - var body: some View { - NavigationStack { - VStack { - Text("Identifier: \(cask.fullToken)") - Text("Version: \(cask.version)") - } - .navigationTitle(cask.name.first ?? cask.fullToken) - .toolbar { - ToolbarItem(placement: .primaryAction) { - if cask.installed == nil { - DownloadButton(name: cask.fullToken, isCask: true) - } else if cask.outdated { - Button("Update") { + var cask: Cask + @Bindable var brewListing: Homebrew + var body: some View { + NavigationStack { + VStack { + Text("Identifier: \(cask.fullToken)") + Text("Version: \(cask.version)") + } + .navigationTitle(cask.name.first ?? cask.fullToken) + .toolbar { + ToolbarItem(placement: .primaryAction) { + if cask.installed == nil { + DownloadButton(name: cask.fullToken, isCask: true) + } else if cask.outdated { + Button("Update") { - } - } - } - if cask.installed != nil { - ToolbarItem(placement: .primaryAction) { - UninstallButton(name: cask.fullToken, brewListing: brewListing) - } - } - } - } - } + } + } + } + if cask.installed != nil { + ToolbarItem(placement: .primaryAction) { + UninstallButton( + name: cask.fullToken, brewListing: brewListing) + } + } + } + } + } } diff --git a/Brewer/Components/DownloadButton.swift b/Brewer/Components/DownloadButton.swift index 6394846..68ae45f 100644 --- a/Brewer/Components/DownloadButton.swift +++ b/Brewer/Components/DownloadButton.swift @@ -8,46 +8,46 @@ import SwiftUI struct DownloadButton: View { - let name: String - var isCask: Bool = false - @State private var brew = Homebrew() - @State private var downloaded = false + let name: String + var isCask: Bool = false + @State private var brew = Homebrew() + @State private var downloaded = false - var body: some View { - VStack { - if downloaded { - Image(systemName: "checkmark") - .symbolRenderingMode(.palette) - .symbolVariant(.circle) - .symbolVariant(.fill) - .foregroundStyle(.white, .green) - } else if brew.isLoading { - ProgressView() - .controlSize(.small) - } else if brew.errorMessage != nil { - Image(systemName: "x") - .symbolRenderingMode(.palette) - .symbolVariant(.circle) - .symbolVariant(.fill) - .foregroundStyle(.white, .red) - } else { - Button("Get") { - Task { - downloaded = await brew.install(name, isCask: isCask) - } - } - .buttonBorderShape(.capsule) - .buttonStyle(.borderedProminent) - } - } - .onAppear { - Task { - downloaded = await brew.isDownloaded(name) - } - } - } + var body: some View { + VStack { + if downloaded { + Image(systemName: "checkmark") + .symbolRenderingMode(.palette) + .symbolVariant(.circle) + .symbolVariant(.fill) + .foregroundStyle(.white, .green) + } else if brew.isLoading { + ProgressView() + .controlSize(.small) + } else if brew.errorMessage != nil { + Image(systemName: "x") + .symbolRenderingMode(.palette) + .symbolVariant(.circle) + .symbolVariant(.fill) + .foregroundStyle(.white, .red) + } else { + Button("Get") { + Task { + downloaded = await brew.install(name, isCask: isCask) + } + } + .buttonBorderShape(.capsule) + .buttonStyle(.borderedProminent) + } + } + .onAppear { + Task { + downloaded = await brew.isDownloaded(name) + } + } + } } #Preview { - DownloadButton(name: "firefox") + DownloadButton(name: "firefox") } diff --git a/Brewer/Components/UninstallButton.swift b/Brewer/Components/UninstallButton.swift index aaf6bbf..4382022 100644 --- a/Brewer/Components/UninstallButton.swift +++ b/Brewer/Components/UninstallButton.swift @@ -8,38 +8,38 @@ import SwiftUI struct UninstallButton: View { - let name: String - @State private var brew = Homebrew() - @State private var uninstalled = false - @Bindable var brewListing: Homebrew - var body: some View { - VStack { - if uninstalled { - EmptyView() - } else if brew.isLoading { - ProgressView() - .controlSize(.small) - } else if brew.errorMessage != nil { - Image(systemName: "x") - .symbolRenderingMode(.palette) - .symbolVariant(.circle) - .symbolVariant(.fill) - .foregroundStyle(.white, .red) - } else { - Button("Uninstall", role: .destructive) { - Task { - uninstalled = await brew.uninstall(name) - brewListing.getInstalled() - } - } - .buttonBorderShape(.capsule) - .buttonStyle(.borderedProminent) - } - } - .onAppear { - Task { - uninstalled = await brew.isDownloaded(name) - } - } - } + let name: String + @State private var brew = Homebrew() + @State private var uninstalled = false + @Bindable var brewListing: Homebrew + var body: some View { + VStack { + if uninstalled { + EmptyView() + } else if brew.isLoading { + ProgressView() + .controlSize(.small) + } else if brew.errorMessage != nil { + Image(systemName: "x") + .symbolRenderingMode(.palette) + .symbolVariant(.circle) + .symbolVariant(.fill) + .foregroundStyle(.white, .red) + } else { + Button("Uninstall", role: .destructive) { + Task { + uninstalled = await brew.uninstall(name) + brewListing.getInstalled() + } + } + .buttonBorderShape(.capsule) + .buttonStyle(.borderedProminent) + } + } + .onAppear { + Task { + uninstalled = await brew.isDownloaded(name) + } + } + } } diff --git a/Brewer/ContentView.swift b/Brewer/ContentView.swift index 3208d4a..f078d72 100644 --- a/Brewer/ContentView.swift +++ b/Brewer/ContentView.swift @@ -8,29 +8,29 @@ import SwiftUI enum SegementedSelection: String, CaseIterable { - case search = "Search" - case installed = "Installed" + case search = "Search" + case installed = "Installed" } struct ContentView: View { - @State private var segmentedSelection: SegementedSelection = .search - var body: some View { - NavigationStack { - Picker("", selection: $segmentedSelection) { - ForEach(SegementedSelection.allCases, id: \.self) { sel in - Text(sel.rawValue).tag(sel) - } - }.pickerStyle(.segmented) - switch segmentedSelection { - case .search: - SearchView() - case .installed: - InstalledView() - } - } - } + @State private var segmentedSelection: SegementedSelection = .search + var body: some View { + NavigationStack { + Picker("", selection: $segmentedSelection) { + ForEach(SegementedSelection.allCases, id: \.self) { sel in + Text(sel.rawValue).tag(sel) + } + }.pickerStyle(.segmented) + switch segmentedSelection { + case .search: + SearchView() + case .installed: + InstalledView() + } + } + } } #Preview { - ContentView() + ContentView() } diff --git a/Brewer/InstalledView.swift b/Brewer/InstalledView.swift index 1e29784..1784da4 100644 --- a/Brewer/InstalledView.swift +++ b/Brewer/InstalledView.swift @@ -8,101 +8,120 @@ import SwiftUI struct InstalledView: View { - @State private var brew = Homebrew() - var body: some View { - VStack { - if brew.isLoading { - ProgressView("Loading...") - } else if let data = brew.data { - List { - if !data.casks.isEmpty { - Section { - ForEach(data.casks, id: \.fullToken) { cask in - NavigationLink { - CaskDetailView(cask: cask, brewListing: brew) - } label: { - HStack { - Text(cask.name.first ?? cask.fullToken) - Spacer() - if cask.outdated { - Button { + @State private var brew = Homebrew() + var body: some View { + VStack { + if brew.isLoading { + ProgressView("Loading...") + } else if let data = brew.data { + List { + if !data.casks.isEmpty { + Section { + ForEach(data.casks, id: \.fullToken) { cask in + NavigationLink { + CaskDetailView( + cask: cask, brewListing: brew) + } label: { + HStack { + Text(cask.name.first ?? cask.fullToken) + Spacer() + if cask.outdated { + Button { - } label: { - Label("Update", systemImage: "arrow.counterclockwise.circle.fill") - .symbolRenderingMode(.palette) - .foregroundStyle(.white, .orange) - } - } else { - Text(cask.version) - } - } - .contextMenu { - UninstallButton(name: cask.fullToken, brewListing: brew) - } - } - } - } header: { - HStack { - Text("Casks") - Spacer() - Text("\(data.casks.count) installed") - } - } - } + } label: { + Label( + "Update", + systemImage: + "arrow.counterclockwise.circle.fill" + ) + .symbolRenderingMode(.palette) + .foregroundStyle( + .white, .orange) + } + } else { + Text(cask.version) + } + } + .contextMenu { + UninstallButton( + name: cask.fullToken, + brewListing: brew) + } + } + } + } header: { + HStack { + Text("Casks") + Spacer() + Text("\(data.casks.count) installed") + } + } + } - if !data.formulae.isEmpty { - Section { - ForEach(data.formulae, id: \.fullName) { formulae in - HStack { - Text(formulae.fullName) - Spacer() - if formulae.outdated { - Button { + if !data.formulae.isEmpty { + Section { + ForEach(data.formulae, id: \.fullName) { formulae in + HStack { + Text(formulae.fullName) + Spacer() + if formulae.outdated { + Button { - } label: { - Label("Update", systemImage: "arrow.counterclockwise.circle.fill") - .symbolRenderingMode(.palette) - .foregroundStyle(.white, .orange) - } - } else { - Text(formulae.versions.stable) - } - } - .contextMenu { - UninstallButton(name: formulae.fullName, brewListing: brew) - } - } - } header: { - HStack { - Text("Formulae") - Spacer() - Text("\(data.formulae.count) installed") - } - } - } - } - .listStyle(.inset(alternatesRowBackgrounds: true)) - let areOutdated = data.casks.map(\.outdated).count + data.formulae.map(\.outdated).count - let _ = UserDefaults.standard.set(!(areOutdated > 0), forKey: "isUpToDate") - if areOutdated > 0 { - Button { + } label: { + Label( + "Update", + systemImage: + "arrow.counterclockwise.circle.fill" + ) + .symbolRenderingMode(.palette) + .foregroundStyle(.white, .orange) + } + } else { + Text(formulae.versions.stable) + } + } + .contextMenu { + UninstallButton( + name: formulae.fullName, + brewListing: brew) + } + } + } header: { + HStack { + Text("Formulae") + Spacer() + Text("\(data.formulae.count) installed") + } + } + } + } + .listStyle(.inset(alternatesRowBackgrounds: true)) + let areOutdated = + data.casks.map(\.outdated).count + + data.formulae.map(\.outdated).count + let _ = UserDefaults.standard.set( + !(areOutdated > 0), forKey: "isUpToDate") + if areOutdated > 0 { + Button { - } label: { - Label("Update all", systemImage: "arrow.counterclockwise.circle.fill") - } - .buttonStyle(.borderedProminent) - .tint(.orange) - } - } else if let error = brew.errorMessage { - Text(error) - .foregroundStyle(.red) - } - }.task { - brew.getInstalled() - } - } + } label: { + Label( + "Update all", + systemImage: "arrow.counterclockwise.circle.fill") + } + .buttonStyle(.borderedProminent) + .tint(.orange) + } + } else if let error = brew.errorMessage { + Text(error) + .foregroundStyle(.red) + } + }.task { + brew.getInstalled() + } + } } #Preview { - InstalledView() + InstalledView() } diff --git a/Brewer/Model/Homebrew.swift b/Brewer/Model/Homebrew.swift index d2f539c..6131939 100644 --- a/Brewer/Model/Homebrew.swift +++ b/Brewer/Model/Homebrew.swift @@ -8,207 +8,217 @@ import Foundation enum ShellError: Error { - case emptyOutput + case emptyOutput } @discardableResult func shell(_ command: String) throws -> String { - let task = Process() - task.executableURL = URL(filePath: "/bin/bash") - task.arguments = ["-c", command] + let task = Process() + task.executableURL = URL(filePath: "/bin/bash") + task.arguments = ["-c", command] - let pipe = Pipe() - task.standardError = pipe - task.standardOutput = pipe + let pipe = Pipe() + task.standardError = pipe + task.standardOutput = pipe - try task.run() - if let data = try pipe.fileHandleForReading.readToEnd(), - let output = String(data: data, encoding: .utf8) - { - return output - } + try task.run() + if let data = try pipe.fileHandleForReading.readToEnd(), + let output = String(data: data, encoding: .utf8) + { + return output + } - throw ShellError.emptyOutput + throw ShellError.emptyOutput } struct Cask: Codable { - let token: String - let fullToken: String - let tap: String - let name: [String] - let desc: String - let homepage: String - let url: String - let version: String - let installed: String? - let outdated: Bool + let token: String + let fullToken: String + let tap: String + let name: [String] + let desc: String + let homepage: String + let url: String + let version: String + let installed: String? + let outdated: Bool - enum CodingKeys: String, CodingKey { - case token, tap, name, desc, homepage, url, version, installed, outdated - case fullToken = "full_token" - } + enum CodingKeys: String, CodingKey { + case token, tap, name, desc, homepage, url, version, installed, outdated + case fullToken = "full_token" + } } struct Formulae: Codable { - struct Version: Codable { - let stable: String - let head: String? - let bottle: Bool + struct Version: Codable { + let stable: String + let head: String? + let bottle: Bool - enum CodingKeys: String, CodingKey { - case stable - case head, bottle - } - } + enum CodingKeys: String, CodingKey { + case stable + case head, bottle + } + } - let name: String - let fullName: String - let tap: String - let oldNames: [String] - let aliases: [String] - let versionedFormulae: [String] - let desc: String - let license: String? - let homepage: String - let versions: Version - let outdated: Bool + let name: String + let fullName: String + let tap: String + let oldNames: [String] + let aliases: [String] + let versionedFormulae: [String] + let desc: String + let license: String? + let homepage: String + let versions: Version + let outdated: Bool - enum CodingKeys: String, CodingKey { - case name - case tap - case aliases - case desc - case license - case homepage - case versions - case outdated - case fullName = "full_name" - case oldNames = "oldnames" - case versionedFormulae = "versioned_formulae" - } + enum CodingKeys: String, CodingKey { + case name + case tap + case aliases + case desc + case license + case homepage + case versions + case outdated + case fullName = "full_name" + case oldNames = "oldnames" + case versionedFormulae = "versioned_formulae" + } } struct InfoResponse: Codable { - let formulae: [Formulae] - let casks: [Cask] + let formulae: [Formulae] + let casks: [Cask] - enum CodingKeys: String, CodingKey { - case casks - case formulae - } + enum CodingKeys: String, CodingKey { + case casks + case formulae + } } @Observable class Homebrew { - var data: InfoResponse? - var isLoading = false - var errorMessage: String? + var data: InfoResponse? + var isLoading = false + var errorMessage: String? - func getInfo(on query: String) { - self.isLoading = true - self.errorMessage = nil - self.data = nil - Task { [weak self] in - do { - let res = try shell("/opt/homebrew/bin/brew info --json=v2 \(query)") - if let data = res.data(using: .utf8) { - let output = try JSONDecoder().decode(InfoResponse.self, from: data) - self?.data = output - } - } catch { - self?.errorMessage = error.localizedDescription - } - self?.isLoading = false - } - } + func getInfo(on query: String) { + self.isLoading = true + self.errorMessage = nil + self.data = nil + Task { [weak self] in + do { + let res = try shell( + "/opt/homebrew/bin/brew info --json=v2 \(query)") + if let data = res.data(using: .utf8) { + let output = try JSONDecoder().decode( + InfoResponse.self, from: data) + self?.data = output + } + } catch { + self?.errorMessage = error.localizedDescription + } + self?.isLoading = false + } + } - func getInstalled() { - self.isLoading = true - self.data = nil - self.errorMessage = nil - Task { [weak self] in - do { - let res = try shell("/opt/homebrew/bin/brew info --json=v2 --installed") - if let data = res.data(using: .utf8) { - let output = try JSONDecoder().decode(InfoResponse.self, from: data) - self?.data = output - } - } catch { - self?.errorMessage = error.localizedDescription - } - self?.isLoading = false - } + func getInstalled() { + self.isLoading = true + self.data = nil + self.errorMessage = nil + Task { [weak self] in + do { + let res = try shell( + "/opt/homebrew/bin/brew info --json=v2 --installed") + if let data = res.data(using: .utf8) { + let output = try JSONDecoder().decode( + InfoResponse.self, from: data) + self?.data = output + } + } catch { + self?.errorMessage = error.localizedDescription + } + self?.isLoading = false + } - } + } - func isDownloaded(_ name: String) async -> Bool { - self.isLoading = true - self.errorMessage = nil - self.data = nil - let task = Task { [weak self] in - do { - let res = try shell("/opt/homebrew/bin/brew list -1 \(name) >/dev/null 2>&1; echo $?") - .trimmingCharacters(in: .whitespacesAndNewlines) - self?.isLoading = false - return res == "0" - } catch { - self?.errorMessage = error.localizedDescription - } + func isDownloaded(_ name: String) async -> Bool { + self.isLoading = true + self.errorMessage = nil + self.data = nil + let task = Task { [weak self] in + do { + let res = try shell( + "/opt/homebrew/bin/brew list -1 \(name) >/dev/null 2>&1; echo $?" + ) + .trimmingCharacters(in: .whitespacesAndNewlines) + self?.isLoading = false + return res == "0" + } catch { + self?.errorMessage = error.localizedDescription + } - return false - } + return false + } - switch await task.result { - case .success(let success): - return success - case .failure(let fail): - return false - } - } + switch await task.result { + case .success(let success): + return success + case .failure(let fail): + return false + } + } - func install(_ fullToken: String, isCask: Bool = false) async -> Bool { - self.isLoading = true - self.data = nil - let task = Task { [weak self] in - do { - try shell("/opt/homebrew/bin/brew install \(isCask ? "--cask" : "") \(fullToken)") - } catch { - self?.errorMessage = error.localizedDescription - } - self?.isLoading = false - return await self?.isDownloaded(fullToken) ?? false - } + func install(_ fullToken: String, isCask: Bool = false) async -> Bool { + self.isLoading = true + self.data = nil + let task = Task { [weak self] in + do { + try shell( + "/opt/homebrew/bin/brew install \(isCask ? "--cask" : "") \(fullToken)" + ) + } catch { + self?.errorMessage = error.localizedDescription + } + self?.isLoading = false + return await self?.isDownloaded(fullToken) ?? false + } - return switch await task.result { - case .success(let success): - success - case .failure(let fail): - false - } - } + return switch await task.result { + case .success(let success): + success + case .failure(let fail): + false + } + } - func uninstall(_ fullToken: String) async -> Bool { - self.isLoading = true - self.data = nil - let task = Task { [weak self] in - do { - let res = - try shell("/opt/homebrew/bin/brew uninstall \(fullToken); echo $?") - .trimmingCharacters(in: .whitespacesAndNewlines) - } catch { - self?.errorMessage = error.localizedDescription - } - self?.isLoading = false - return await !(self?.isDownloaded(fullToken) ?? true) - } + func uninstall(_ fullToken: String) async -> Bool { + self.isLoading = true + self.data = nil + let task = Task { [weak self] in + do { + let res = + try shell( + "/opt/homebrew/bin/brew uninstall \(fullToken); echo $?" + ) + .trimmingCharacters(in: .whitespacesAndNewlines) + } catch { + self?.errorMessage = error.localizedDescription + } + self?.isLoading = false + return await !(self?.isDownloaded(fullToken) ?? true) + } - return switch await task.result { - case .success(let success): - success - case .failure(let failure): - false - } + return switch await task.result { + case .success(let success): + success + case .failure(let failure): + false + } - } + } } diff --git a/Brewer/SearchView.swift b/Brewer/SearchView.swift index 93d9e3b..16bbb6b 100644 --- a/Brewer/SearchView.swift +++ b/Brewer/SearchView.swift @@ -8,58 +8,61 @@ import SwiftUI struct SearchView: View { - @State private var query = "" - @State private var brew = Homebrew() - var body: some View { - VStack { - TextField("Search", text: $query) - .padding() - .padding(.bottom, 0) - .onSubmit { - brew.getInfo(on: query) - } - Spacer() - if brew.isLoading { - ProgressView("Loading...") - } else if let data = brew.data { - List { - if !data.casks.isEmpty { - Section("Casks") { - ForEach(data.casks, id: \.fullToken) { cask in - HStack { - Text(cask.fullToken) - Spacer() - if cask.installed != nil { - Image(systemName: "checkmark.circle.fill") - .symbolRenderingMode(.palette) - .foregroundStyle(.white, .green) - } else { - DownloadButton(name: cask.fullToken, isCask: true) - } - } - } - } - } - if !data.formulae.isEmpty { + @State private var query = "" + @State private var brew = Homebrew() + var body: some View { + VStack { + TextField("Search", text: $query) + .padding() + .padding(.bottom, 0) + .onSubmit { + brew.getInfo(on: query) + } + Spacer() + if brew.isLoading { + ProgressView("Loading...") + } else if let data = brew.data { + List { + if !data.casks.isEmpty { + Section("Casks") { + ForEach(data.casks, id: \.fullToken) { cask in + HStack { + Text(cask.fullToken) + Spacer() + if cask.installed != nil { + Image( + systemName: "checkmark.circle.fill" + ) + .symbolRenderingMode(.palette) + .foregroundStyle(.white, .green) + } else { + DownloadButton( + name: cask.fullToken, isCask: true) + } + } + } + } + } + if !data.formulae.isEmpty { - Section("Formulaes") { - ForEach(data.formulae, id: \.fullName) { formulae in - HStack { - Text(formulae.fullName) - } - } - } - } - } - } else if let errorMessage = brew.errorMessage { - Text(errorMessage) - .foregroundStyle(.red) - } - } - } + Section("Formulaes") { + ForEach(data.formulae, id: \.fullName) { formulae in + HStack { + Text(formulae.fullName) + } + } + } + } + } + } else if let errorMessage = brew.errorMessage { + Text(errorMessage) + .foregroundStyle(.red) + } + } + } } #Preview { - SearchView() + SearchView() } diff --git a/BrewerTests/BrewerTests.swift b/BrewerTests/BrewerTests.swift index d831d40..b788195 100644 --- a/BrewerTests/BrewerTests.swift +++ b/BrewerTests/BrewerTests.swift @@ -6,31 +6,32 @@ // import XCTest + @testable import Brewer final class BrewerTests: XCTestCase { - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } } diff --git a/BrewerUITests/BrewerUITests.swift b/BrewerUITests/BrewerUITests.swift index b58e678..c7cf997 100644 --- a/BrewerUITests/BrewerUITests.swift +++ b/BrewerUITests/BrewerUITests.swift @@ -9,33 +9,33 @@ import XCTest final class BrewerUITests: XCTestCase { - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = false + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. - } + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } - func testExample() throws { - // UI tests must launch the application that they test. - let app = XCUIApplication() - app.launch() + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() - // Use XCTAssert and related functions to verify your tests produce the correct results. - } + // Use XCTAssert and related functions to verify your tests produce the correct results. + } - func testLaunchPerformance() throws { - if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { - // This measures how long it takes to launch your application. - measure(metrics: [XCTApplicationLaunchMetric()]) { - XCUIApplication().launch() - } - } - } + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } } diff --git a/BrewerUITests/BrewerUITestsLaunchTests.swift b/BrewerUITests/BrewerUITestsLaunchTests.swift index e2b68c7..145a7cf 100644 --- a/BrewerUITests/BrewerUITestsLaunchTests.swift +++ b/BrewerUITests/BrewerUITestsLaunchTests.swift @@ -9,24 +9,24 @@ import XCTest final class BrewerUITestsLaunchTests: XCTestCase { - override class var runsForEachTargetApplicationUIConfiguration: Bool { - true - } + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } - override func setUpWithError() throws { - continueAfterFailure = false - } + override func setUpWithError() throws { + continueAfterFailure = false + } - func testLaunch() throws { - let app = XCUIApplication() - app.launch() + func testLaunch() throws { + let app = XCUIApplication() + app.launch() - // Insert steps here to perform after app launch but before taking a screenshot, - // such as logging into a test account or navigating somewhere in the app + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app - let attachment = XCTAttachment(screenshot: app.screenshot()) - attachment.name = "Launch Screen" - attachment.lifetime = .keepAlways - add(attachment) - } + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } }