import XCTest import SaplingCore @testable import SaplingEditor final class EditorStateTests: XCTestCase { func testActiveLineFollowsSelection() { let source = "# Heading\nRendered **line**\nRaw source line" let document = EditorDocument( url: URL(fileURLWithPath: "/tmp/EditorStateTests.md"), title: "EditorStateTests", source: source ) var state = EditorState(document: document) let secondLineLocation = (source as NSString).range(of: "Rendered").location state.updateSelection(EditorSelection(location: secondLineLocation, length: 0)) XCTAssertEqual(state.activeLineIndex, 1) XCTAssertEqual(state.lines[0].mode, .rendered) XCTAssertEqual(state.lines[1].mode, .source) XCTAssertEqual(state.lines[2].mode, .rendered) } func testUpdatingSourceTracksUnsavedChanges() { let document = EditorDocument( url: URL(fileURLWithPath: "/tmp/EditorStateTests.md"), title: "EditorStateTests", source: "Initial" ) var state = EditorState(document: document) state.updateSource("Initial\nChanged") XCTAssertTrue(state.hasUnsavedChanges) XCTAssertEqual(state.lines.count, 2) state.markSaved() XCTAssertFalse(state.hasUnsavedChanges) } func testActiveColumnFollowsSelectionWithinLine() { let source = "First line\nSecond line" let document = EditorDocument( url: URL(fileURLWithPath: "/tmp/EditorStateTests.md"), title: "EditorStateTests", source: source ) var state = EditorState(document: document) let secondLineLocation = (source as NSString).range(of: "Second").location state.updateSelection(EditorSelection(location: secondLineLocation + 3, length: 0)) XCTAssertEqual(state.activeLineIndex, 1) XCTAssertEqual(state.activeColumnNumber, 4) } @MainActor func testViewModelSavesDocumentToDisk() throws { let directory = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString, isDirectory: true) try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) let url = directory.appendingPathComponent("Note.md") try "# Note\n".write(to: url, atomically: true, encoding: .utf8) let document = try HybridMarkdownEditorViewModel.loadDocument(at: url) let viewModel = HybridMarkdownEditorViewModel(document: document) viewModel.updateSource("# Note\n\nUpdated") try viewModel.save() let saved = try String(contentsOf: url, encoding: .utf8) XCTAssertEqual(saved, "# Note\n\nUpdated") XCTAssertFalse(viewModel.hasUnsavedChanges) } }