import Foundation import Testing /// Root of the package: Tests/SstUITests/ → 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 = ["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"))") } }