feat: render interactive markdown task checkboxes
This commit is contained in:
@@ -322,3 +322,68 @@ func markdownListReturnContinuesExitsAndUndoesAtArbitraryDepths() throws {
|
||||
let id = try #require(defaults.string(forKey: "selectedNote").flatMap(UUID.init(uuidString:)))
|
||||
#expect(restored.notes.first { $0.id == id }?.contents.string == "7. saved\n8. ")
|
||||
}
|
||||
|
||||
@Test @MainActor
|
||||
func taskCheckboxesToggleMarkdownWithUndoPersistenceAndListContinuation() throws {
|
||||
_ = NSApplication.shared
|
||||
let suite = "NotesTasks.\(UUID().uuidString)"
|
||||
let defaults = try #require(UserDefaults(suiteName: suite))
|
||||
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(suite)
|
||||
defer {
|
||||
defaults.removePersistentDomain(forName: suite)
|
||||
try? FileManager.default.removeItem(at: directory)
|
||||
}
|
||||
let controller = NotesController(defaults: defaults, directory: directory)
|
||||
let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 750, height: 390),
|
||||
styleMask: .borderless, backing: .buffered, defer: false)
|
||||
window.contentViewController = controller
|
||||
defer { _ = controller.close(); window.orderOut(nil) }
|
||||
func descendants(_ view: NSView) -> [NSView] { [view] + view.subviews.flatMap(descendants) }
|
||||
let editor = try #require(descendants(controller.view).compactMap { $0 as? NotesTextView }.first)
|
||||
window.makeFirstResponder(editor)
|
||||
let before = "- [ ] buy 🦊\n - [X] nested\n```md\n- [ ] literal\n```\nprose - [ ] not a task"
|
||||
editor.insertText(before, replacementRange: editor.selectedRange())
|
||||
editor.breakUndoCoalescing()
|
||||
editor.undoManager?.removeAllActions()
|
||||
let boxes = editor.subviews.compactMap { $0 as? NSButton }
|
||||
#expect(boxes.map(\.state) == [.off, .on])
|
||||
#expect(boxes.first?.cell?.accessibilityRole() == .checkBox)
|
||||
#expect(boxes.first?.accessibilityLabel() == "buy 🦊")
|
||||
let selection = editor.selectedRange()
|
||||
let first = try #require(boxes.first)
|
||||
first.performClick(nil)
|
||||
let checked = before.replacingOccurrences(of: "- [ ] buy", with: "- [x] buy")
|
||||
#expect(editor.string == checked)
|
||||
#expect(first.state == .on)
|
||||
#expect(editor.selectedRange() == selection)
|
||||
let id = try #require(defaults.string(forKey: "selectedNote").flatMap(UUID.init(uuidString:)))
|
||||
let saved = try #require(NotesStore(directory: directory).notes.first { $0.id == id })
|
||||
#expect(saved.contents.string == checked)
|
||||
#expect(saved.contents.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? NSColor != .clear)
|
||||
editor.undoManager?.undo()
|
||||
#expect(editor.string == before)
|
||||
#expect(first.state == .off)
|
||||
editor.undoManager?.redo()
|
||||
#expect(editor.string == checked)
|
||||
#expect(first.state == .on)
|
||||
editor.setSelectedRange(NSRange(location: 0, length: editor.string.utf16.count))
|
||||
let board = NSPasteboard.withUniqueName()
|
||||
defer { board.releaseGlobally() }
|
||||
#expect(editor.writeSelection(to: board, types: editor.writablePasteboardTypes))
|
||||
#expect(board.string(forType: .string) == checked)
|
||||
let reopened = NotesController(defaults: defaults, directory: directory)
|
||||
defer { _ = reopened.close() }
|
||||
let restoredEditor = try #require(descendants(reopened.view).compactMap { $0 as? NotesTextView }.first)
|
||||
#expect(restoredEditor.string == checked)
|
||||
#expect(restoredEditor.subviews.compactMap { $0 as? NSButton }.map(\.state) == [.on, .on])
|
||||
editor.insertText("- [x] finished", replacementRange: NSRange(location: 0, length: editor.string.utf16.count))
|
||||
let enter = try #require(NSEvent.keyEvent(with: .keyDown, location: .zero, modifierFlags: [],
|
||||
timestamp: 1, windowNumber: window.windowNumber, context: nil, characters: "\r",
|
||||
charactersIgnoringModifiers: "\r", isARepeat: false, keyCode: 36))
|
||||
editor.keyDown(with: enter)
|
||||
#expect(editor.string == "- [x] finished\n- [ ] ")
|
||||
#expect(editor.subviews.compactMap { $0 as? NSButton }.map(\.state) == [.on, .off])
|
||||
editor.keyDown(with: enter)
|
||||
#expect(editor.string == "- [x] finished\n")
|
||||
#expect(editor.subviews.compactMap { $0 as? NSButton }.map(\.state) == [.on])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user