186 lines
7.5 KiB
Swift
186 lines
7.5 KiB
Swift
import AppKit
|
|
import XCTest
|
|
@testable import markdownViewr
|
|
|
|
final class FileMenuPrunerTests: XCTestCase {
|
|
func testRemovesOnlyRequestedFileMenuItems() {
|
|
let fileMenu = NSMenu(title: "File")
|
|
["New", "Open...", "Open Recent", "Close", "Save", "Duplicate", "Rename", "Save As...", "Revert To", "Page Setup...", "Print..."]
|
|
.forEach { fileMenu.addItem(withTitle: $0, action: nil, keyEquivalent: "") }
|
|
|
|
FileMenuPruner.removeEditingItems(from: fileMenu)
|
|
|
|
XCTAssertEqual(
|
|
fileMenu.items.map(\.title),
|
|
["Open...", "Open Recent", "Close", "Duplicate", "Rename", "Save As...", "Page Setup...", "Print..."]
|
|
)
|
|
}
|
|
|
|
func testRemovesSaveWithEllipsisWithoutRemovingSaveAs() {
|
|
let fileMenu = NSMenu(title: "File")
|
|
["Save...", "Save As...", "Duplicate", "Rename"]
|
|
.forEach { fileMenu.addItem(withTitle: $0, action: nil, keyEquivalent: "") }
|
|
|
|
FileMenuPruner.removeEditingItems(from: fileMenu)
|
|
|
|
XCTAssertEqual(fileMenu.items.map(\.title), ["Save As...", "Duplicate", "Rename"])
|
|
}
|
|
|
|
func testRemovesNestedRevertToSubmenu() {
|
|
let fileMenu = NSMenu(title: "File")
|
|
fileMenu.addItem(withTitle: "Open...", action: nil, keyEquivalent: "")
|
|
let revertItem = NSMenuItem(title: "Revert To", action: nil, keyEquivalent: "")
|
|
revertItem.submenu = NSMenu(title: "Revert To")
|
|
fileMenu.addItem(revertItem)
|
|
fileMenu.addItem(withTitle: "Print...", action: nil, keyEquivalent: "")
|
|
|
|
FileMenuPruner.removeEditingItems(from: fileMenu)
|
|
|
|
XCTAssertEqual(fileMenu.items.map(\.title), ["Open...", "Print..."])
|
|
}
|
|
}
|
|
|
|
final class ExternalEditorMenuStateTests: XCTestCase {
|
|
func testDisabledWhenNoEditorsAreAvailable() {
|
|
let state = ExternalEditorMenuState(editors: [])
|
|
|
|
XCTAssertEqual(state, .disabled)
|
|
}
|
|
|
|
func testSingleEditorUsesAppNameInTitle() {
|
|
let editor = EditorConfig(name: "TextEdit", path: "/System/Applications/TextEdit.app")
|
|
let state = ExternalEditorMenuState(editors: [editor])
|
|
|
|
XCTAssertEqual(state, .single(editor, title: "Open in TextEdit"))
|
|
}
|
|
|
|
func testMultipleEditorsUseSubmenu() {
|
|
let textEdit = EditorConfig(name: "TextEdit", path: "/System/Applications/TextEdit.app")
|
|
let code = EditorConfig(name: "Visual Studio Code", path: "/Applications/Visual Studio Code.app")
|
|
let state = ExternalEditorMenuState(editors: [textEdit, code])
|
|
|
|
XCTAssertEqual(state, .submenu([textEdit, code]))
|
|
}
|
|
|
|
func testSingleEditorFileMenuItemKeepsEditorIDForAction() throws {
|
|
let controller = ExternalEditorFileMenuController()
|
|
let manager = EditorManager()
|
|
let editor = EditorConfig(name: "TextEdit", path: "/System/Applications/TextEdit.app")
|
|
manager.editors = [editor]
|
|
controller.editorManager = manager
|
|
controller.currentFileURLProvider = { URL(fileURLWithPath: "/tmp/test.md") }
|
|
|
|
let fileMenu = NSMenu(title: "File")
|
|
fileMenu.addItem(withTitle: "Open Recent", action: nil, keyEquivalent: "")
|
|
|
|
controller.update(in: fileMenu)
|
|
|
|
let item = try XCTUnwrap(fileMenu.item(withTitle: "Open in TextEdit"))
|
|
XCTAssertEqual(item.representedObject as? String, editor.id.uuidString)
|
|
XCTAssertTrue(item.target === controller)
|
|
}
|
|
|
|
func testSingleEditorFileMenuItemIsDisabledWithoutOpenFile() throws {
|
|
let controller = ExternalEditorFileMenuController()
|
|
let manager = EditorManager()
|
|
manager.editors = [EditorConfig(name: "TextEdit", path: "/System/Applications/TextEdit.app")]
|
|
controller.editorManager = manager
|
|
controller.currentFileURLProvider = { nil }
|
|
|
|
let fileMenu = NSMenu(title: "File")
|
|
fileMenu.addItem(withTitle: "Open Recent", action: nil, keyEquivalent: "")
|
|
|
|
controller.update(in: fileMenu)
|
|
|
|
let item = try XCTUnwrap(fileMenu.item(withTitle: "Open in TextEdit"))
|
|
XCTAssertFalse(item.isEnabled)
|
|
XCTAssertNil(item.action)
|
|
XCTAssertNil(item.target)
|
|
XCTAssertFalse(controller.validateMenuItem(item))
|
|
}
|
|
|
|
func testExternalEditorSubmenuItemsAreDisabledWithoutOpenFile() throws {
|
|
let controller = ExternalEditorFileMenuController()
|
|
let manager = EditorManager()
|
|
manager.editors = [
|
|
EditorConfig(name: "TextEdit", path: "/System/Applications/TextEdit.app"),
|
|
EditorConfig(name: "Visual Studio Code", path: "/Applications/Visual Studio Code.app")
|
|
]
|
|
controller.editorManager = manager
|
|
controller.currentFileURLProvider = { nil }
|
|
|
|
let fileMenu = NSMenu(title: "File")
|
|
fileMenu.addItem(withTitle: "Open Recent", action: nil, keyEquivalent: "")
|
|
|
|
controller.update(in: fileMenu)
|
|
|
|
let item = try XCTUnwrap(fileMenu.item(withTitle: "Open in External Editor"))
|
|
let submenu = try XCTUnwrap(item.submenu)
|
|
XCTAssertTrue(item.isEnabled)
|
|
XCTAssertTrue(submenu.items.allSatisfy { !$0.isEnabled })
|
|
XCTAssertTrue(submenu.items.allSatisfy { $0.action == nil })
|
|
XCTAssertTrue(submenu.items.allSatisfy { $0.target == nil })
|
|
XCTAssertTrue(submenu.items.allSatisfy { !controller.validateMenuItem($0) })
|
|
}
|
|
|
|
func testExternalEditorMenuItemValidationAllowsOpenFile() throws {
|
|
let controller = ExternalEditorFileMenuController()
|
|
let manager = EditorManager()
|
|
manager.editors = [EditorConfig(name: "TextEdit", path: "/System/Applications/TextEdit.app")]
|
|
controller.editorManager = manager
|
|
controller.currentFileURLProvider = { URL(fileURLWithPath: "/tmp/test.md") }
|
|
|
|
let fileMenu = NSMenu(title: "File")
|
|
fileMenu.addItem(withTitle: "Open Recent", action: nil, keyEquivalent: "")
|
|
|
|
controller.update(in: fileMenu)
|
|
|
|
let item = try XCTUnwrap(fileMenu.item(withTitle: "Open in TextEdit"))
|
|
XCTAssertEqual(item.action, NSSelectorFromString("openInExternalEditor:"))
|
|
XCTAssertTrue(item.target === controller)
|
|
XCTAssertTrue(controller.validateMenuItem(item))
|
|
}
|
|
|
|
func testCurrentOpenDocumentFileURLIgnoresDocumentsWithoutVisibleWindows() {
|
|
let document = NSDocument()
|
|
document.fileURL = URL(fileURLWithPath: "/tmp/closed.md")
|
|
document.addWindowController(NSWindowController(window: TestWindow(isVisibleForTest: false)))
|
|
|
|
XCTAssertNil(ExternalEditorFileMenuController.currentOpenDocumentFileURL(in: [document]))
|
|
}
|
|
|
|
func testCurrentOpenDocumentFileURLUsesVisibleDocumentWindow() {
|
|
let hiddenDocument = NSDocument()
|
|
hiddenDocument.fileURL = URL(fileURLWithPath: "/tmp/hidden.md")
|
|
hiddenDocument.addWindowController(NSWindowController(window: TestWindow(isVisibleForTest: false)))
|
|
|
|
let visibleDocument = NSDocument()
|
|
let visibleURL = URL(fileURLWithPath: "/tmp/visible.md")
|
|
visibleDocument.fileURL = visibleURL
|
|
visibleDocument.addWindowController(NSWindowController(window: TestWindow(isVisibleForTest: true)))
|
|
|
|
XCTAssertEqual(
|
|
ExternalEditorFileMenuController.currentOpenDocumentFileURL(in: [hiddenDocument, visibleDocument]),
|
|
visibleURL
|
|
)
|
|
}
|
|
}
|
|
|
|
private final class TestWindow: NSWindow {
|
|
private let isVisibleForTest: Bool
|
|
|
|
init(isVisibleForTest: Bool) {
|
|
self.isVisibleForTest = isVisibleForTest
|
|
super.init(
|
|
contentRect: NSRect(x: 0, y: 0, width: 100, height: 100),
|
|
styleMask: [],
|
|
backing: .buffered,
|
|
defer: false
|
|
)
|
|
}
|
|
|
|
override var isVisible: Bool {
|
|
isVisibleForTest
|
|
}
|
|
}
|