66 lines
2.8 KiB
Swift
66 lines
2.8 KiB
Swift
import XCTest
|
|
import Foundation
|
|
|
|
/// Regression test: ensures UpdatePill is never gated behind #if DEBUG in production code paths.
|
|
/// This prevents accidentally hiding the update UI in Release builds.
|
|
final class UpdatePillReleaseVisibilityTests: XCTestCase {
|
|
|
|
/// Source files that must show UpdatePill without #if DEBUG guards.
|
|
private let filesToCheck = [
|
|
"Sources/Update/UpdateTitlebarAccessory.swift",
|
|
"Sources/ContentView.swift",
|
|
]
|
|
|
|
func testUpdatePillNotGatedBehindDebug() throws {
|
|
let projectRoot = findProjectRoot()
|
|
|
|
for relativePath in filesToCheck {
|
|
let url = projectRoot.appendingPathComponent(relativePath)
|
|
let source = try String(contentsOf: url, encoding: .utf8)
|
|
let lines = source.components(separatedBy: .newlines)
|
|
|
|
// Track #if DEBUG nesting depth.
|
|
var debugDepth = 0
|
|
|
|
for (index, line) in lines.enumerated() {
|
|
let trimmed = line.trimmingCharacters(in: .whitespaces)
|
|
|
|
if trimmed == "#if DEBUG" || trimmed.hasPrefix("#if DEBUG ") {
|
|
debugDepth += 1
|
|
} else if trimmed == "#endif" && debugDepth > 0 {
|
|
debugDepth -= 1
|
|
} else if trimmed == "#else" && debugDepth > 0 {
|
|
// #else inside #if DEBUG means we're in the non-debug branch — that's fine.
|
|
// But UpdatePill in the #if DEBUG branch (before #else) is the problem.
|
|
// We handle this by only flagging UpdatePill when debugDepth > 0 and we haven't
|
|
// hit #else yet. For simplicity, treat #else as flipping out of the guarded section.
|
|
debugDepth -= 1
|
|
}
|
|
|
|
if debugDepth > 0 && trimmed.contains("UpdatePill") {
|
|
XCTFail(
|
|
"""
|
|
\(relativePath):\(index + 1) — UpdatePill is inside #if DEBUG. \
|
|
This hides the update UI in Release builds. Remove the #if DEBUG guard \
|
|
or move UpdatePill to the #else branch.
|
|
"""
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func findProjectRoot() -> URL {
|
|
// Walk up from the test bundle to find the project root (contains GhosttyTabs.xcodeproj).
|
|
var dir = URL(fileURLWithPath: #file).deletingLastPathComponent().deletingLastPathComponent()
|
|
for _ in 0..<10 {
|
|
let marker = dir.appendingPathComponent("GhosttyTabs.xcodeproj")
|
|
if FileManager.default.fileExists(atPath: marker.path) {
|
|
return dir
|
|
}
|
|
dir = dir.deletingLastPathComponent()
|
|
}
|
|
// Fallback: assume CWD is project root.
|
|
return URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
|
|
}
|
|
}
|