106 lines
4.8 KiB
Swift
106 lines
4.8 KiB
Swift
// SPDX-FileCopyrightText: 2026 Kaede Akino
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import TermindApplication
|
|
import TermindDomain
|
|
import TermindPresentation
|
|
import Testing
|
|
|
|
import struct TermindDomain.Host
|
|
|
|
@Suite @MainActor
|
|
struct HostEditorBindingsTests {
|
|
@Test func creatingRelatedRecordsLeavesExistingSelectionsAndDraftsUntouched() {
|
|
let identity = Identity(name: "Shared", username: "deploy")
|
|
var host = Host(name: "Server", host: "server.invalid")
|
|
host.identityID = identity.id
|
|
host.groupID = UUID()
|
|
var custom = HostCustomIdentityDraft()
|
|
custom.sshUsername = "unsaved-user"
|
|
let original = host
|
|
var creations: [HostEditorCreation] = []
|
|
let fields = HostEditorBindings(
|
|
host: Binding(get: { host }, set: { host = $0 }),
|
|
customIdentity: Binding(get: { custom }, set: { custom = $0 }),
|
|
library: HostLibraryModel(identities: [identity]), create: { creations.append($0) })
|
|
|
|
fields.identityChoice.wrappedValue = .new
|
|
fields.telnetIdentityChoice.wrappedValue = .new
|
|
fields.proxyIdentityChoice.wrappedValue = .new
|
|
fields.telnetProxyIdentityChoice.wrappedValue = .new
|
|
fields.groupChoice.wrappedValue = .new
|
|
|
|
#expect(host == original)
|
|
#expect(custom.sshUsername == "unsaved-user")
|
|
#expect(fields.identityChoice.wrappedValue == .existing(identity.id))
|
|
#expect(creations == [.identity, .telnetIdentity, .proxyIdentity, .telnetProxyIdentity, .group])
|
|
}
|
|
|
|
@Test func telnetCustomAndNoneRemainDistinctWithoutASavedCustomIdentity() {
|
|
let identity = Identity(name: "Shared", username: "deploy")
|
|
var host = Host(name: "Server", host: "server.invalid", telnetEnabled: true)
|
|
var custom = HostCustomIdentityDraft()
|
|
custom.telnetUsername = "unsaved-user"
|
|
let fields = HostEditorBindings(
|
|
host: Binding(get: { host }, set: { host = $0 }),
|
|
customIdentity: Binding(get: { custom }, set: { custom = $0 }),
|
|
library: HostLibraryModel(identities: [identity]), create: { _ in })
|
|
|
|
fields.identityChoice.wrappedValue = .existing(identity.id)
|
|
fields.telnetIdentityChoice.wrappedValue = .custom
|
|
#expect(host.telnetIdentityID == nil)
|
|
#expect(fields.telnetIdentityChoice.wrappedValue == .custom)
|
|
fields.telnetIdentityChoice.wrappedValue = .existing(identity.id)
|
|
#expect(host.telnetIdentityID == identity.id)
|
|
fields.telnetIdentityChoice.wrappedValue = .unset
|
|
#expect(host.telnetIdentityID == nil)
|
|
#expect(fields.telnetIdentityChoice.wrappedValue == .unset)
|
|
#expect(custom.telnetUsername == "unsaved-user")
|
|
#expect(host.identityID == identity.id)
|
|
}
|
|
|
|
/// Renaming or re-porting a host must not silently attach the known-host
|
|
/// entries of another login that still uses the original address.
|
|
@Test func savingAnEditedAddressLeavesSharedKnownHostsAlone() {
|
|
var host = Host(name: "Server", host: "old.example")
|
|
let shared = Host(name: "Other Login", host: "old.example")
|
|
let entry = KnownHostEntry(hostname: host.host, fingerprint: "SHA256:old")
|
|
let library = HostLibraryModel(hosts: [host, shared], knownHosts: [entry])
|
|
host.host = "new.example"
|
|
host.port = 2222
|
|
|
|
#expect(library.saveHost(host))
|
|
#expect(library.knownHosts == [entry])
|
|
#expect(library.knownHosts(for: host).isEmpty)
|
|
#expect(library.knownHosts(for: shared) == [entry])
|
|
}
|
|
|
|
@Test(arguments: [false, true])
|
|
func proxyEditsShareDefaultPortPolicyAndKeepProtocolsIndependent(_ telnet: Bool) {
|
|
var host = Host(name: "Server", host: "server.invalid", telnetEnabled: true)
|
|
var custom = HostCustomIdentityDraft()
|
|
let fields = HostEditorBindings(
|
|
host: Binding(get: { host }, set: { host = $0 }),
|
|
customIdentity: Binding(get: { custom }, set: { custom = $0 }),
|
|
library: HostLibraryModel(), create: { _ in })
|
|
let kind = telnet ? fields.telnetProxyKind : fields.proxyKind
|
|
let port = telnet ? fields.telnetProxyInt(\.port) : fields.proxyInt(\.port)
|
|
let hostname = telnet ? fields.telnetProxyString(\.hostname) : fields.proxyString(\.hostname)
|
|
|
|
kind.wrappedValue = .http
|
|
hostname.wrappedValue = "proxy.invalid"
|
|
kind.wrappedValue = .socks5
|
|
#expect(port.wrappedValue == HostProxy.ProtocolKind.socks5.defaultPort)
|
|
#expect(hostname.wrappedValue == "proxy.invalid")
|
|
port.wrappedValue = 9999
|
|
kind.wrappedValue = .http
|
|
#expect(port.wrappedValue == 9999)
|
|
#expect(telnet ? host.proxy == nil : host.telnetProxy == nil)
|
|
kind.wrappedValue = nil
|
|
hostname.wrappedValue = "must-not-recreate.invalid"
|
|
#expect(host.proxy == nil && host.telnetProxy == nil)
|
|
}
|
|
}
|