Files
RouterOS/RouterOSAssistantTests/RouterOSCommandBuilderTests.swift
T
KayandClaude Sonnet 5 e2b303963a M12: Geräte-Tab — LAN-Scanner mit Static-IP-Zuweisung
Neuer Tab: eine Tabelle pro physischem Ethernet/WLAN-Port mit den dort
gefundenen Geräten (Name, IP, MAC, Fest/Dynamisch/Kein-DHCP), gebaut aus
DHCP-Leases + ARP + Bridge-Host-Tabelle. Rechtsklick auf ein dynamisches
Gerät -> "Feste IP zuweisen" (RouterOS' "Make Static", per
/ip dhcp-server lease make-static), mit Bestätigungsdialog und
Session-Backup vor dem ersten Schreibvorgang (geteilter Mechanismus mit
dem Experte-Tab).

Vier reale Bugs live gefunden und gefixt (siehe HANDOFF.md Bug 14-17):

- "print terse" gibt das "dynamic"-Feld von /ip dhcp-server lease nie
  aus, in keinem Zustand -> Status kommt jetzt über RouterOS' find/get
  gegen die interne Eigenschaft, nicht aus gelesenen Feldern.
- fetchMenuItems' .id-Positionsüberlagerung ordnete für dieses Menü die
  falsche .id der falschen Zeile zu -> Erkennung und make-static-Ziel
  laufen jetzt über die MAC-Adresse statt .id.
- Ein SwiftUI-.confirmationDialog löschte sein eigenes Ziel-Objekt vor
  der Ausführung der bestätigten Aktion (Setter feuert bei jedem
  Knopfdruck, nicht nur Abbrechen) -> Dialog-Sichtbarkeit und
  Nutzlast entkoppelt, wie in BackupListView.
- Die eigene Verifikations-Abfrage (get [find ...] feld als ein
  kombinierter Befehl) war selbst eine nie verifizierte Annahme und
  lieferte falsche Negative -> ersetzt durch :foreach aus zwei einzeln
  bestätigten Bausteinen (find, get <id> feld).

RouterOSCommand bekommt einen neuen .action-Operationstyp für
RouterOS-"Menü-spezifische Befehle" jenseits von add/set/remove (aktuell
nur make-static). HANDOFF.md/CHATLOG.md mit allen vier Bugs, neuen
Milestones M11/M12 und offenen Punkten aktualisiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CTgRxJTzaQwaRkngbaE1GJ
2026-09-14 13:55:46 +02:00

91 lines
3.2 KiB
Swift

import XCTest
@testable import RouterOSAssistant
final class RouterOSCommandBuilderTests: XCTestCase {
func testWanDhcpClientCommand() {
let config = WanConfig(interfaceName: "ether1", mode: .dhcpClient)
let commands = config.buildCommands()
XCTAssertEqual(commands.count, 1)
XCTAssertEqual(commands[0].menuPath, "/ip dhcp-client")
XCTAssertEqual(commands[0].operation, .add)
XCTAssertEqual(commands[0].arguments["interface"], "ether1")
}
func testWanStaticIPCommandsIncludeRouteOnlyWhenGatewayGiven() {
var config = WanConfig(interfaceName: "ether1", mode: .staticIP)
config.staticAddress = "203.0.113.5/24"
XCTAssertEqual(config.buildCommands().count, 1)
config.staticGateway = "203.0.113.1"
let commands = config.buildCommands()
XCTAssertEqual(commands.count, 2)
XCTAssertEqual(commands[0].arguments["address"], "203.0.113.5/24")
XCTAssertEqual(commands[1].arguments["gateway"], "203.0.113.1")
}
func testWanPppoeCommand() {
var config = WanConfig(interfaceName: "ether1", mode: .pppoe)
config.pppoeUsername = "user@isp"
config.pppoePassword = "secret"
let commands = config.buildCommands()
XCTAssertEqual(commands.count, 1)
XCTAssertEqual(commands[0].menuPath, "/interface pppoe-client")
XCTAssertEqual(commands[0].arguments["user"], "user@isp")
XCTAssertEqual(commands[0].arguments["password"], "secret")
}
func testLanDhcpCommandsCoverAddressPoolServerAndNetwork() {
let config = LanDhcpConfig()
let commands = config.buildCommands()
XCTAssertEqual(commands.count, 4)
XCTAssertEqual(commands[0].menuPath, "/ip address")
XCTAssertEqual(commands[1].menuPath, "/ip pool")
XCTAssertEqual(commands[2].menuPath, "/ip dhcp-server")
XCTAssertEqual(commands[3].menuPath, "/ip dhcp-server network")
XCTAssertEqual(commands[3].arguments["gateway"], "192.168.88.1")
}
func testCliLineRendersSortedQuotedArgumentsForAdd() {
let command = RouterOSCommand.add(
menuPath: "/interface pppoe-client",
restPath: "interface/pppoe-client",
arguments: ["user": "user@isp", "password": "a secret"],
summary: "test"
)
XCTAssertEqual(command.cliLine, "/interface pppoe-client add password=\"a secret\" user=user@isp")
}
func testCliLineRendersFindLookupForSet() {
let command = RouterOSCommand.set(
menuPath: "/interface wireless",
restPath: "interface/wireless",
matchField: "name",
matchValue: "wlan1",
arguments: ["ssid": "Home"],
summary: "test"
)
XCTAssertEqual(command.cliLine, "/interface wireless set [find name=wlan1] ssid=Home")
}
func testCliLineRendersFindLookupForAction() {
let command = RouterOSCommand.action(
menuPath: "/ip dhcp-server lease",
restPath: "ip/dhcp-server/lease",
name: "make-static",
matchField: ".id",
matchValue: "*7",
summary: "test"
)
XCTAssertEqual(command.cliLine, "/ip dhcp-server lease make-static [find .id=*7]")
}
}