mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-06 07:38:21 +00:00
macOS: GhosttyUITests
This commit is contained in:
@@ -28,6 +28,13 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
810ACCA52E9D3302004F8F92 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = A5B30529299BEAAA0047F10C /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = A5B30530299BEAAA0047F10C;
|
||||
remoteInfo = Ghostty;
|
||||
};
|
||||
A54F45F72E1F047A0046BD5C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = A5B30529299BEAAA0047F10C /* Project object */;
|
||||
@@ -42,6 +49,7 @@
|
||||
3B39CAA42B33949B00DABEB8 /* GhosttyReleaseLocal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GhosttyReleaseLocal.entitlements; sourceTree = "<group>"; };
|
||||
55154BDF2B33911F001622DC /* ghostty */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ghostty; path = "../zig-out/share/ghostty"; sourceTree = "<group>"; };
|
||||
552964E52B34A9B400030505 /* vim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = vim; path = "../zig-out/share/vim"; sourceTree = "<group>"; };
|
||||
810ACC9F2E9D3301004F8F92 /* GhosttyUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GhosttyUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9351BE8E2D22937F003B3499 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = "../zig-out/share/nvim"; sourceTree = "<group>"; };
|
||||
A51BFC282B30F26D00E92F16 /* GhosttyDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GhosttyDebug.entitlements; sourceTree = "<group>"; };
|
||||
A546F1132D7B68D7003B11A0 /* locale */ = {isa = PBXFileReference; lastKnownFileType = folder; name = locale; path = "../zig-out/share/locale"; sourceTree = "<group>"; };
|
||||
@@ -198,11 +206,19 @@
|
||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
810ACCA02E9D3302004F8F92 /* GhosttyUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = GhosttyUITests; sourceTree = "<group>"; };
|
||||
81F82BC72E82815D001EDFA7 /* Sources */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (81F82CB12E8281F9001EDFA7 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 81F82CB02E8281F5001EDFA7 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Sources; sourceTree = "<group>"; };
|
||||
A54F45F42E1F047A0046BD5C /* Tests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Tests; sourceTree = "<group>"; };
|
||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
810ACC9C2E9D3301004F8F92 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A54F45F02E1F047A0046BD5C /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -259,6 +275,7 @@
|
||||
3B39CAA42B33949B00DABEB8 /* GhosttyReleaseLocal.entitlements */,
|
||||
81F82BC72E82815D001EDFA7 /* Sources */,
|
||||
A54F45F42E1F047A0046BD5C /* Tests */,
|
||||
810ACCA02E9D3302004F8F92 /* GhosttyUITests */,
|
||||
A5D495A3299BECBA00DD1313 /* Frameworks */,
|
||||
A5A1F8862A489D7400D1E8BC /* Resources */,
|
||||
A5B30532299BEAAA0047F10C /* Products */,
|
||||
@@ -271,6 +288,7 @@
|
||||
A5B30531299BEAAA0047F10C /* Ghostty.app */,
|
||||
A5D4499D2B53AE7B000F5B83 /* Ghostty-iOS.app */,
|
||||
A54F45F32E1F047A0046BD5C /* GhosttyTests.xctest */,
|
||||
810ACC9F2E9D3301004F8F92 /* GhosttyUITests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -287,6 +305,29 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
810ACC9E2E9D3301004F8F92 /* GhosttyUITests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 810ACCA72E9D3302004F8F92 /* Build configuration list for PBXNativeTarget "GhosttyUITests" */;
|
||||
buildPhases = (
|
||||
810ACC9B2E9D3301004F8F92 /* Sources */,
|
||||
810ACC9C2E9D3301004F8F92 /* Frameworks */,
|
||||
810ACC9D2E9D3301004F8F92 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
810ACCA62E9D3302004F8F92 /* PBXTargetDependency */,
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
810ACCA02E9D3302004F8F92 /* GhosttyUITests */,
|
||||
);
|
||||
name = GhosttyUITests;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = GhosttyUITests;
|
||||
productReference = 810ACC9F2E9D3301004F8F92 /* GhosttyUITests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
A54F45F22E1F047A0046BD5C /* GhosttyTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = A54F45FC2E1F047A0046BD5C /* Build configuration list for PBXNativeTarget "GhosttyTests" */;
|
||||
@@ -360,9 +401,13 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 2600;
|
||||
LastSwiftUpdateCheck = 2610;
|
||||
LastUpgradeCheck = 1610;
|
||||
TargetAttributes = {
|
||||
810ACC9E2E9D3301004F8F92 = {
|
||||
CreatedOnToolsVersion = 26.1;
|
||||
TestTargetID = A5B30530299BEAAA0047F10C;
|
||||
};
|
||||
A54F45F22E1F047A0046BD5C = {
|
||||
CreatedOnToolsVersion = 26.0;
|
||||
TestTargetID = A5B30530299BEAAA0047F10C;
|
||||
@@ -395,11 +440,19 @@
|
||||
A5B30530299BEAAA0047F10C /* Ghostty */,
|
||||
A5D4499C2B53AE7B000F5B83 /* Ghostty-iOS */,
|
||||
A54F45F22E1F047A0046BD5C /* GhosttyTests */,
|
||||
810ACC9E2E9D3301004F8F92 /* GhosttyUITests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
810ACC9D2E9D3301004F8F92 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A54F45F12E1F047A0046BD5C /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -438,6 +491,13 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
810ACC9B2E9D3301004F8F92 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
A54F45EF2E1F047A0046BD5C /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -462,6 +522,11 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
810ACCA62E9D3302004F8F92 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = A5B30530299BEAAA0047F10C /* Ghostty */;
|
||||
targetProxy = 810ACCA52E9D3302004F8F92 /* PBXContainerItemProxy */;
|
||||
};
|
||||
A54F45F82E1F047A0046BD5C /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = A5B30530299BEAAA0047F10C /* Ghostty */;
|
||||
@@ -579,6 +644,73 @@
|
||||
};
|
||||
name = ReleaseLocal;
|
||||
};
|
||||
810ACCA82E9D3302004F8F92 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 26.1;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.GhosttyUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_TARGET_NAME = Ghostty;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
810ACCA92E9D3302004F8F92 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 26.1;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.GhosttyUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_TARGET_NAME = Ghostty;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
810ACCAA2E9D3302004F8F92 /* ReleaseLocal */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 26.1;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.GhosttyUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = NO;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_TARGET_NAME = Ghostty;
|
||||
};
|
||||
name = ReleaseLocal;
|
||||
};
|
||||
A54F45F92E1F047A0046BD5C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -995,6 +1127,16 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
810ACCA72E9D3302004F8F92 /* Build configuration list for PBXNativeTarget "GhosttyUITests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
810ACCA82E9D3302004F8F92 /* Debug */,
|
||||
810ACCA92E9D3302004F8F92 /* Release */,
|
||||
810ACCAA2E9D3302004F8F92 /* ReleaseLocal */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = ReleaseLocal;
|
||||
};
|
||||
A54F45FC2E1F047A0046BD5C /* Build configuration list for PBXNativeTarget "GhosttyTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -40,6 +40,17 @@
|
||||
ReferencedContainer = "container:Ghostty.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "810ACC9E2E9D3301004F8F92"
|
||||
BuildableName = "GhosttyUITests.xctest"
|
||||
BlueprintName = "GhosttyUITests"
|
||||
ReferencedContainer = "container:Ghostty.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
|
||||
39
macos/GhosttyUITests/GhosttyTitleUITests.swift
Normal file
39
macos/GhosttyUITests/GhosttyTitleUITests.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// GhosttyTitleUITests.swift
|
||||
// GhosttyUITests
|
||||
//
|
||||
// Created by luca on 13.10.2025.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
final class GhosttyTitleUITests: XCTestCase {
|
||||
|
||||
override class var runsForEachTargetApplicationUIConfiguration: Bool {
|
||||
true
|
||||
}
|
||||
|
||||
var configFile: URL?
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
let temporaryConfig = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
||||
.appendingPathExtension("ghostty")
|
||||
try #"title = "GhosttyUITestsLaunchTests""#.write(to: temporaryConfig, atomically: true, encoding: .utf8)
|
||||
configFile = temporaryConfig
|
||||
}
|
||||
|
||||
override func tearDown() async throws {
|
||||
if let configFile {
|
||||
try FileManager.default.removeItem(at: configFile)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func testTitle() throws {
|
||||
let app = XCUIApplication()
|
||||
app.launchEnvironment["GHOSTTY_CONFIG_PATH"] = configFile?.path
|
||||
app.launch()
|
||||
|
||||
XCTAssert(app.windows.firstMatch.title == "GhosttyUITestsLaunchTests", "Oops, `title=` doesn't work!")
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ class AppDelegate: NSObject,
|
||||
private var derivedConfig: DerivedConfig = DerivedConfig()
|
||||
|
||||
/// The ghostty global state. Only one per process.
|
||||
let ghostty: Ghostty.App = Ghostty.App()
|
||||
let ghostty: Ghostty.App
|
||||
|
||||
/// The global undo manager for app-level state such as window restoration.
|
||||
lazy var undoManager = ExpiringUndoManager()
|
||||
@@ -155,6 +155,11 @@ class AppDelegate: NSObject,
|
||||
@Published private(set) var appIcon: NSImage? = nil
|
||||
|
||||
override init() {
|
||||
#if DEBUG
|
||||
ghostty = Ghostty.App(configPath: ProcessInfo.processInfo.environment["GHOSTTY_CONFIG_PATH"])
|
||||
#else
|
||||
ghostty = Ghostty.App()
|
||||
#endif
|
||||
super.init()
|
||||
|
||||
ghostty.delegate = self
|
||||
|
||||
@@ -27,8 +27,10 @@ extension Ghostty {
|
||||
/// The global app configuration. This defines the app level configuration plus any behavior
|
||||
/// for new windows, tabs, etc. Note that when creating a new window, it may inherit some
|
||||
/// configuration (i.e. font size) from the previously focused window. This would override this.
|
||||
@Published private(set) var config: Config
|
||||
@Published fileprivate(set) var config: Config
|
||||
|
||||
/// Preferred config file than the default ones
|
||||
private var configPath: String?
|
||||
/// The ghostty app instance. We only have one of these for the entire app, although I guess
|
||||
/// in theory you can have multiple... I don't know why you would...
|
||||
@Published var app: ghostty_app_t? = nil {
|
||||
@@ -44,9 +46,10 @@ extension Ghostty {
|
||||
return ghostty_app_needs_confirm_quit(app)
|
||||
}
|
||||
|
||||
init() {
|
||||
init(configPath: String? = nil) {
|
||||
self.configPath = configPath
|
||||
// Initialize the global configuration.
|
||||
self.config = Config()
|
||||
self.config = configPath.flatMap({ Self.readConfig(at: $0, finalize: true) }) ?? Config()
|
||||
if self.config.config == nil {
|
||||
readiness = .error
|
||||
return
|
||||
@@ -143,7 +146,7 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
// Hard or full updates have to reload the full configuration
|
||||
let newConfig = Config()
|
||||
let newConfig = configPath.flatMap({ Self.readConfig(at: $0, finalize: true) }) ?? Config()
|
||||
guard newConfig.loaded else {
|
||||
Ghostty.logger.warning("failed to reload configuration")
|
||||
return
|
||||
@@ -163,7 +166,7 @@ extension Ghostty {
|
||||
// Hard or full updates have to reload the full configuration.
|
||||
// NOTE: We never set this on self.config because this is a surface-only
|
||||
// config. We free it after the call.
|
||||
let newConfig = Config()
|
||||
let newConfig = configPath.flatMap({ Self.readConfig(at: $0, finalize: true) }) ?? Config()
|
||||
guard newConfig.loaded else {
|
||||
Ghostty.logger.warning("failed to reload configuration")
|
||||
return
|
||||
@@ -2074,3 +2077,27 @@ extension Ghostty {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
extension Ghostty.App {
|
||||
static func readConfig(at path: String, finalize: Bool = true) -> Ghostty.Config? {
|
||||
guard
|
||||
let cfg = ghostty_config_new()
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
if FileManager.default.fileExists(atPath: path) {
|
||||
ghostty_config_load_file(cfg, path)
|
||||
}
|
||||
if !isRunningInXcode() {
|
||||
ghostty_config_load_cli_args(cfg)
|
||||
}
|
||||
ghostty_config_load_recursive_files(cfg)
|
||||
if finalize {
|
||||
// Finalize will make our defaults available,
|
||||
// and also will combine all the keys into one file,
|
||||
// we might not need this in the future
|
||||
ghostty_config_finalize(cfg)
|
||||
}
|
||||
return Ghostty.Config(config: cfg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,14 +33,16 @@ extension Ghostty {
|
||||
return diags
|
||||
}
|
||||
|
||||
init() {
|
||||
if let cfg = Self.loadConfig() {
|
||||
self.config = cfg
|
||||
}
|
||||
init(config: ghostty_config_t?) {
|
||||
self.config = config
|
||||
}
|
||||
|
||||
init(clone config: ghostty_config_t) {
|
||||
self.config = ghostty_config_clone(config)
|
||||
convenience init() {
|
||||
self.init(config: Self.loadConfig())
|
||||
}
|
||||
|
||||
convenience init(clone config: ghostty_config_t) {
|
||||
self.init(config: ghostty_config_clone(config))
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
Reference in New Issue
Block a user