59 lines
3.2 KiB
Swift
59 lines
3.2 KiB
Swift
import Foundation
|
|
import Testing
|
|
|
|
/// Root of the package: Tests/SstUITests/<this file> → three levels up.
|
|
private let root = URL(fileURLWithPath: #filePath)
|
|
.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent()
|
|
|
|
struct TokenIntegrityTests {
|
|
@Test func generatedSwiftMatchesTokensJSONAndContrastHolds() throws {
|
|
#expect(
|
|
FileManager.default.fileExists(atPath: root.appending(path: "Sources/SstUI/DesignTokens.swift").path),
|
|
"Sources/SstUI/DesignTokens.swift ontbreekt: run `python3 Design/build_tokens.py`.")
|
|
let process = Process()
|
|
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
|
|
process.arguments = ["python3", "Design/build_tokens.py", "--check"]
|
|
process.currentDirectoryURL = root
|
|
let pipe = Pipe()
|
|
process.standardOutput = pipe
|
|
process.standardError = pipe
|
|
try process.run()
|
|
process.waitUntilExit()
|
|
let output = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
|
|
#expect(process.terminationStatus == 0, "Run `python3 Design/build_tokens.py`.\n\(output.suffix(600))")
|
|
}
|
|
|
|
/// Views take every colour, size and time from the tokens. A line may opt out with `// token-exempt: reason`.
|
|
@Test func viewsContainNoLooseDesignValues() throws {
|
|
let forbidden: [(name: String, pattern: String)] = [
|
|
("hex colour", #"0x[0-9A-Fa-f]{6}\b"#),
|
|
("component colour", #"(NS)?Color\((red|white|hue):"#),
|
|
("literal font size", #"\.system\(size:\s*\d"#),
|
|
("literal corner radius", #"cornerRadius:\s*\d|\.cornerRadius\(\s*\d"#),
|
|
("literal padding", #"\.padding\(\s*(\.\w+\s*,\s*)?\d"#),
|
|
("literal frame size", #"(width|height|minWidth|minHeight|maxWidth|maxHeight|idealWidth|idealHeight):\s*[1-9]"#),
|
|
("literal line width", #"lineWidth:\s*\d"#),
|
|
("literal opacity", #"\.opacity\(\s*[0-9]"#),
|
|
]
|
|
let skipped: Set<String> = ["DesignTokens.swift", "DynamicColor.swift"]
|
|
var directories = [root.appending(path: "Sources/SstUI")]
|
|
let app = root.appending(path: "Sources/Sst")
|
|
if FileManager.default.fileExists(atPath: app.path) { directories.append(app) }
|
|
|
|
var problems: [String] = []
|
|
for directory in directories {
|
|
let files = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil)
|
|
.filter { $0.pathExtension == "swift" && !skipped.contains($0.lastPathComponent) }
|
|
for file in files {
|
|
let lines = try String(contentsOf: file, encoding: .utf8).components(separatedBy: "\n")
|
|
for (index, line) in lines.enumerated() where !line.contains("token-exempt") {
|
|
for rule in forbidden where line.range(of: rule.pattern, options: .regularExpression) != nil {
|
|
problems.append("\(file.lastPathComponent):\(index + 1) \(rule.name): \(line.trimmingCharacters(in: .whitespaces))")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#expect(problems.isEmpty, "Loose design values:\n\(problems.joined(separator: "\n"))")
|
|
}
|
|
}
|