mac: more tests

This commit is contained in:
Peter Steinberger 2025-06-23 14:48:17 +02:00
parent c7e0675d5c
commit 7c41a8cc53
4 changed files with 434 additions and 0 deletions

View file

@ -0,0 +1,103 @@
import Foundation
import Testing
@testable import VibeTunnel
@Suite("AppleScript Executor Tests", .tags(.integration))
struct AppleScriptExecutorTests {
@Test("Execute simple AppleScript")
@MainActor
func executeSimpleScript() throws {
let script = """
return "Hello from AppleScript"
"""
let result = try AppleScriptExecutor.shared.executeWithResult(script)
#expect(result == "Hello from AppleScript")
}
@Test("Execute script with math")
@MainActor
func executeScriptWithMath() throws {
let script = """
return 2 + 2
"""
let result = try AppleScriptExecutor.shared.executeWithResult(script)
#expect(result == "4")
}
@Test("Handle script error")
@MainActor
func handleScriptError() throws {
let script = """
error "This is a test error"
"""
do {
_ = try AppleScriptExecutor.shared.executeWithResult(script)
Issue.record("Expected error to be thrown")
} catch {
#expect(error.localizedDescription.contains("test error"))
}
}
@Test("Handle invalid syntax")
@MainActor
func handleInvalidSyntax() throws {
let script = """
this is not valid applescript syntax
"""
do {
_ = try AppleScriptExecutor.shared.executeWithResult(script)
Issue.record("Expected error to be thrown")
} catch {
// Should throw a syntax error
#expect(error is AppleScriptError)
}
}
@Test("Execute empty script")
@MainActor
func executeEmptyScript() throws {
let script = ""
do {
let result = try AppleScriptExecutor.shared.executeWithResult(script)
#expect(result.isEmpty || result == "missing value")
} catch {
// Empty script might throw an error, which is also acceptable
#expect(error is AppleScriptError)
}
}
@Test("Check Terminal application")
@MainActor
func checkTerminalApplication() throws {
let script = """
tell application "System Events"
return exists application process "Terminal"
end tell
"""
let result = try AppleScriptExecutor.shared.executeWithResult(script)
// Result will be "true" or "false" as a string
#expect(result == "true" || result == "false")
}
@Test("Test async execution")
func testAsyncExecution() async throws {
// Test the async method
let hasPermission = await AppleScriptExecutor.shared.checkPermission()
#expect(hasPermission == true || hasPermission == false)
}
@Test("Singleton instance")
@MainActor
func singletonInstance() {
let instance1 = AppleScriptExecutor.shared
let instance2 = AppleScriptExecutor.shared
#expect(instance1 === instance2)
}
}

View file

@ -0,0 +1,109 @@
import Foundation
import Testing
import AppKit
@testable import VibeTunnel
@Suite("Dock Icon Manager Tests")
struct DockIconManagerTests {
@Test("Singleton instance")
@MainActor
func singletonInstance() {
let instance1 = DockIconManager.shared
let instance2 = DockIconManager.shared
#expect(instance1 === instance2)
}
@Test("User preference for dock icon")
func userPreferenceForDockIcon() {
// Store current value to restore later
let currentValue = UserDefaults.standard.bool(forKey: "showInDock")
// Test with dock icon enabled
UserDefaults.standard.set(true, forKey: "showInDock")
#expect(UserDefaults.standard.bool(forKey: "showInDock") == true)
// Test with dock icon disabled
UserDefaults.standard.set(false, forKey: "showInDock")
#expect(UserDefaults.standard.bool(forKey: "showInDock") == false)
// Restore original value
UserDefaults.standard.set(currentValue, forKey: "showInDock")
}
@Test("Update dock visibility based on windows")
@MainActor
func updateDockVisibilityBasedOnWindows() {
let manager = DockIconManager.shared
// Save original preference
let originalPref = UserDefaults.standard.bool(forKey: "showInDock")
// Set preference to hide dock
UserDefaults.standard.set(false, forKey: "showInDock")
// Update visibility - with no windows, dock should be hidden
manager.updateDockVisibility()
// The policy depends on whether there are windows open
// In test environment, NSApp might be nil
if let app = NSApp {
#expect(app.activationPolicy() == .regular || app.activationPolicy() == .accessory)
} else {
// In test environment without NSApp, just verify no crash
#expect(true)
}
// Restore original preference
UserDefaults.standard.set(originalPref, forKey: "showInDock")
}
@Test("Temporarily show dock")
@MainActor
func temporarilyShowDock() {
let manager = DockIconManager.shared
// Call temporarilyShowDock
manager.temporarilyShowDock()
// Should always show as regular
if let app = NSApp {
#expect(app.activationPolicy() == .regular)
} else {
// In test environment without NSApp, just verify no crash
#expect(true)
}
}
@Test("Dock visibility with user preference")
@MainActor
func dockVisibilityWithUserPreference() {
let manager = DockIconManager.shared
let originalPref = UserDefaults.standard.bool(forKey: "showInDock")
// Test with showInDock = true (user wants dock visible)
UserDefaults.standard.set(true, forKey: "showInDock")
manager.updateDockVisibility()
if let app = NSApp {
#expect(app.activationPolicy() == .regular)
} else {
// In test environment without NSApp, just verify no crash
#expect(true)
}
// Test with showInDock = false (user wants dock hidden)
UserDefaults.standard.set(false, forKey: "showInDock")
manager.updateDockVisibility()
// Dock visibility depends on whether windows are open
// In test environment, NSApp might be nil
if let app = NSApp {
#expect(app.activationPolicy() == .regular || app.activationPolicy() == .accessory)
} else {
// In test environment without NSApp, just verify no crash
#expect(true)
}
// Restore
UserDefaults.standard.set(originalPref, forKey: "showInDock")
}
}

View file

@ -0,0 +1,136 @@
import Foundation
import Testing
@testable import VibeTunnel
@Suite("Ngrok Service Tests", .tags(.networking))
struct NgrokServiceTests {
let testAuthToken = "test_auth_token_123"
let testPort = 8888
@Test("Singleton instance")
@MainActor
func singletonInstance() {
let instance1 = NgrokService.shared
let instance2 = NgrokService.shared
#expect(instance1 === instance2)
}
@Test("Initial state")
@MainActor
func initialState() {
let service = NgrokService.shared
#expect(service.isActive == false)
#expect(service.publicUrl == nil)
#expect(service.tunnelStatus == nil)
}
@Test("Auth token management")
@MainActor
func authTokenManagement() {
let service = NgrokService.shared
// Save original token
let originalToken = service.authToken
// Set test token
service.authToken = testAuthToken
#expect(service.authToken == testAuthToken)
#expect(service.hasAuthToken == true)
// Clear token
service.authToken = nil
#expect(service.authToken == nil)
#expect(service.hasAuthToken == false)
// Restore original token
service.authToken = originalToken
}
@Test("Start without auth token fails")
@MainActor
func startWithoutAuthToken() async throws {
let service = NgrokService.shared
// Save original token
let originalToken = service.authToken
// Clear token
service.authToken = nil
do {
_ = try await service.start(port: testPort)
Issue.record("Expected error to be thrown")
} catch let error as NgrokError {
#expect(error == .authTokenMissing)
} catch {
Issue.record("Expected NgrokError.authTokenMissing")
}
// Restore original token
service.authToken = originalToken
}
@Test("Stop when not running")
@MainActor
func stopWhenNotRunning() async throws {
let service = NgrokService.shared
// Ensure not running
if service.isActive {
try await service.stop()
}
// Stop again should be safe
try await service.stop()
#expect(service.isActive == false)
#expect(service.publicUrl == nil)
}
@Test("Is running check")
@MainActor
func isRunningCheck() async {
let service = NgrokService.shared
let running = await service.isRunning()
#expect(running == service.isActive)
}
@Test("Get status when inactive")
@MainActor
func getStatusWhenInactive() async {
let service = NgrokService.shared
// Ensure not running
if service.isActive {
try? await service.stop()
}
let status = await service.getStatus()
#expect(status == nil)
}
@Test("NgrokError descriptions")
func ngrokErrorDescriptions() {
let errors: [NgrokError] = [
.notInstalled,
.authTokenMissing,
.tunnelCreationFailed("test error"),
.invalidConfiguration,
.networkError("connection failed")
]
for error in errors {
#expect(error.errorDescription != nil)
#expect(!error.errorDescription!.isEmpty)
}
}
@Test("NgrokError equality")
func ngrokErrorEquality() {
#expect(NgrokError.notInstalled == NgrokError.notInstalled)
#expect(NgrokError.authTokenMissing == NgrokError.authTokenMissing)
#expect(NgrokError.tunnelCreationFailed("a") == NgrokError.tunnelCreationFailed("a"))
#expect(NgrokError.tunnelCreationFailed("a") != NgrokError.tunnelCreationFailed("b"))
}
}

View file

@ -0,0 +1,86 @@
import Foundation
import Testing
import ServiceManagement
@testable import VibeTunnel
@Suite("Startup Manager Tests")
struct StartupManagerTests {
@Test("Create instance")
@MainActor
func createInstance() {
let manager = StartupManager()
// Just verify we can create an instance
#expect(manager.isLaunchAtLoginEnabled == true || manager.isLaunchAtLoginEnabled == false)
}
@Test("Initial launch at login state")
@MainActor
func initialLaunchAtLoginState() {
let manager = StartupManager()
// The initial state depends on system configuration
// We just verify it returns a boolean
let state = manager.isLaunchAtLoginEnabled
#expect(state == true || state == false)
}
@Test("Set launch at login")
@MainActor
func setLaunchAtLogin() {
let manager = StartupManager()
// Try to enable (may fail in test environment)
manager.setLaunchAtLogin(enabled: true)
// Try to disable (may fail in test environment)
manager.setLaunchAtLogin(enabled: false)
// We can't verify the actual state change in tests
// Just ensure the methods don't crash
#expect(true)
}
@Test("Service management availability")
@available(macOS 13.0, *)
func serviceManagementAvailability() {
// Test that we can at least query the service status
let service = SMAppService.mainApp
// Status should be queryable
let status = service.status
// We just verify that we can get a status without crashing
// The actual value depends on the test environment
#expect(status.rawValue >= 0)
}
@Test("App bundle identifier")
func appBundleIdentifier() {
// In test environment, bundle identifier might be nil
let bundleId = Bundle.main.bundleIdentifier
if let bundleId = bundleId {
#expect(!bundleId.isEmpty)
// In test environment, might be different than production
#expect(bundleId.contains("VibeTunnel") || bundleId.contains("xctest") || bundleId.contains("swift"))
} else {
// It's OK for bundle ID to be nil in test environment
#expect(bundleId == nil)
}
}
@Test("Multiple operations")
@MainActor
func multipleOperations() {
let manager = StartupManager()
// Perform multiple operations
manager.setLaunchAtLogin(enabled: true)
manager.setLaunchAtLogin(enabled: false)
manager.setLaunchAtLogin(enabled: true)
// Just ensure no crashes
#expect(true)
}
}