From a791bbede83787aa29d21812693383de3c291a2d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 22 Jun 2025 10:11:43 +0200 Subject: [PATCH] test fixes --- mac/VibeTunnelTests/ServerManagerTests.swift | 20 +++--- .../SessionIdHandlingTests.swift | 8 ++- mac/VibeTunnelTests/SessionMonitorTests.swift | 70 +++++++++---------- mac/VibeTunnelTests/TerminalLaunchTests.swift | 68 +++++++++--------- 4 files changed, 84 insertions(+), 82 deletions(-) diff --git a/mac/VibeTunnelTests/ServerManagerTests.swift b/mac/VibeTunnelTests/ServerManagerTests.swift index 3270ad07..4ff38ead 100644 --- a/mac/VibeTunnelTests/ServerManagerTests.swift +++ b/mac/VibeTunnelTests/ServerManagerTests.swift @@ -7,14 +7,14 @@ import Testing @Suite("Server Manager Tests") @MainActor final class ServerManagerTests { - // We'll use the shared ServerManager instance since it's a singleton + /// We'll use the shared ServerManager instance since it's a singleton let manager = ServerManager.shared - + init() async { // Ensure clean state before each test await manager.stop() } - + deinit { // Clean up is handled in init() of next test since we can't use async in deinit } @@ -34,7 +34,7 @@ final class ServerManagerTests { if let error = manager.lastError as? BunServerError { #expect(error == .binaryNotFound) } - + // Server should not be running without the binary #expect(!manager.isRunning) #expect(manager.bunServer == nil) @@ -51,7 +51,7 @@ final class ServerManagerTests { func startingAlreadyRunningServer() async throws { // In test environment, we can't actually start the server // So we'll test the logic of preventing duplicate starts - + // First attempt to start await manager.start() try await Task.sleep(for: .milliseconds(100)) @@ -64,7 +64,7 @@ final class ServerManagerTests { // Should still have the same state (either nil or same instance) #expect(manager.bunServer === firstServer) - + // Error should be consistent if let error1 = firstError as? BunServerError, let error2 = manager.lastError as? BunServerError { @@ -77,7 +77,6 @@ final class ServerManagerTests { @Test("Port configuration") func portConfiguration() async throws { - // Store original port let originalPort = manager.port @@ -99,7 +98,6 @@ final class ServerManagerTests { DashboardAccessMode.network ]) func bindAddressConfiguration(mode: DashboardAccessMode) async throws { - // Store original mode let originalMode = UserDefaults.standard.string(forKey: "dashboardAccessMode") ?? "" @@ -174,11 +172,11 @@ final class ServerManagerTests { // Verify port configuration is maintained #expect(manager.port == testPort) - + // In test environment without binary, both instances should be nil #expect(manager.bunServer == nil) #expect(serverBeforeRestart == nil) - + // Error should be consistent (binary not found) if let error = manager.lastError as? BunServerError { #expect(error == .binaryNotFound) @@ -228,7 +226,7 @@ final class ServerManagerTests { // In test environment, server won't actually start #expect(!manager.isRunning) #expect(manager.bunServer == nil) - + // Verify error is set appropriately if let error = manager.lastError as? BunServerError { #expect(error == .binaryNotFound) diff --git a/mac/VibeTunnelTests/SessionIdHandlingTests.swift b/mac/VibeTunnelTests/SessionIdHandlingTests.swift index bf74f7c7..e582c002 100644 --- a/mac/VibeTunnelTests/SessionIdHandlingTests.swift +++ b/mac/VibeTunnelTests/SessionIdHandlingTests.swift @@ -128,9 +128,13 @@ struct SessionIdHandlingTests { let started_at: String let stdin: String let streamOut: String - + enum CodingKeys: String, CodingKey { - case cmdline, cwd, name, pid, status + case cmdline + case cwd + case name + case pid + case status case started_at = "started_at" case stdin case streamOut = "stream-out" diff --git a/mac/VibeTunnelTests/SessionMonitorTests.swift b/mac/VibeTunnelTests/SessionMonitorTests.swift index 01bad489..a63a3b23 100644 --- a/mac/VibeTunnelTests/SessionMonitorTests.swift +++ b/mac/VibeTunnelTests/SessionMonitorTests.swift @@ -8,70 +8,70 @@ import Testing @MainActor final class SessionMonitorTests { let monitor = SessionMonitor.shared - + init() async { // Ensure clean state before each test await monitor.refresh() } - + // MARK: - Basic Functionality Tests - + @Test("Session count calculation") func sessionCount() { // When no sessions exist #expect(monitor.sessionCount == 0) - + // Note: Full integration tests would require a running server // These tests verify the basic functionality of SessionMonitor } - + // MARK: - Cache Behavior Tests - + @Test("Cache behavior", .tags(.performance)) func cacheBehavior() async { // First call should fetch _ = await monitor.getSessions() - + // Immediate second call should use cache (no network request) let cachedSessions = await monitor.getSessions() - + // Verify we got a result (even if empty due to no server) // cachedSessions is non-optional, so just verify it's a dictionary #expect(cachedSessions.isEmpty || !cachedSessions.isEmpty) } - + @Test("Force refresh clears cache") func forceRefresh() async { // Get initial sessions let initialSessions = await monitor.getSessions() - + // Force refresh await monitor.refresh() - + // Next call should fetch fresh data let refreshedSessions = await monitor.getSessions() - + // Both should be dictionaries (possibly empty) #expect(type(of: initialSessions) == type(of: refreshedSessions)) } - + // MARK: - Error Handling Tests - + @Test("Error handling", .tags(.reliability)) func errorHandling() async { // When server is not running, should handle gracefully _ = await monitor.getSessions() - + // Should have empty sessions, not crash #expect(monitor.sessions.isEmpty || !monitor.sessions.isEmpty) - + // Last error might be nil (if treating connection errors as expected) // or might contain error info #expect(monitor.lastError == nil || monitor.lastError != nil) } - + // MARK: - Concurrent Access Tests - + @Test("Concurrent session access", .tags(.concurrency)) func concurrentAccess() async { await withTaskGroup(of: [String: ServerSessionInfo].self) { group in @@ -81,12 +81,12 @@ final class SessionMonitorTests { await monitor.getSessions() } } - + var results: [[String: ServerSessionInfo]] = [] for await result in group { results.append(result) } - + // All concurrent calls should return consistent results if let first = results.first { for result in results { @@ -95,57 +95,57 @@ final class SessionMonitorTests { } } } - + // MARK: - Session Update Tests - + @Test("Session updates are reflected") func sessionUpdates() async { // Get initial state _ = monitor.sessionCount - + // Refresh to get latest await monitor.refresh() - + // Count should be consistent with sessions dictionary #expect(monitor.sessionCount == monitor.sessions.count) #expect(monitor.sessionCount >= 0) } - + // MARK: - Integration Tests - + @Test("Session monitor integration", .tags(.integration)) func integration() async { // Test the full flow await monitor.refresh() let sessions = await monitor.getSessions() - + // Verify session structure if we have any for (sessionId, _) in sessions { // Session ID should be valid #expect(!sessionId.isEmpty) - + // Note: ServerSessionInfo structure details would be validated here // if we had access to the actual session info fields } } - + // MARK: - Performance Tests - + @Test("Cache performance", .tags(.performance)) func cachePerformance() async throws { // Warm up cache _ = await monitor.getSessions() - + // Measure cached access time let start = Date() - + for _ in 0..<100 { _ = await monitor.getSessions() } - + let elapsed = Date().timeIntervalSince(start) - + // Cached access should be very fast #expect(elapsed < 0.1, "Cached access took too long: \(elapsed)s for 100 calls") } -} \ No newline at end of file +} diff --git a/mac/VibeTunnelTests/TerminalLaunchTests.swift b/mac/VibeTunnelTests/TerminalLaunchTests.swift index b5b30f44..227e754a 100644 --- a/mac/VibeTunnelTests/TerminalLaunchTests.swift +++ b/mac/VibeTunnelTests/TerminalLaunchTests.swift @@ -1,6 +1,6 @@ +import AppKit import Foundation import Testing -import AppKit @testable import VibeTunnel // MARK: - Terminal Launch Tests @@ -8,7 +8,7 @@ import AppKit @Suite("Terminal Launch Tests") struct TerminalLaunchTests { // MARK: - URL Generation Tests - + @Test("Terminal URL generation", arguments: [ (Terminal.iTerm2, "echo 'Hello World'", "iterm2://run?command=echo%20\'Hello%20World\'"), (Terminal.iTerm2, "cd /tmp && ls", "iterm2://run?command=cd%20/tmp%20%26%26%20ls"), @@ -24,33 +24,33 @@ struct TerminalLaunchTests { #expect(expectedURL == nil) } } - + // MARK: - Command Arguments Tests - + @Test("Command argument generation for terminals") func commandArgumentGeneration() { let command = "echo 'Hello World'" - + // Test Alacritty arguments let alacrittyArgs = Terminal.alacritty.commandArguments(for: command) #expect(alacrittyArgs == ["-e", "/bin/bash", "-c", command]) - + // Test WezTerm arguments let weztermArgs = Terminal.wezterm.commandArguments(for: command) #expect(weztermArgs == ["start", "--", "/bin/bash", "-c", command]) - + // Test Terminal.app (limited support) let terminalArgs = Terminal.terminal.commandArguments(for: command) #expect(terminalArgs == []) } - + // MARK: - Working Directory Tests - + @Test("Working directory support") func workingDirectorySupport() { let workDir = "/Users/test/projects" let command = "ls -la" - + // Alacritty with working directory let alacrittyArgs = Terminal.alacritty.commandArguments( for: command, @@ -60,7 +60,7 @@ struct TerminalLaunchTests { "--working-directory", workDir, "-e", "/bin/bash", "-c", command ]) - + // WezTerm with working directory let weztermArgs = Terminal.wezterm.commandArguments( for: command, @@ -70,7 +70,7 @@ struct TerminalLaunchTests { "start", "--cwd", workDir, "--", "/bin/bash", "-c", command ]) - + // iTerm2 URL with working directory if let url = Terminal.iTerm2.commandURL(for: command, workingDirectory: workDir) { #expect(url.absoluteString.contains("cd=")) @@ -79,62 +79,62 @@ struct TerminalLaunchTests { ) } } - + // MARK: - Complex Command Tests - + @Test("Complex command encoding") func complexCommandEncoding() { let complexCommand = "git log --oneline -10 && echo 'Done!'" - + // Test iTerm2 URL encoding if let url = Terminal.iTerm2.commandURL(for: complexCommand) { // URLComponents encodes differently, so just check the URL contains the command #expect(url.absoluteString.contains("command=")) #expect(url.absoluteString.contains("git")) } - + // Test argument generation doesn't break the command let alacrittyArgs = Terminal.alacritty.commandArguments(for: complexCommand) #expect(alacrittyArgs.last == complexCommand) } - + // MARK: - Terminal Detection Tests - + @Test("Terminal detection") func terminalDetection() { // At least Terminal.app should be available on macOS #expect(Terminal.installed.contains(.terminal)) - + // Check that installed terminals have valid paths for terminal in Terminal.installed { // Check if terminal is installed #expect(NSWorkspace.shared.urlForApplication(withBundleIdentifier: terminal.bundleIdentifier) != nil) } } - + // MARK: - Environment Variable Tests - + @Test("Launching with environment variables") @MainActor func environmentVariables() { _ = ["MY_VAR": "test_value", "PATH": "/custom/path:/usr/bin"] _ = "echo $MY_VAR" - + // Test that environment variables can be passed _ = TerminalLauncher.shared - + // This would need to be implemented in TerminalLauncher // Just testing the concept here #expect(Bool(true)) // No-throw test } - + // MARK: - Script File Tests - + @Test("Script file execution") func scriptFileExecution() throws { let tempDir = FileManager.default.temporaryDirectory let scriptPath = tempDir.appendingPathComponent("test_script.sh") - + // Create a test script let scriptContent = """ #!/bin/bash @@ -142,16 +142,16 @@ struct TerminalLaunchTests { pwd """ try scriptContent.write(to: scriptPath, atomically: true, encoding: .utf8) - + // Make executable try FileManager.default.setAttributes( [.posixPermissions: 0o755], ofItemAtPath: scriptPath.path ) - + // Test launching the script #expect(FileManager.default.fileExists(atPath: scriptPath.path)) - + // Cleanup try? FileManager.default.removeItem(at: scriptPath) } @@ -171,7 +171,7 @@ extension Terminal { } args += ["-e", "/bin/bash", "-c", command] return args - + case .wezterm: var args = ["start"] if let workDir = workingDirectory { @@ -179,12 +179,12 @@ extension Terminal { } args += ["--", "/bin/bash", "-c", command] return args - + default: return [] } } - + /// Generate URL for terminals that support URL schemes func commandURL(for command: String, workingDirectory: String? = nil) -> URL? { switch self { @@ -198,9 +198,9 @@ extension Terminal { } components?.queryItems = queryItems return components?.url - + default: return nil } } -} \ No newline at end of file +}