Sapling/Tests/SaplingEditorTests/MarkdownTextStylerRenderingTests.swift

128 lines
5.9 KiB
Swift
Raw Normal View History

import XCTest
@testable import SaplingEditor
#if os(macOS)
import AppKit
final class MarkdownTextStylerRenderingTests: XCTestCase {
func testRenderedHeadingHidesMarkerWhileActiveHeadingKeepsSourceVisible() {
let source = "Intro\n# Heading"
let renderedStorage = styledStorage(source: source, activeLineIndex: 0)
let activeStorage = styledStorage(source: source, activeLineIndex: 1)
let headingMarker = (source as NSString).range(of: "#")
let headingText = (source as NSString).range(of: "Heading")
XCTAssertTrue(isHidden(renderedStorage, at: headingMarker.location))
XCTAssertGreaterThan(font(in: renderedStorage, at: headingText.location).pointSize, 20)
XCTAssertFalse(isHidden(activeStorage, at: headingMarker.location))
}
func testRenderedInlineMarkdownHidesDelimitersOnly() {
let source = "Intro\nThis has **bold**, *italic*, and `code`."
let storage = styledStorage(source: source, activeLineIndex: 0)
let nsSource = source as NSString
XCTAssertTrue(isHidden(storage, at: nsSource.range(of: "**").location))
XCTAssertFalse(isHidden(storage, at: nsSource.range(of: "bold").location))
XCTAssertTrue(isHidden(storage, at: nsSource.range(of: "*italic*").location))
XCTAssertFalse(isHidden(storage, at: nsSource.range(of: "italic").location))
XCTAssertTrue(isHidden(storage, at: nsSource.range(of: "`").location))
XCTAssertNotNil(storage.attribute(.backgroundColor, at: nsSource.range(of: "code").location, effectiveRange: nil))
}
func testRenderedTaskListHidesListMarkerAndShowsTaskState() {
let source = "Intro\n* [x] Done\n* [ ] Todo"
let storage = styledStorage(source: source, activeLineIndex: 0)
let nsSource = source as NSString
let checkedMarker = nsSource.range(of: "* [x]")
let uncheckedMarker = nsSource.range(of: "* [ ]")
let doneRange = nsSource.range(of: "Done")
XCTAssertTrue(isHidden(storage, at: checkedMarker.location))
XCTAssertFalse(isHidden(storage, at: checkedMarker.location + 2))
XCTAssertNotNil(storage.attribute(.backgroundColor, at: checkedMarker.location + 2, effectiveRange: nil))
XCTAssertTrue(isHidden(storage, at: uncheckedMarker.location))
XCTAssertFalse(isHidden(storage, at: uncheckedMarker.location + 2))
XCTAssertNotNil(storage.attribute(.strikethroughStyle, at: doneRange.location, effectiveRange: nil))
}
func testRenderedCodeBlockHidesFencesAndStylesCodeContent() {
let source = "Intro\n```swift\nlet value = 42\n```"
let storage = styledStorage(source: source, activeLineIndex: 0)
let nsSource = source as NSString
let openingFence = nsSource.range(of: "```swift")
let language = nsSource.range(of: "swift")
let code = nsSource.range(of: "let value = 42")
let closingFence = nsSource.range(of: "```", options: .backwards)
XCTAssertTrue(isHidden(storage, at: openingFence.location))
XCTAssertFalse(isHidden(storage, at: language.location))
XCTAssertNotNil(storage.attribute(.backgroundColor, at: code.location, effectiveRange: nil))
XCTAssertEqual(font(in: storage, at: code.location).fontDescriptor.symbolicTraits.contains(.monoSpace), true)
XCTAssertTrue(isHidden(storage, at: closingFence.location))
}
func testDirtyCodeBlockRenderingResolvesBlockContext() {
let source = "Intro\n```swift\nlet value = 42\n```"
let storage = NSTextStorage(string: source)
let lineIndex = DocumentLineIndex(source: source)
let codeLine = 2
MarkdownTextStyler.apply(
to: storage,
lineIndex: lineIndex,
invalidationPlan: EditorDirtyLineInvalidationPlan(
reason: .activeLineChange,
isFullRender: false,
dirtyLineIndexes: [codeLine]
),
activeLineIndex: 0,
backgroundColor: .textBackgroundColor,
activeLineBackgroundColor: .controlAccentColor.withAlphaComponent(0.10),
textColor: .labelColor,
secondaryTextColor: .secondaryLabelColor,
accentColor: .controlAccentColor
)
let code = (source as NSString).range(of: "let value = 42")
XCTAssertNotNil(storage.attribute(.backgroundColor, at: code.location, effectiveRange: nil))
XCTAssertEqual(font(in: storage, at: code.location).fontDescriptor.symbolicTraits.contains(.monoSpace), true)
}
private func styledStorage(source: String, activeLineIndex: Int) -> NSTextStorage {
let storage = NSTextStorage(string: source)
let lineIndex = DocumentLineIndex(source: source)
MarkdownTextStyler.apply(
to: storage,
lineIndex: lineIndex,
invalidationPlan: EditorDirtyLineInvalidator.plan(
previousText: nil,
currentLineIndex: lineIndex,
edit: nil,
previousActiveLineIndex: nil,
currentActiveLineIndex: activeLineIndex
),
activeLineIndex: activeLineIndex,
backgroundColor: .textBackgroundColor,
activeLineBackgroundColor: .controlAccentColor.withAlphaComponent(0.10),
textColor: .labelColor,
secondaryTextColor: .secondaryLabelColor,
accentColor: .controlAccentColor
)
return storage
}
private func isHidden(_ storage: NSTextStorage, at location: Int) -> Bool {
let color = storage.attribute(.foregroundColor, at: location, effectiveRange: nil) as? NSColor
return color?.alphaComponent == 0 && font(in: storage, at: location).pointSize < 1
}
private func font(in storage: NSTextStorage, at location: Int) -> NSFont {
guard let font = storage.attribute(.font, at: location, effectiveRange: nil) as? NSFont else {
return NSFont.systemFont(ofSize: 0)
}
return font
}
}
#endif