Files
bookstax/bookstaxTests/OnboardingViewModelTests.swift
T
2026-04-20 09:41:18 +02:00

227 lines
6.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Testing
@testable import bookstax
// MARK: - URL Validation
@Suite("OnboardingViewModel URL Validation")
struct OnboardingViewModelURLTests {
// MARK: Empty input
@Test("Empty URL sets error and returns false")
func emptyURL() {
let vm = OnboardingViewModel()
vm.serverURLInput = ""
#expect(vm.validateServerURL() == false)
#expect(vm.serverURLError != nil)
}
@Test("Whitespace-only URL sets error and returns false")
func whitespaceURL() {
let vm = OnboardingViewModel()
vm.serverURLInput = " "
#expect(vm.validateServerURL() == false)
#expect(vm.serverURLError != nil)
}
// MARK: Auto-prefix https://
@Test("URL without scheme gets https:// prepended")
func autoprefixHTTPS() {
let vm = OnboardingViewModel()
vm.serverURLInput = "wiki.example.com"
let result = vm.validateServerURL()
#expect(result == true)
#expect(vm.serverURLInput.hasPrefix("https://"))
}
@Test("URL already starting with https:// is left unchanged")
func httpsAlreadyPresent() {
let vm = OnboardingViewModel()
vm.serverURLInput = "https://wiki.example.com"
let result = vm.validateServerURL()
#expect(result == true)
#expect(vm.serverURLInput == "https://wiki.example.com")
}
@Test("URL starting with http:// is left as-is (not double-prefixed)")
func httpNotDoublePrefixed() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://wiki.example.com"
let result = vm.validateServerURL()
#expect(result == true)
#expect(vm.serverURLInput == "http://wiki.example.com")
}
// MARK: Trailing slash removal
@Test("Trailing slash is stripped from URL")
func trailingSlash() {
let vm = OnboardingViewModel()
vm.serverURLInput = "https://wiki.example.com/"
_ = vm.validateServerURL()
#expect(vm.serverURLInput == "https://wiki.example.com")
}
@Test("Multiple trailing slashes only last slash stripped then accepted")
func multipleSlashesInPath() {
let vm = OnboardingViewModel()
vm.serverURLInput = "https://wiki.example.com/path/"
_ = vm.validateServerURL()
#expect(vm.serverURLInput == "https://wiki.example.com/path")
}
// MARK: Successful validation
@Test("Valid URL clears any previous error")
func validURLClearsError() {
let vm = OnboardingViewModel()
vm.serverURLError = "Previous error"
vm.serverURLInput = "https://books.mycompany.com"
#expect(vm.validateServerURL() == true)
#expect(vm.serverURLError == nil)
}
}
// MARK: - isHTTP Flag
@Suite("OnboardingViewModel isHTTP")
struct OnboardingViewModelHTTPTests {
@Test("http:// URL sets isHTTP = true")
func httpURL() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://wiki.local"
#expect(vm.isHTTP == true)
}
@Test("https:// URL sets isHTTP = false")
func httpsURL() {
let vm = OnboardingViewModel()
vm.serverURLInput = "https://wiki.local"
#expect(vm.isHTTP == false)
}
@Test("Empty URL is not HTTP")
func emptyNotHTTP() {
let vm = OnboardingViewModel()
vm.serverURLInput = ""
#expect(vm.isHTTP == false)
}
}
// MARK: - isRemoteServer Detection
@Suite("OnboardingViewModel isRemoteServer")
struct OnboardingViewModelRemoteTests {
// MARK: Local / private addresses
@Test("localhost is not remote")
func localhost() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://localhost"
#expect(vm.isRemoteServer == false)
}
@Test("127.0.0.1 is not remote")
func loopback() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://127.0.0.1"
#expect(vm.isRemoteServer == false)
}
@Test("IPv6 loopback ::1 is not remote")
func ipv6Loopback() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://[::1]"
#expect(vm.isRemoteServer == false)
}
@Test(".local mDNS host is not remote")
func mdnsLocal() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://bookstack.local"
#expect(vm.isRemoteServer == false)
}
@Test("Plain hostname without dots is not remote")
func plainHostname() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://mywiki"
#expect(vm.isRemoteServer == false)
}
@Test("10.x.x.x private range is not remote")
func privateClass_A() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://10.0.1.50"
#expect(vm.isRemoteServer == false)
}
@Test("192.168.x.x private range is not remote")
func privateClass_C() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://192.168.1.100"
#expect(vm.isRemoteServer == false)
}
@Test("172.16.x.x private range is not remote")
func privateClass_B_low() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://172.16.0.1"
#expect(vm.isRemoteServer == false)
}
@Test("172.31.x.x private range is not remote")
func privateClass_B_high() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://172.31.255.255"
#expect(vm.isRemoteServer == false)
}
@Test("172.15.x.x is outside private range and is remote")
func justBelowPrivateClass_B() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://172.15.0.1"
#expect(vm.isRemoteServer == true)
}
@Test("172.32.x.x is outside private range and is remote")
func justAbovePrivateClass_B() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://172.32.0.1"
#expect(vm.isRemoteServer == true)
}
// MARK: Remote addresses
@Test("Public IP 8.8.8.8 is remote")
func publicIP() {
let vm = OnboardingViewModel()
vm.serverURLInput = "http://8.8.8.8"
#expect(vm.isRemoteServer == true)
}
@Test("Public domain with subdomain is remote")
func publicDomain() {
let vm = OnboardingViewModel()
vm.serverURLInput = "https://wiki.mycompany.com"
#expect(vm.isRemoteServer == true)
}
@Test("Top-level domain name is remote")
func topLevelDomain() {
let vm = OnboardingViewModel()
vm.serverURLInput = "https://bookstack.io"
#expect(vm.isRemoteServer == true)
}
@Test("Empty URL is not remote")
func emptyIsNotRemote() {
let vm = OnboardingViewModel()
vm.serverURLInput = ""
#expect(vm.isRemoteServer == false)
}
}