vibetunnel/ios/VibeTunnelTests/Models/ServerConfigTests.swift

227 lines
6.2 KiB
Swift

import Foundation
import Testing
@testable import VibeTunnel
@Suite("ServerConfig Tests", .tags(.models))
struct ServerConfigTests {
@Test("Creates valid HTTP URL")
func hTTPURLCreation() {
// Arrange
let config = ServerConfig(
host: "localhost",
port: 8_888,
name: nil,
)
// Act
let url = config.baseURL
// Assert
#expect(url.absoluteString == "http://localhost:8888")
#expect(url.scheme == "http")
#expect(url.host == "localhost")
#expect(url.port == 8_888)
}
@Test("Creates valid URL with different ports")
func urlWithDifferentPorts() {
// Arrange
let config = ServerConfig(
host: "example.com",
port: 443,
name: "user",
)
// Act
let url = config.baseURL
// Assert - baseURL always uses http://
#expect(url.absoluteString == "http://example.com:443")
#expect(url.scheme == "http")
#expect(url.host == "example.com")
#expect(url.port == 443)
}
@Test("Display name uses custom name if provided")
func displayNameWithCustomName() {
let config = ServerConfig(
host: "localhost",
port: 8888,
name: "My Server",
)
#expect(config.displayName == "My Server")
}
@Test("Handles standard ports correctly")
func standardPorts() {
// HTTP standard port (80)
let httpConfig = ServerConfig(
host: "example.com",
port: 80,
)
#expect(httpConfig.baseURL.absoluteString == "http://example.com:80")
// Another port
let httpsConfig = ServerConfig(
host: "example.com",
port: 443,
)
#expect(httpsConfig.baseURL.absoluteString == "http://example.com:443")
}
@Test("Encodes and decodes correctly")
func codable() throws {
// Arrange
let originalConfig = ServerConfig(
host: "test.local",
port: 9_999,
name: "testuser",
)
// Act
let encoder = JSONEncoder()
let data = try encoder.encode(originalConfig)
let decoder = JSONDecoder()
let decodedConfig = try decoder.decode(ServerConfig.self, from: data)
// Assert
#expect(decodedConfig.host == originalConfig.host)
#expect(decodedConfig.port == originalConfig.port)
#expect(decodedConfig.name == originalConfig.name)
}
@Test("Optional credentials encoding")
func optionalCredentials() throws {
// Config without credentials
let configNoAuth = ServerConfig(
host: "public.server",
port: 8_080,
)
let data = try JSONEncoder().encode(configNoAuth)
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
#expect(json?["name"] == nil)
}
@Test("Equality comparison")
func equality() {
let config1 = ServerConfig(
host: "localhost",
port: 8_888,
)
let config2 = ServerConfig(
host: "localhost",
port: 8_888,
)
let config3 = ServerConfig(
host: "localhost",
port: 9_999, // Different port
)
#expect(config1 == config2)
#expect(config1 != config3)
}
@Test("Handles IPv6 addresses")
func iPv6Address() {
let config = ServerConfig(
host: "::1",
port: 8_888,
)
let url = config.baseURL
// IPv6 addresses need brackets in URLs
#expect(url.absoluteString == "http://[::1]:8888" || url.absoluteString == "http://::1:8888")
#expect(url.port == 8888)
}
@Test("Handles domain with subdomain")
func subdomainHandling() {
let config = ServerConfig(
host: "api.staging.example.com",
port: 443,
)
let url = config.baseURL
#expect(url.absoluteString == "http://api.staging.example.com:443")
#expect(url.host == "api.staging.example.com")
}
@Test("Display name formatting")
func testDisplayName() {
// Without custom name
let simpleConfig = ServerConfig(
host: "localhost",
port: 8_888,
)
#expect(simpleConfig.displayName == "localhost:8888")
// With custom name
let namedConfig = ServerConfig(
host: "secure.example.com",
port: 443,
name: "Production Server"
)
#expect(namedConfig.displayName == "Production Server")
}
@Test("JSON representation matches expected format")
func jSONFormat() throws {
// Arrange
let config = ServerConfig(
host: "test.server",
port: 3_000,
name: "user",
)
// Act
let encoder = JSONEncoder()
encoder.outputFormatting = .sortedKeys
let data = try encoder.encode(config)
let jsonString = String(data: data, encoding: .utf8)!
// Assert
#expect(jsonString.contains("\"host\":\"test.server\""))
#expect(jsonString.contains("\"port\":3000"))
#expect(jsonString.contains("\"name\":\"user\""))
}
}
// MARK: - Integration Tests
@Suite("ServerConfig Integration Tests", .tags(.models, .integration))
struct ServerConfigIntegrationTests {
@Test("Round-trip through UserDefaults")
func userDefaultsPersistence() throws {
// Arrange
let config = TestFixtures.sslServerConfig
let key = "test_server_config"
// Clear any existing value
UserDefaults.standard.removeObject(forKey: key)
// Act - Save
let encoder = JSONEncoder()
let data = try encoder.encode(config)
UserDefaults.standard.set(data, forKey: key)
// Act - Load
guard let loadedData = UserDefaults.standard.data(forKey: key) else {
Issue.record("Failed to load data from UserDefaults")
return
}
let decoder = JSONDecoder()
let loadedConfig = try decoder.decode(ServerConfig.self, from: loadedData)
// Assert
#expect(loadedConfig == config)
// Cleanup
UserDefaults.standard.removeObject(forKey: key)
}
}