Files
SwiftGen/Sources/TestUtils/VariationGenerator.swift
David Jennes 4d1d3591c7 Bump year
2022-07-30 20:47:39 +02:00

93 lines
3.4 KiB
Swift

//
// Templates UnitTests
// Copyright © 2022 SwiftGen
// MIT Licence
//
import PathKit
import Stencil
import StencilSwiftKit
import SwiftGenKit
import XCTest
public extension XCTestCase {
///
/// Generate variations of a context.
///
/// - Parameter name: The name of the context
/// - Parameter context: The context itself
/// - Return: a tuple with a list of generated contexts, and a suffix to find the correct output file
///
typealias VariationGenerator = ((String, [String: Any]) throws -> [(context: [String: Any], suffix: String)])
///
/// Test the given template against a list of contexts, comparing the output with files in the expected folder.
///
/// - Parameter template: The name of the template (without the `stencil` extension)
/// - Parameter contextNames: A list of context names (without the `plist` extension)
/// - Parameter directory: The directory to look for files in (corresponds to the command)
/// - Parameter resourceDirectory: The directory to look for files in (corresponds to the command)
/// - Parameter contextVariations: Optional closure to generate context variations.
///
func test(
template templateName: String,
contextNames: [String],
directory: Fixtures.Directory,
resourceDirectory: Fixtures.Directory? = nil,
outputDirectory: Fixtures.Directory? = nil,
file: StaticString = #file,
line: UInt = #line,
contextVariations: VariationGenerator? = nil,
outputExtension: String = "swift"
) {
let template: Template
do {
let templateRealPath = Fixtures.template(for: "\(templateName).stencil", sub: directory)
template = try Template.load(from: templateRealPath, modernSpacing: true)
} catch {
fatalError("Unable to load fixture \(templateName)'s content: \(error)")
}
// default values
let contextVariations = contextVariations ?? { [(context: $1, suffix: "")] }
let resourceDir = resourceDirectory ?? directory
let outputDir = outputDirectory ?? resourceDir
for contextName in contextNames {
print("Testing context '\(contextName)'...")
let context = Fixtures.context(for: "\(contextName).yaml", sub: resourceDir)
// generate context variations
guard let variations = try? contextVariations(contextName, context) else {
fatalError("Unable to generate context variations")
}
for (index, (context: context, suffix: suffix)) in variations.enumerated() {
let outputFile = "\(contextName)\(suffix).\(outputExtension)"
if variations.count > 1 { print(" - Variation #\(index)... (expecting: \(outputFile))") }
let result: String
do {
result = try template.render(context)
} catch let error {
fatalError("Unable to render template: \(error)")
}
// check if we should generate or not
if ProcessInfo().environment["GENERATE_OUTPUT"] == "YES" {
let target = Path(#filePath).parent() + "Fixtures/Generated" + outputDir.rawValue +
templateName + outputFile
do {
try target.write(result)
} catch {
fatalError("Unable to write output file \(target)")
}
} else {
let expected = Fixtures.output(template: templateName, variation: outputFile, sub: outputDir)
XCTDiffStrings(result, expected, file: file, line: line)
}
}
}
}
}