import XCTest @testable import MultiSimAdmin final class InstanceRepositoryTests: XCTestCase { private var location: URL! override func setUp() { super.setUp() location = FileManager.default.temporaryDirectory .appendingPathComponent("multi-simadmin-\(UUID().uuidString).json") } override func tearDown() { try? FileManager.default.removeItem(at: location) super.tearDown() } func testCreateListUpdateAndDeleteInstance() async throws { let repository = FileInstanceRepository(location: location) let input = InstanceInput( name: "Lab Alpha", origin: URL(string: "http://192.168.3.55:3000/")!, tags: ["primary", "lab"], password: "secret" ) let created = try await repository.create(input) XCTAssertEqual(created.name, "Lab Alpha") XCTAssertEqual(created.endpoint.displayAddress, "http://192.168.3.55:3000") XCTAssertEqual(created.tags, ["primary", "lab"]) XCTAssertEqual(created.configRevision, 1) XCTAssertTrue(created.credentialConfigured) let patch = InstancePatch(name: "Alpha", tags: ["lab"]) let updated = try await repository.update(created.id, expectedRevision: 1, patch) XCTAssertEqual(updated.name, "Alpha") XCTAssertEqual(updated.tags, ["lab"]) XCTAssertEqual(updated.configRevision, 2) XCTAssertTrue(updated.credentialConfigured) try await repository.delete(updated.id, expectedRevision: 2) let afterDelete = try await repository.list(InstanceQuery()) XCTAssertTrue(afterDelete.isEmpty) } func testRejectsInvalidOriginDuplicateOriginAndStaleRevision() async throws { let repository = FileInstanceRepository(location: location) let origin = URL(string: "http://192.168.1.20:3000")! let input = InstanceInput(name: "One", origin: origin, tags: [], password: nil) let first = try await repository.create(input) do { let nested = InstanceInput( name: "Nested", origin: URL(string: "http://192.168.1.20:3000/admin")!, tags: [], password: nil ) _ = try await repository.create(nested) XCTFail("Expected nested path rejection") } catch let error as RepositoryError { XCTAssertEqual(error, .invalidOrigin) } do { _ = try await repository.create(input) XCTFail("Expected duplicate-origin failure") } catch let error as RepositoryError { XCTAssertEqual(error, .duplicateOrigin) } do { _ = try await repository.update(first.id, expectedRevision: 99, InstancePatch(name: "New")) XCTFail("Expected stale-revision failure") } catch let error as RepositoryError { XCTAssertEqual(error, .revisionConflict) } } func testListFiltersBySearchAndTag() async throws { let repository = FileInstanceRepository(location: location) _ = try await repository.create(InstanceInput( name: "Lab Alpha", origin: URL(string: "http://192.168.1.10:3000")!, tags: ["production"], password: nil )) _ = try await repository.create(InstanceInput( name: "Home Beta", origin: URL(string: "http://192.168.1.20:3000")!, tags: ["lab"], password: nil )) let search = try await repository.list(InstanceQuery(search: "alpha")) XCTAssertEqual(search.map(\.name), ["Lab Alpha"]) let tagged = try await repository.list(InstanceQuery(tags: ["lab"])) XCTAssertEqual(tagged.map(\.name), ["Home Beta"]) let production = try await repository.list(InstanceQuery(tags: ["production"])) XCTAssertEqual(production.map(\.name), ["Lab Alpha"]) let sorted = try await repository.list(InstanceQuery()) XCTAssertEqual(sorted.map(\.name), ["Home Beta", "Lab Alpha"]) } }