Files
swift-hpa/Tests/CliClientTests/CliClientTests.swift

187 lines
5.1 KiB
Swift

@_spi(Internal) import CliClient
import ConfigurationClient
import Dependencies
import FileClient
import Foundation
import ShellClient
import Testing
import TestSupport
@Suite("CliClientTests")
struct CliClientTests: TestCase {
@Test
func capturingClient() async throws {
let captured = CliClient.CapturingClient()
let client = CliClient.capturing(captured)
try await client.runCommand(quiet: false, shell: .zsh(), "foo", "bar")
let quiet = await captured.quiet!
#expect(quiet == false)
let shell = await captured.shell
#expect(shell == .zsh())
let arguments = await captured.arguments!
#expect(arguments == ["foo", "bar"])
}
@Test(arguments: ["encrypt", "decrypt"])
func runVault(argument: String) async throws {
let captured = CliClient.CapturingClient()
try await withMockConfiguration(captured, key: "runVault") {
$0.fileClient.findVaultFileInCurrentDirectory = { URL(filePath: "vault.yml") }
} operation: {
@Dependency(\.cliClient) var cliClient
let configuration = Configuration.mock
try await cliClient.runVaultCommand(.init(arguments: [argument], quiet: false, shell: nil))
let shell = await captured.shell
#expect(shell == .zsh(useDashC: true))
let vaultPath = URL(filePath: #file)
.deletingLastPathComponent()
.deletingLastPathComponent()
.appending(path: "vault.yml")
var encryptArgs: [String] = []
if argument == "encrypt", let id = configuration.vault.encryptId {
encryptArgs = ["--encrypt-vault-id", id]
}
let expectedArguments = [
"ansible-vault", argument
] + configuration.vault.args!
+ encryptArgs
+ [vaultPath.cleanFilePath]
let arguments = await captured.arguments
#expect(arguments == expectedArguments)
}
}
@Test(arguments: [
Configuration(
args: ["--tags", "debug"],
useVaultArgs: true,
playbook: .init(directory: "playbook", inventory: nil),
vault: .mock
)
])
func runPlaybook(configuration: Configuration) async throws {
let captured = CliClient.CapturingClient()
try await withMockConfiguration(captured, configuration: configuration, key: "runPlaybook") {
@Dependency(\.cliClient) var cliClient
try await cliClient.runPlaybookCommand(.init(
arguments: [],
quiet: false,
shell: nil
))
let expectedArguments = [
"ansible-playbook", "playbook/main.yml",
"--inventory", "playbook/inventory.ini",
"--tags", "debug",
"--vault-id=myId@$SCRIPTS/vault-gopass-client"
]
let arguments = await captured.arguments
#expect(arguments == expectedArguments)
}
}
@Test
func ensuredPlaybookDirectory() throws {
let configuration = Configuration.mock
let playbookDir = try configuration.ensuredPlaybookDirectory("playbook")
#expect(playbookDir == "playbook")
do {
_ = try configuration.ensuredPlaybookDirectory(nil)
#expect(Bool(false))
} catch {
#expect(Bool(true))
}
}
@Test
func shellOrDefault() {
var shell: String? = "/bin/bash"
#expect(shell.orDefault == .custom(path: "/bin/bash", useDashC: true))
shell = nil
#expect(shell.orDefault == .zsh(useDashC: true))
}
@Test
func testEnsuredInventoryPath() {
let configuration = Configuration(playbook: .init(inventory: "inventory.ini"))
let playbookDir = "playbook"
let inventoryPath = "inventory.ini"
var output = ensuredInventoryPath(
inventoryPath,
configuration: configuration,
playbookDirectory: playbookDir
)
#expect(output == "inventory.ini")
output = ensuredInventoryPath(
nil,
configuration: configuration,
playbookDirectory: playbookDir
)
#expect(output == "inventory.ini")
}
@Test
func vaultFilePath() async throws {
var fileClient = FileClient.testValue
fileClient.findVaultFileInCurrentDirectory = { URL(string: "vault.yml") }
var output = try await fileClient.ensuredVaultFilePath("vault.yml")
#expect(output == "vault.yml")
output = try await fileClient.ensuredVaultFilePath(nil)
fileClient.findVaultFileInCurrentDirectory = { nil }
do {
_ = try await fileClient.ensuredVaultFilePath(nil)
#expect(Bool(false))
} catch {
#expect(Bool(true))
}
}
func withMockConfiguration(
_ capturing: CliClient.CapturingClient,
configuration: Configuration = .mock,
key: String,
logLevel: Logger.Level = .trace,
depednencies setupDependencies: @escaping (inout DependencyValues) -> Void = { _ in },
operation: @Sendable @escaping () async throws -> Void
) async rethrows {
try await withTestLogger(key: key, logLevel: logLevel) {
$0.configurationClient = .mock(configuration)
$0.cliClient = .capturing(capturing)
setupDependencies(&$0)
} operation: {
try await operation()
}
}
}
extension ConfigurationClient {
static func mock(_ configuration: Configuration) -> Self {
var mock = Self.testValue
mock.find = { throw TestError() }
mock.load = { _ in configuration }
return mock
}
}
struct TestError: Error {}