diff options
Diffstat (limited to 'Tests/NorgKeyboardToolbarTests/EditorSnippetTests.swift')
| -rw-r--r-- | Tests/NorgKeyboardToolbarTests/EditorSnippetTests.swift | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/Tests/NorgKeyboardToolbarTests/EditorSnippetTests.swift b/Tests/NorgKeyboardToolbarTests/EditorSnippetTests.swift new file mode 100644 index 0000000..00a9332 --- /dev/null +++ b/Tests/NorgKeyboardToolbarTests/EditorSnippetTests.swift @@ -0,0 +1,150 @@ +import Testing + +@testable import NorgKeyboardToolbar + +struct EditorSnippetTests { + + @Test func idMatchesRawValueAndIsUnique() { + for snippet in EditorSnippet.allCases { + #expect(snippet.id == snippet.rawValue) + } + #expect(Set(EditorSnippet.allCases.map(\.id)).count == EditorSnippet.allCases.count) + } + + @Test func insertsIntoEmptyDocumentWithoutLeadingNewline() { + let result = EditorSnippet.heading.apply(to: "", cursor: 0) + #expect(result.text == "* ") + #expect(result.cursor == 2) + } + + @Test func insertsOnNewLineBeneathCurrentLine() { + let result = EditorSnippet.task.apply(to: "first line", cursor: 3) + #expect(result.text == "first line\n- ( ) ") + // Cursor sits at the end of the inserted task marker, ready to type. + #expect(result.cursor == result.text.count) + } + + @Test func insertsBetweenLinesNotSplittingThem() { + let result = EditorSnippet.task.apply(to: "a\nb", cursor: 0) + #expect(result.text == "a\n- ( ) \nb") + } + + @Test func delimiterHasNoTrailingSpace() { + let weak = EditorSnippet.weakReverse.apply(to: "x", cursor: 1) + #expect(weak.text == "x\n---") + let strong = EditorSnippet.strongReverse.apply(to: "x", cursor: 1) + #expect(strong.text == "x\n===") + } + + @Test func codeBlockPlacesCursorIndentedBetweenMarkers() { + let result = EditorSnippet.code.apply(to: "note", cursor: 4) + #expect(result.text == "note\n@code\n\t\n@end") + // Cursor lands right after the tab on the middle line. + let index = result.text.index(result.text.startIndex, offsetBy: result.cursor) + #expect(result.text[result.text.startIndex..<index].hasSuffix("@code\n\t")) + #expect(String(result.text[index...]) == "\n@end") + } + + @Test func clampsCursorBeyondBounds() { + let result = EditorSnippet.heading.apply(to: "abc", cursor: 999) + #expect(result.text == "abc\n* ") + } + + // MARK: - Heading promotion (the `*` button's special behaviour) + + @Test func headingPromotesEmptyMarker() { + // "* |" -> "** |" + let result = EditorSnippet.heading.apply(to: "* ", cursor: 2) + #expect(result.text == "** ") + #expect(result.cursor == 3) + } + + @Test func headingPromotesWithTrailingContent() { + // "* |Hello" -> "** |Hello" + let result = EditorSnippet.heading.apply(to: "* Hello", cursor: 2) + #expect(result.text == "** Hello") + #expect(result.cursor == 3) + } + + @Test func headingPromotesBareStars() { + // "***|" -> "****|" + let result = EditorSnippet.heading.apply(to: "***", cursor: 3) + #expect(result.text == "****") + #expect(result.cursor == 4) + } + + @Test func headingInsertsNewLineWhenCursorAfterContent() { + // "* Hello|" -> new heading line + let result = EditorSnippet.heading.apply(to: "* Hello", cursor: 7) + #expect(result.text == "* Hello\n* ") + } + + @Test func headingInsertsNewLineWhenMarkerNotAtLineStart() { + // "Hello *|" -> new heading line, not promotion + let result = EditorSnippet.heading.apply(to: "Hello *", cursor: 7) + #expect(result.text == "Hello *\n* ") + } + + @Test func headingPromotesIndentedMarker() { + let result = EditorSnippet.heading.apply(to: " ** ", cursor: 5) + #expect(result.text == " *** ") + } + + @Test func headingPromotionKeepsCursorWhenInsertingAfterIt() { + // "*|*" -> "**|*" : the new star lands after the cursor, so the offset + // is unchanged. + let result = EditorSnippet.heading.apply(to: "**", cursor: 1) + #expect(result.text == "***") + #expect(result.cursor == 1) + } + + // MARK: - Task button heading awareness + + @Test func taskAddsMarkerToBareHeading() { + // "* |" -> "* ( ) |" + let result = EditorSnippet.task.apply(to: "* ", cursor: 2) + #expect(result.text == "* ( ) ") + #expect(result.cursor == 6) + } + + @Test func taskAddsMarkerToHeadingPreservingLevelAndContent() { + // "** |Hello" -> "** ( ) |Hello" + let result = EditorSnippet.task.apply(to: "** Hello", cursor: 3) + #expect(result.text == "** ( ) Hello") + #expect(result.cursor == 7) + } + + @Test func taskInsertsNewLineWhenHeadingHasContent() { + // "** Hello|" -> "** Hello\n- ( ) " + let result = EditorSnippet.task.apply(to: "** Hello", cursor: 8) + #expect(result.text == "** Hello\n- ( ) ") + #expect(result.cursor == result.text.count) + } + + @Test func taskAddsMarkerToBareOrderedListItem() { + // "~ |" -> "~ ( ) |" + let result = EditorSnippet.task.apply(to: "~ ", cursor: 2) + #expect(result.text == "~ ( ) ") + #expect(result.cursor == 6) + } + + @Test func taskAddsMarkerToOrderedListPreservingLevelAndContent() { + // "~~ |Hello" -> "~~ ( ) |Hello" + let result = EditorSnippet.task.apply(to: "~~ Hello", cursor: 3) + #expect(result.text == "~~ ( ) Hello") + #expect(result.cursor == 7) + } + + @Test func taskInsertsNewLineWhenOrderedListHasContent() { + // "~ Hello|" -> "~ Hello\n- ( ) " + let result = EditorSnippet.task.apply(to: "~ Hello", cursor: 7) + #expect(result.text == "~ Hello\n- ( ) ") + #expect(result.cursor == result.text.count) + } + + @Test func headingIgnoresOrderedListMarker() { + // The `*` button only promotes `*` headings, not `~` lists. + let result = EditorSnippet.heading.apply(to: "~ ", cursor: 2) + #expect(result.text == "~ \n* ") + } +} |