mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-15 12:55:52 +00:00
mac: more tests
This commit is contained in:
parent
c7e0675d5c
commit
7c41a8cc53
4 changed files with 434 additions and 0 deletions
103
mac/VibeTunnelTests/AppleScriptExecutorTests.swift
Normal file
103
mac/VibeTunnelTests/AppleScriptExecutorTests.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
109
mac/VibeTunnelTests/DockIconManagerTests.swift
Normal file
109
mac/VibeTunnelTests/DockIconManagerTests.swift
Normal 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")
|
||||
}
|
||||
}
|
||||
136
mac/VibeTunnelTests/NgrokServiceTests.swift
Normal file
136
mac/VibeTunnelTests/NgrokServiceTests.swift
Normal 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"))
|
||||
}
|
||||
}
|
||||
86
mac/VibeTunnelTests/StartupManagerTests.swift
Normal file
86
mac/VibeTunnelTests/StartupManagerTests.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue