import XCTest @testable import RouterOSAssistant final class PortConflictTests: XCTestCase { func testBridgeMembershipProducesNoResolutionCommand() { // DhcpServerCommandBuilder already unconditionally detaches any bridge membership — // repeating it here would just be a harmless duplicate at best, so it's deliberately // excluded from this list. let conflict = PortConflict(interfaceName: "ether4", reasons: [.bridgeMember(bridgeName: "bridge")]) XCTAssertTrue(conflict.resolutionCommands().isEmpty) } func testExistingAddressIsRemovedByInterfaceMatch() { let conflict = PortConflict(interfaceName: "ether4", reasons: [.hasAddresses(["10.0.0.1/24"])]) let commands = conflict.resolutionCommands() XCTAssertEqual(commands.count, 1) XCTAssertEqual(commands[0].menuPath, "/ip address") XCTAssertEqual(commands[0].operation, .remove(matchField: "interface", matchValue: "ether4")) } func testDhcpClientAndPppoeClientAreBothRemoved() { let conflict = PortConflict(interfaceName: "ether1", reasons: [.dhcpClient, .pppoeClient]) let commands = conflict.resolutionCommands() XCTAssertEqual(commands.count, 2) XCTAssertEqual(commands[0].menuPath, "/ip dhcp-client") XCTAssertEqual(commands[0].operation, .remove(matchField: "interface", matchValue: "ether1")) XCTAssertEqual(commands[1].menuPath, "/interface pppoe-client") XCTAssertEqual(commands[1].operation, .remove(matchField: "interface", matchValue: "ether1")) } /// Regression test for the Experte-tab "Port freimachen?" flow (per explicit request): unlike /// the Setup Wizard, the Experte tab has no separate step that unconditionally detaches a /// bridge port on its own, so its resolution list must include that removal explicitly — /// `resolutionCommands()` alone (the wizard's version) deliberately leaves it out. func testResolutionCommandsIncludingBridgeDetachAddsBridgePortRemoval() { let conflict = PortConflict(interfaceName: "ether4", reasons: [.bridgeMember(bridgeName: "bridge")]) let commands = conflict.resolutionCommandsIncludingBridgeDetach() XCTAssertEqual(commands.count, 1) XCTAssertEqual(commands[0].menuPath, "/interface bridge port") XCTAssertEqual(commands[0].operation, .remove(matchField: "interface", matchValue: "ether4")) } func testResolutionCommandsIncludingBridgeDetachKeepsOtherReasonsToo() { let conflict = PortConflict(interfaceName: "ether4", reasons: [.bridgeMember(bridgeName: "bridge"), .dhcpClient]) let commands = conflict.resolutionCommandsIncludingBridgeDetach() XCTAssertEqual(commands.count, 2) XCTAssertEqual(commands[0].menuPath, "/interface bridge port") XCTAssertEqual(commands[1].menuPath, "/ip dhcp-client") } }