Skip to content

Commit

Permalink
Add a new insertAutocompleteSuggestion proxy extension
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsaidi committed Mar 18, 2021
1 parent c86c034 commit 964169c
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 3 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"repositoryURL": "https://github.com/danielsaidi/MockingKit.git",
"state": {
"branch": null,
"revision": "26bb7371e769a4b4a725358d817e7f842f6aab7b",
"version": "0.9.2"
"revision": "3fb3fb321c6752b06662462d2b10c7377b7d3843",
"version": "0.9.3"
}
},
{
Expand Down
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Breaking changes can still occur in minor versions, if the alternative is to not
* `KeyboardInputViewController` has a new `autocompleteSuggestionProvider` property.
* `KeyboardInputViewController` has now implemented `performAutocomplete` and `resetAutocomplete`.
* `SystemKeyboardSpaceButtonContent` has a new initializer that lets you inject a custom space view.
* `UITextDocumentProxy` has a new `insertAutocompleteSuggestion` function.
* `UITextDocumentProxy` has a new `isOpenAlternateQuotationBeforeInput(for:)` function.
* `UITextDocumentProxy` has a new `isOpenQuotationBeforeInput(for:)` function.

Expand Down
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)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class KeyboardAction_AutocompleteTests: QuickSpec {
expected.append(.newLine)
expected.append(.return)
expected.append(.space)

actions.forEach {
expect($0.shouldApplyAutocompleteSuggestion).to(equal(expected.contains($0)))
}
Expand Down
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))
}
}
}
}
56 changes: 56 additions & 0 deletions Tests/KeyboardKitTests/Mocks/MockTextDocumentProxy.swift
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: ())
}
}

0 comments on commit 964169c

Please sign in to comment.