Skip to content

Commit

Permalink
Support for environment parameters in 'prefire.yml'
Browse files Browse the repository at this point in the history
  • Loading branch information
BarredEwe committed May 30, 2024
1 parent 3d0f8c0 commit ee0b7fb
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 46 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Foundation

private enum Constants {
static let outputFileName = "PreviewModels.generated.swift"
static let configFileName = "sourcery.yml"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extension Prefire {
output: output,
template: template,
cacheBasePath: cacheBasePath,
config: Config.load(from: config, testTargetPath: nil)
config: Config.load(from: config, testTargetPath: nil, env: ProcessInfo.processInfo.environment)
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,31 +95,26 @@ enum GenerateTestsCommand {
}

static func makeArguments(for options: GeneratedTestsOptions) -> [String: Any?] {
guard let target = options.target else {
fatalError("You must provide the --target")
}

let sources = options.sources
let output = options.output ?? FileManager.default.currentDirectoryPath.appending("/\(Constants.snapshotFileName).generated.swift")
let snapshotOutput = (options.testTargetPath ?? FileManager.default.currentDirectoryPath)
.appending("/\(Constants.snapshotFileName).swift")
let snapshotOutput = options.testTargetPath?.appending("/\(Constants.snapshotFileName).swift")

Logger.print(
"""
Prefire configuration
➜ Target used for tests: \(target)
➜ Target used for tests: \(options.target ?? "nil")
➜ Tests target: \(options.testTarget ?? "nil")
➜ Sourcery path: \(options.sourcery)
➜ Template path: \(options.template)
➜ Generated test path: \(output)
➜ Snapshot resources path: \(snapshotOutput)
➜ Snapshot resources path: \(snapshotOutput ?? "nil")
➜ Preview default enabled: \(options.prefireEnabledMarker)
"""
)

// Works with `#Preview` macro
#if swift(>=5.9)
let previewBodies = PreviewLoader.loadPreviewBodies(for: target, and: sources, defaultEnabled: options.prefireEnabledMarker)
let previewBodies = PreviewLoader.loadPreviewBodies(for: sources, defaultEnabled: options.prefireEnabledMarker)
#else
let previewBodies: String? = nil
#endif
Expand All @@ -136,7 +131,7 @@ enum GenerateTestsCommand {
Keys.previewsMacros: previewBodies,
Keys.imports: options.imports,
Keys.testableImports: options.testableImports,
Keys.mainTarget: target,
Keys.mainTarget: options.target,
Keys.file: snapshotOutput,
] as [String: Any?]
]
Expand Down
4 changes: 2 additions & 2 deletions PrefireExecutable/Sources/prefire/Commands/Tests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extension Prefire {
static let configuration = CommandConfiguration(abstract: "Generate Snapshot/Accessibility Tests")

@Argument(help: "Paths to a source swift files or directories.")
var sources: [String]
var sources: [String] = []

@Option(help: "Path to the sourcery.")
var sourcery: String
Expand Down Expand Up @@ -49,7 +49,7 @@ extension Prefire {
cacheBasePath: cacheBasePath,
device: device,
osVersion: osVersion,
config: Config.load(from: config, testTargetPath: testTargetPath)
config: Config.load(from: config, testTargetPath: testTargetPath, env: ProcessInfo.processInfo.environment)
)
)
}
Expand Down
66 changes: 44 additions & 22 deletions PrefireExecutable/Sources/prefire/Config/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct Config {
var tests = TestsConfig()
var playbook = PlaybookConfig()

init?(from configDataString: String) {
init?(from configDataString: String, env: [String : String]) {
var isTestConfig = false
var isPlaybookConfig = false

Expand All @@ -48,58 +48,58 @@ struct Config {
let components = lines[index].components(separatedBy: Constants.separtor)

if isTestConfig {
if let target = Config.getValue(from: components, key: .target) {
if let target = Config.getValue(from: components, key: .target, env: env) {
tests.target = target
continue
}
if let testFilePath = Config.getValue(from: components, key: .test_file_path) {
if let testFilePath = Config.getValue(from: components, key: .test_file_path, env: env) {
tests.testFilePath = testFilePath
continue
}
if let template = Config.getValue(from: components, key: .template_file_path) {
if let template = Config.getValue(from: components, key: .template_file_path, env: env) {
tests.template = template
continue
}
if let device = Config.getValue(from: components, key: .simulator_device) {
if let device = Config.getValue(from: components, key: .simulator_device, env: env) {
tests.device = device
continue
}
if let osVersion = Config.getValue(from: components, key: .required_os) {
if let osVersion = Config.getValue(from: components, key: .required_os, env: env) {
tests.osVersion = osVersion
continue
}
if let snapshotDevices = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .snapshot_devices) {
if let snapshotDevices = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .snapshot_devices, env: env) {
tests.snapshotDevices = snapshotDevices
continue
}
if let previewDefaultEnabled = Config.getValue(from: components, key: .preview_default_enabled) {
if let previewDefaultEnabled = Config.getValue(from: components, key: .preview_default_enabled, env: env) {
tests.previewDefaultEnabled = previewDefaultEnabled == "true"
continue
}
if let imports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .imports) {
if let imports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .imports, env: env) {
tests.imports = imports
continue
}
if let testableImports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .testable_imports) {
if let testableImports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .testable_imports, env: env) {
tests.testableImports = testableImports
continue
}
}

if isPlaybookConfig {
if let template = Config.getValue(from: components, key: .template_file_path) {
if let template = Config.getValue(from: components, key: .template_file_path, env: env) {
playbook.template = template
continue
}
if let previewDefaultEnabled = Config.getValue(from: components, key: .preview_default_enabled) {
if let previewDefaultEnabled = Config.getValue(from: components, key: .preview_default_enabled, env: env) {
playbook.previewDefaultEnabled = previewDefaultEnabled == "true"
continue
}
if let imports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .imports) {
if let imports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .imports, env: env) {
playbook.imports = imports
continue
}
if let testableImports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .testable_imports) {
if let testableImports = Config.getValues(from: components, lines: Array(lines[index..<lines.count]), key: .testable_imports, env: env) {
playbook.testableImports = testableImports
continue
}
Expand All @@ -125,7 +125,7 @@ extension Config {
case playbook_configuration
}

static func load(from configPath: String?, testTargetPath: String?) -> Config? {
static func load(from configPath: String?, testTargetPath: String?, env: [String : String]) -> Config? {
let possibleConfigPaths = ConfigPathBuilder.possibleConfigPaths(for: configPath, testTargetPath: testTargetPath)

for path in possibleConfigPaths {
Expand All @@ -135,7 +135,7 @@ extension Config {

Logger.print("🟢 The '.prefire' file is used on the path: \(configUrl.path)")

if let configuration = Config(from: configDataString) {
if let configuration = Config(from: configDataString, env: env) {
return configuration
}
}
Expand All @@ -147,32 +147,54 @@ extension Config {

// MARK: - Private

private static func getValues(from components: [String], lines: [String], key: Keys) -> [String]? {
private static func getValues(from components: [String], lines: [String], key: Keys, env: [String : String]) -> [String]? {
guard (components.first?.hasSuffix("- \(key.rawValue)") ?? false) == true, components.last?.isEmpty == true else { return nil }

var values = [String]()

for line in lines[1..<lines.count] {
guard !line.contains(Constants.separtor) else { return values }

let value = line
var value = line
.trimmingCharacters(in: CharacterSet.whitespaces)
.replacingOccurrences(of: "\"", with: "")
.replacingOccurrences(of: "- ", with: "")

if !value.isEmpty {
values.append(value)
guard !value.isEmpty else { continue }

// Check and replace if the value contains a key formatted as "${key}"
if let key = value.findKey(), let envValue = env[key] {
value = value.replacingOccurrences(of: "${\(key)}", with: envValue)
}

values.append(value)
}

return values
}

private static func getValue(from components: [String], key: Keys) -> String? {
private static func getValue(from components: [String], key: Keys, env: [String : String]) -> String? {
guard components.first?.hasSuffix("- \(key.rawValue)") == true else { return nil }

return components.last?
var value = components.last?
.trimmingCharacters(in: CharacterSet.whitespaces)
.replacingOccurrences(of: "\"", with: "")

// Check and replace if the value contains a key formatted as "${key}"
if let key = value?.findKey(), let envValue = env[key] {
value = value?.replacingOccurrences(of: "${\(key)}", with: envValue)
}

return value
}
}

private extension String {
/// Extract the key enclosed within "${}" from a string
/// - Returns: Key
func findKey() -> String? {
guard contains("${") else { return nil }

return components(separatedBy: "${").last?.components(separatedBy: "}").first
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ extension PreviewLoader {
private static let yamlSettings = "|-4\n\n"
private static let previewSpaces = " "

static func loadPreviewBodies(for target: String, and sources: [String], defaultEnabled: Bool) -> String? {
static func loadPreviewBodies(for sources: [String], defaultEnabled: Bool) -> String? {
guard let findedBodies = loadRawPreviewBodies(for: sources, defaultEnabled: defaultEnabled) else { return nil }

let result = findedBodies.map { makeFunc(body: $0) + "\r\n" }.joined()
Expand Down
8 changes: 5 additions & 3 deletions PrefireExecutable/Tests/PrefireTests/ConfigTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ConfigTests: XCTestCase {
private let prefireConfigString = """
test_configuration:
- target: PrefireExample
- test_file_path: PrefireExampleTests/PreviewTests.generated.swift
- test_file_path: ${TARGET_DIR}/PrefireExampleTests/PreviewTests.generated.swift
- template_file_path: CustomPreviewTests.stencil
- simulator_device: "iPhone15,2"
- required_os: 17
Expand All @@ -26,13 +26,14 @@ class ConfigTests: XCTestCase {
- Foundation
- testable_imports:
- SwiftUI
- preview_default_enabled: false
"""

func test_successCreateConfig() {
let config = Config(from: prefireConfigString)
let config = Config(from: prefireConfigString, env: ["TARGET_DIR":"/User/Tests"])

XCTAssertEqual(config?.tests.target, "PrefireExample")
XCTAssertEqual(config?.tests.testFilePath, "PrefireExampleTests/PreviewTests.generated.swift")
XCTAssertEqual(config?.tests.testFilePath, "/User/Tests/PrefireExampleTests/PreviewTests.generated.swift")
XCTAssertEqual(config?.tests.template, "CustomPreviewTests.stencil")
XCTAssertEqual(config?.tests.device, "iPhone15,2")
XCTAssertEqual(config?.tests.osVersion, "17")
Expand All @@ -43,5 +44,6 @@ class ConfigTests: XCTestCase {
XCTAssertEqual(config?.playbook.imports, ["UIKit", "Foundation"])
XCTAssertEqual(config?.playbook.testableImports, ["SwiftUI"])
XCTAssertEqual(config?.playbook.template, "CustomModels.stencil")
XCTAssertEqual(config?.playbook.previewDefaultEnabled, false)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class GenerateTestsCommandTests: XCTestCase {
testTarget: "GenerateTestsCommandTests",
template: "templatePath",
sources: [],
output: nil,
testTargetPath: nil,
output: "User/Tests/PreviewTests.generated.swift",
testTargetPath: "User/Tests",
cacheBasePath: nil,
device: nil,
osVersion: nil,
Expand All @@ -25,7 +25,7 @@ class GenerateTestsCommandTests: XCTestCase {
func test_makeArguments_sources() {
options.sources = ["some/sources"]
let expectedArguments = [
"output": FileManager.default.currentDirectoryPath + "/PreviewTests.generated.swift",
"output": options.output,
"sources": options.sources,
"templates": [options.template],
"cacheBasePath": options.cacheBasePath,
Expand All @@ -37,7 +37,7 @@ class GenerateTestsCommandTests: XCTestCase {
"imports": options.imports,
"testableImports": options.testableImports,
"mainTarget": options.target,
"file": "\(FileManager.default.currentDirectoryPath)/PreviewTests.swift",
"file": options.testTargetPath.flatMap({ $0 + "/PreviewTests.swift"}),
],
] as [String: Any?]

Expand All @@ -53,10 +53,10 @@ class GenerateTestsCommandTests: XCTestCase {
let expectedArguments = [
"templates": [options.template],
"sources": ["some/sources", "some/other/sources"],
"output": FileManager.default.currentDirectoryPath + "/PreviewTests.generated.swift",
"output": options.output,
"args": [
"mainTarget": "\(options.target ?? "")",
"file": "\(FileManager.default.currentDirectoryPath)/PreviewTests.swift",
"file": options.testTargetPath.flatMap({ $0 + "/PreviewTests.swift"}),
"snapshotDevices": "iPhone 15|iPad",
]
] as [String: Any?]
Expand Down

0 comments on commit ee0b7fb

Please sign in to comment.