From 0b2bcd6d1ee71d6004d2aae2efc17c6e6c4ca261 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Thu, 20 Feb 2025 00:18:33 +0100 Subject: [PATCH] Implemented the OpenProjectTask task in the library target. --- Library/Sources/Public/Enumerations/IDE.swift | 16 ++++++ .../Public/Tasks/OpenProjectTask.swift | 44 +++++++++++++++ .../Public/Tasks/OpenProjectTaskTests.swift | 56 +++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 Library/Sources/Public/Tasks/OpenProjectTask.swift create mode 100644 Test/Sources/Cases/Public/Tasks/OpenProjectTaskTests.swift diff --git a/Library/Sources/Public/Enumerations/IDE.swift b/Library/Sources/Public/Enumerations/IDE.swift index 23f1196..2c530ac 100644 --- a/Library/Sources/Public/Enumerations/IDE.swift +++ b/Library/Sources/Public/Enumerations/IDE.swift @@ -2,3 +2,19 @@ public enum IDE: String { case vscode case xcode } + +// MARK: - Extension + +extension IDE { + + // MARK: Functions + + static func random() -> IDE { + .allCases.randomElement() ?? .xcode + } + +} + +// MARK: - CaseIterable + +extension IDE: CaseIterable {} diff --git a/Library/Sources/Public/Tasks/OpenProjectTask.swift b/Library/Sources/Public/Tasks/OpenProjectTask.swift new file mode 100644 index 0000000..d609ebb --- /dev/null +++ b/Library/Sources/Public/Tasks/OpenProjectTask.swift @@ -0,0 +1,44 @@ +import Foundation + +public struct OpenProjectTask { + + // MARK: Properties + + private let terminalService: TerminalServicing + + // MARK: Initialisers + + public init(terminalService: TerminalServicing) { + self.terminalService = terminalService + } + + // MARK: Functions + + public func callAsFunction(with ide: IDE, at location: URL? = nil) async throws (TerminalServiceError) { + let executableURL: URL = switch ide { + case .vscode: .init(at: "/usr/local/bin/code") + case .xcode: .init(at: "/usr/bin/open") + } + + let locationPath = switch ide { + case .vscode: location?.pathString ?? "." + case .xcode: location?.appendingPath(.Path.package).pathString ?? .Path.package + } + + let arguments: [String] = switch ide { + case .vscode: [locationPath] + case .xcode: ["-a", "Xcode", locationPath] + } + + try await terminalService.run(executableURL, arguments: arguments) + } + +} + +// MARK: - String+Constants + +private extension String { + enum Path { + static let package = "Package.swift" + } +} diff --git a/Test/Sources/Cases/Public/Tasks/OpenProjectTaskTests.swift b/Test/Sources/Cases/Public/Tasks/OpenProjectTaskTests.swift new file mode 100644 index 0000000..7e4f748 --- /dev/null +++ b/Test/Sources/Cases/Public/Tasks/OpenProjectTaskTests.swift @@ -0,0 +1,56 @@ +import Foundation +import Testing + +@testable import ColibriLibrary + +struct OpenProjectTaskTests { + + @Test(arguments: [nil, URL.someCurrentFolder]) + func taskWithVSCodeIDE(at location: URL?) async throws { + // GIVEN + let terminalService = TerminalServiceSpy() + let task = OpenProjectTask(terminalService: terminalService) + + // WHEN + try await task(with: .vscode, at: location) + + // THEN + let executableURL = URL(at: "/usr/local/bin/code") + let arguments = [location?.pathString ?? "."] + + #expect(terminalService.actions.count == 1) + #expect(terminalService.actions[0] == .ran(executableURL, arguments)) + } + + @Test(arguments: [nil, URL.someCurrentFolder]) + func taskWithXcodeIDE(at location: URL?) async throws { + // GIVEN + let terminalService = TerminalServiceSpy() + let task = OpenProjectTask(terminalService: terminalService) + + // WHEN + try await task(with: .xcode, at: location) + + // THEN + let locationPath = location?.appendingPath("Package.swift").pathString ?? "Package.swift" + let executableURL = URL(at: "/usr/bin/open") + let arguments = ["-a", "Xcode", locationPath] + + #expect(terminalService.actions.count == 1) + #expect(terminalService.actions[0] == .ran(executableURL, arguments)) + } + + @Test(arguments: [nil, URL.someCurrentFolder], [TerminalServiceError.unexpected, .output(""), .captured("")]) + func task(at location: URL?, throws error: TerminalServiceError) async throws { + // GIVEN + let terminalService = TerminalServiceMock(action: .error(error)) + let task = OpenProjectTask(terminalService: terminalService) + + // WHEN + // THEN + await #expect(throws: error) { + try await task(with: .random(), at: location) + } + } + +}