forked from KeyboardKit/KeyboardKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a new insertAutocompleteSuggestion proxy extension
- Loading branch information
1 parent
c86c034
commit 964169c
Showing
6 changed files
with
175 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
Sources/KeyboardKit/Autocomplete/UITextDocumentProxy+Autocomplete.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// UITextDocumentProxy+Autocomplete.swift | ||
// KeyboardKit | ||
// | ||
// Created by Daniel Saidi on 2021-03-18. | ||
// Copyright © 2021 Daniel Saidi. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
|
||
public extension UITextDocumentProxy { | ||
|
||
/** | ||
Replace the current word with the suggestion's text and | ||
the try to insert a space, if needed. | ||
*/ | ||
func insertAutocompleteSuggestion(_ suggestion: AutocompleteSuggestion) { | ||
replaceCurrentWord(with: suggestion.text) | ||
tryInsertSpaceAfterSuggestion() | ||
} | ||
} | ||
|
||
public extension UITextDocumentProxy { | ||
|
||
func tryInsertSpaceAfterSuggestion() { | ||
let space = " " | ||
let hasPreviousSpace = documentContextBeforeInput?.hasSuffix(space) ?? false | ||
let hasNextSpace = documentContextAfterInput?.hasPrefix(space) ?? false | ||
if hasPreviousSpace || hasNextSpace { return } | ||
insertText(space) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
Tests/KeyboardKitTests/Autocomplete/UITextDocumentProxy+AutocompleteTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// | ||
// UITextDocumentProxy+AutocompleteTests.swift | ||
// KeyboardKit | ||
// | ||
// Created by Daniel Saidi on 2021-03-18. | ||
// Copyright © 2021 Daniel Saidi. All rights reserved. | ||
// | ||
|
||
import Quick | ||
import Nimble | ||
import MockingKit | ||
import KeyboardKit | ||
|
||
class UITextDocumentProxy_AutocompleteTests: QuickSpec { | ||
|
||
override func spec() { | ||
|
||
let word = "REPLACE" | ||
|
||
var proxy: MockTextDocumentProxy! | ||
|
||
beforeEach { | ||
proxy = MockTextDocumentProxy() | ||
} | ||
|
||
describe("handle autocomplete suggestion") { | ||
|
||
let suggestion = StandardAutocompleteSuggestion(word) | ||
|
||
it("deletes backwards correctly") { | ||
proxy.documentContextBeforeInput = "" | ||
proxy.insertAutocompleteSuggestion(suggestion) | ||
|
||
} | ||
|
||
it("inserts word and space in empty proxy") { | ||
proxy.documentContextBeforeInput = "" | ||
proxy.insertAutocompleteSuggestion(suggestion) | ||
let deleteCalls = proxy.calls(to: proxy.deleteBackwardRef) | ||
let insertCalls = proxy.calls(to: proxy.insertTextRef) | ||
expect(deleteCalls.count).to(equal(0)) | ||
expect(insertCalls.count).to(equal(2)) | ||
expect(insertCalls[0].arguments).to(equal(word)) | ||
expect(insertCalls[1].arguments).to(equal(" ")) | ||
} | ||
|
||
it("inserts word and space in non-empty proxy where input has no surrounding spaces") { | ||
proxy.documentContextBeforeInput = "foo" | ||
proxy.documentContextAfterInput = "bar" | ||
proxy.insertAutocompleteSuggestion(suggestion) | ||
let deleteCalls = proxy.calls(to: proxy.deleteBackwardRef) | ||
let insertCalls = proxy.calls(to: proxy.insertTextRef) | ||
expect(deleteCalls.count).to(equal(6)) | ||
expect(insertCalls.count).to(equal(2)) | ||
expect(insertCalls[0].arguments).to(equal(word)) | ||
expect(insertCalls[1].arguments).to(equal(" ")) | ||
} | ||
|
||
it("inserts word and space in non-empty proxy where input has leading space") { | ||
proxy.documentContextBeforeInput = "foo " | ||
proxy.documentContextAfterInput = "bar" | ||
proxy.insertAutocompleteSuggestion(suggestion) | ||
let deleteCalls = proxy.calls(to: proxy.deleteBackwardRef) | ||
let insertCalls = proxy.calls(to: proxy.insertTextRef) | ||
expect(deleteCalls.count).to(equal(3)) | ||
expect(insertCalls.count).to(equal(2)) | ||
expect(insertCalls[0].arguments).to(equal(word)) | ||
expect(insertCalls[1].arguments).to(equal(" ")) | ||
} | ||
|
||
it("inserts only word in non-empty proxy where input has trailing space") { | ||
proxy.documentContextBeforeInput = "foo" | ||
proxy.documentContextAfterInput = " bar" | ||
proxy.insertAutocompleteSuggestion(suggestion) | ||
let deleteCalls = proxy.calls(to: proxy.deleteBackwardRef) | ||
let insertCalls = proxy.calls(to: proxy.insertTextRef) | ||
expect(deleteCalls.count).to(equal(3)) | ||
expect(insertCalls.count).to(equal(1)) | ||
expect(insertCalls[0].arguments).to(equal(word)) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// | ||
// MockTextDocumentProxy.swift | ||
// KeyboardKit | ||
// | ||
// Created by Daniel Saidi on 2021-03-18. | ||
// Copyright © 2021 Daniel Saidi. All rights reserved. | ||
// | ||
|
||
import MockingKit | ||
import UIKit | ||
|
||
/** | ||
This class can be used as a mocked `UITextDocumentProxy`. | ||
*/ | ||
open class MockTextDocumentProxy: NSObject, UITextDocumentProxy, Mockable { | ||
|
||
public lazy var adjustTextPositionRef = MockReference(adjustTextPosition) | ||
public lazy var deleteBackwardRef = MockReference(deleteBackward as () -> Void) | ||
public lazy var insertTextRef = MockReference(insertText) | ||
public lazy var setMarkedTextRef = MockReference(setMarkedText) | ||
public lazy var unmarkTextRef = MockReference(unmarkText) | ||
|
||
public let mock = Mock() | ||
|
||
public var hasText: Bool = false | ||
|
||
public var autocapitalizationType: UITextAutocapitalizationType = .none | ||
public var documentContextBeforeInput: String? | ||
public var documentContextAfterInput: String? | ||
public var documentIdentifier: UUID = UUID() | ||
public var documentInputMode: UITextInputMode? | ||
public var keyboardAppearance: UIKeyboardAppearance = .light | ||
public var selectedText: String? | ||
|
||
public func adjustTextPosition(byCharacterOffset offset: Int) { | ||
call(adjustTextPositionRef, args: (offset)) | ||
} | ||
|
||
public func deleteBackward() { | ||
let preCount = documentContextBeforeInput?.count ?? 0 | ||
if preCount > 0 { documentContextBeforeInput?.removeLast() } | ||
call(deleteBackwardRef, args: ()) | ||
} | ||
|
||
public func insertText(_ text: String) { | ||
call(insertTextRef, args: (text)) | ||
} | ||
|
||
public func setMarkedText(_ markedText: String, selectedRange: NSRange) { | ||
call(setMarkedTextRef, args: (markedText, selectedRange)) | ||
} | ||
|
||
public func unmarkText() { | ||
call(unmarkTextRef, args: ()) | ||
} | ||
} |