@_spi(Internal) import ConfigurationClient import FileClient import Foundation import Testing import TestSupport @_spi(Internal) import VaultClient @Suite("VaultClientTests") struct VaultClientTests: TestCase { @Test( arguments: TestOptions.testCases ) func decrypt(input: TestOptions) async throws { try await withCapturingCommandClient("decrypt") { $0.configurationClient = .mock(input.configuration) $0.fileClient.findVaultFile = { _ in URL(filePath: "/vault.yml") } $0.vaultClient = .liveValue } run: { @Dependency(\.vaultClient) var vaultClient let output = try await vaultClient.run.decrypt(.init( extraOptions: input.extraOptions, loggingOptions: Self.loggingOptions, outputFilePath: input.outputFilePath, vaultFilePath: input.vaultFilePath )) if let outputFilePath = input.outputFilePath { #expect(output == outputFilePath) } else if let vaultFilePath = input.vaultFilePath { #expect(output == vaultFilePath) } else { #expect(output == "/vault.yml") } } assert: { options in #expect(options.arguments == input.expected(.decrypt)) } } @Test( arguments: TestOptions.testCases ) func encrypt(input: TestOptions) async throws { try await withCapturingCommandClient("decrypt") { $0.configurationClient = .mock(input.configuration) $0.fileClient.findVaultFile = { _ in URL(filePath: "/vault.yml") } $0.vaultClient = .liveValue } run: { @Dependency(\.vaultClient) var vaultClient let output = try await vaultClient.run.encrypt(.init( extraOptions: input.extraOptions, loggingOptions: Self.loggingOptions, outputFilePath: input.outputFilePath, vaultFilePath: input.vaultFilePath )) if let outputFilePath = input.outputFilePath { #expect(output == outputFilePath) } else if let vaultFilePath = input.vaultFilePath { #expect(output == vaultFilePath) } else { #expect(output == "/vault.yml") } } assert: { options in #expect(options.arguments == input.expected(.encrypt)) } } } struct TestOptions: Sendable { let configuration: Configuration let extraOptions: [String]? let outputFilePath: String? let vaultFilePath: String? init( configuration: Configuration = .init(), extraOptions: [String]? = nil, outputFilePath: String? = nil, vaultFilePath: String? = nil ) { self.configuration = configuration self.extraOptions = extraOptions self.outputFilePath = outputFilePath self.vaultFilePath = vaultFilePath } func expected(_ route: VaultClient.Route) -> [String] { var expected = [ "ansible-vault", "\(route.verb)" ] if let outputFilePath { expected.append(contentsOf: ["--output", outputFilePath]) } if let extraOptions { expected.append(contentsOf: extraOptions) } if let vaultArgs = configuration.vault.args { expected.append(contentsOf: vaultArgs) } if route == .encrypt, let id = configuration.vault.encryptId { expected.append(contentsOf: ["--encrypt-vault-id", id]) } expected.append(vaultFilePath ?? "/vault.yml") return expected } static let testCases: [Self] = [ TestOptions(vaultFilePath: "/vault.yml"), TestOptions(extraOptions: ["--verbose"]), TestOptions(configuration: .mock), TestOptions(outputFilePath: "/output.yml") ] } struct TestError: Error {}