Tests // Add unit tests for certain components.
Tests // +PrefManagerTests. Tests // +KeyHandlerTestsNormalCHS. Tests // +UpdateAPITests. Tests // KeyHandlerTestsSCPCCHT (not finished).
This commit is contained in:
parent
d5cbd10a34
commit
0b848f6305
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,383 @@
|
||||||
|
// Copyright (c) 2021 and onwards Zonble Yang (MIT-NTL License).
|
||||||
|
// All possible vChewing-specific modifications are of:
|
||||||
|
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||||
|
/*
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
1. The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
2. No trademark license is granted to use the trade names, trademarks, service
|
||||||
|
marks, or product names of Contributor, except as required to fulfill notice
|
||||||
|
requirements above.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import vChewing
|
||||||
|
|
||||||
|
class KeyHandlerTestsSCPCCHT: XCTestCase {
|
||||||
|
func reset() {
|
||||||
|
mgrPrefs.allKeys.forEach {
|
||||||
|
UserDefaults.standard.removeObject(forKey: $0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSnapshot() -> [String: Any] {
|
||||||
|
var dict = [String: Any]()
|
||||||
|
mgrPrefs.allKeys.forEach {
|
||||||
|
dict[$0] = UserDefaults.standard.object(forKey: $0)
|
||||||
|
}
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
|
||||||
|
func restore(from snapshot: [String: Any]) {
|
||||||
|
mgrPrefs.allKeys.forEach {
|
||||||
|
UserDefaults.standard.set(snapshot[$0], forKey: $0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var snapshot: [String: Any]?
|
||||||
|
|
||||||
|
var handler = KeyHandler()
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
snapshot = makeSnapshot()
|
||||||
|
reset()
|
||||||
|
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC"
|
||||||
|
mgrPrefs.mandarinParser = 0
|
||||||
|
mgrPrefs.useSCPCTypingMode = false
|
||||||
|
mgrPrefs.associatedPhrasesEnabled = false
|
||||||
|
mgrLangModel.loadDataModel(.imeModeCHT)
|
||||||
|
handler = KeyHandler()
|
||||||
|
handler.inputMode = .imeModeCHT
|
||||||
|
_ = mgrPrefs.toggleSCPCTypingModeEnabled()
|
||||||
|
_ = mgrPrefs.toggleAssociatedPhrasesEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDownWithError() throws {
|
||||||
|
if let snapshot = snapshot {
|
||||||
|
restore(from: snapshot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPunctuationTable() {
|
||||||
|
let input = InputSignal(
|
||||||
|
inputText: "`", keyCode: KeyCode.kSymbolMenuPhysicalKey.rawValue, charCode: 0, flags: .option
|
||||||
|
)
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
|
||||||
|
if let state = state as? InputState.ChoosingCandidate {
|
||||||
|
XCTAssertTrue(state.candidates.contains(","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPunctuationComma() {
|
||||||
|
let enabled = mgrPrefs.halfWidthPunctuationEnabled
|
||||||
|
mgrPrefs.halfWidthPunctuationEnabled = false
|
||||||
|
let input = InputSignal(inputText: "<", keyCode: 0, charCode: charCode("<"), flags: .shift)
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
|
||||||
|
if let state = state as? InputState.ChoosingCandidate {
|
||||||
|
XCTAssertEqual(state.composingBuffer, ",")
|
||||||
|
}
|
||||||
|
mgrPrefs.halfWidthPunctuationEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPunctuationPeriod() {
|
||||||
|
let enabled = mgrPrefs.halfWidthPunctuationEnabled
|
||||||
|
mgrPrefs.halfWidthPunctuationEnabled = false
|
||||||
|
let input = InputSignal(inputText: ">", keyCode: 0, charCode: charCode(">"), flags: .shift)
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
|
||||||
|
if let state = state as? InputState.ChoosingCandidate {
|
||||||
|
XCTAssertEqual(state.composingBuffer, "。")
|
||||||
|
}
|
||||||
|
mgrPrefs.halfWidthPunctuationEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHalfPunctuationPeriod() {
|
||||||
|
let enabled = mgrPrefs.halfWidthPunctuationEnabled
|
||||||
|
mgrPrefs.halfWidthPunctuationEnabled = true
|
||||||
|
let input = InputSignal(inputText: ">", keyCode: 0, charCode: charCode(">"), flags: .shift)
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
|
||||||
|
if let state = state as? InputState.ChoosingCandidate {
|
||||||
|
XCTAssertEqual(state.composingBuffer, ".")
|
||||||
|
}
|
||||||
|
mgrPrefs.halfWidthPunctuationEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func testControlPunctuationPeriod() {
|
||||||
|
let input = InputSignal(
|
||||||
|
inputText: ".", keyCode: 0, charCode: charCode("."), flags: [.shift, .control]
|
||||||
|
)
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
var count = 0
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
if count == 0 {
|
||||||
|
state = newState
|
||||||
|
}
|
||||||
|
count += 1
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.Inputting, "\(state)")
|
||||||
|
if let state = state as? InputState.Inputting {
|
||||||
|
XCTAssertEqual(state.composingBuffer, "。")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEnterWithReading() {
|
||||||
|
let input = InputSignal(inputText: "s", keyCode: 0, charCode: charCode("s"), flags: .shift)
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.Inputting, "\(state)")
|
||||||
|
if let state = state as? InputState.Inputting {
|
||||||
|
XCTAssertEqual(state.composingBuffer, "ㄋ")
|
||||||
|
}
|
||||||
|
|
||||||
|
let enter = InputSignal(inputText: " ", keyCode: 0, charCode: 13, flags: [])
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
_ = handler.handle(input: enter, state: state) { newState in
|
||||||
|
if count == 0 {
|
||||||
|
state = newState
|
||||||
|
}
|
||||||
|
count += 1
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.Inputting, "\(state)")
|
||||||
|
if let state = state as? InputState.Inputting {
|
||||||
|
XCTAssertEqual(state.composingBuffer, "ㄋ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInputNe() {
|
||||||
|
let input = InputSignal(inputText: "s", keyCode: 0, charCode: charCode("s"), flags: .shift)
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.Inputting, "\(state)")
|
||||||
|
if let state = state as? InputState.Inputting {
|
||||||
|
XCTAssertEqual(state.composingBuffer, "ㄋ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInputNi() {
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
let keys = Array("su").map {
|
||||||
|
String($0)
|
||||||
|
}
|
||||||
|
for key in keys {
|
||||||
|
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.Inputting, "\(state)")
|
||||||
|
if let state = state as? InputState.Inputting {
|
||||||
|
XCTAssertEqual(state.composingBuffer, "ㄋㄧ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInputNi3() {
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
let keys = Array("su3").map {
|
||||||
|
String($0)
|
||||||
|
}
|
||||||
|
for key in keys {
|
||||||
|
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.ChoosingCandidate, "\(state)")
|
||||||
|
if let state = state as? InputState.ChoosingCandidate {
|
||||||
|
XCTAssertTrue(state.candidates.contains("你"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Further bug-hunting needed.
|
||||||
|
func testCancelCandidateUsingDelete() {
|
||||||
|
mgrPrefs.useSCPCTypingMode = true
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
let keys = Array("su3").map {
|
||||||
|
String($0)
|
||||||
|
}
|
||||||
|
for key in keys {
|
||||||
|
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = InputSignal(
|
||||||
|
inputText: " ", keyCode: KeyCode.kWindowsDelete.rawValue, charCode: charCode(" "), flags: []
|
||||||
|
)
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
print("Expecting EmptyIgnoringPreviousState.")
|
||||||
|
print("\(state)")
|
||||||
|
// XCTAssertTrue(state is InputState.EmptyIgnoringPreviousState, "\(state)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Further bug-hunting needed.
|
||||||
|
func testCancelCandidateUsingEsc() {
|
||||||
|
mgrPrefs.useSCPCTypingMode = true
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
let keys = Array("su3").map {
|
||||||
|
String($0)
|
||||||
|
}
|
||||||
|
for key in keys {
|
||||||
|
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = InputSignal(inputText: " ", keyCode: KeyCode.kEscape.rawValue, charCode: charCode(" "), flags: [])
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
print("Expecting EmptyIgnoringPreviousState.")
|
||||||
|
print("\(state)")
|
||||||
|
// XCTAssertTrue(state is InputState.EmptyIgnoringPreviousState, "\(state)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Further bug-hunting needed.
|
||||||
|
func testAssociatedPhrases() {
|
||||||
|
let enabled = mgrPrefs.associatedPhrasesEnabled
|
||||||
|
mgrPrefs.associatedPhrasesEnabled = true
|
||||||
|
mgrPrefs.useSCPCTypingMode = true
|
||||||
|
handler.forceOpenStringInsteadForAssociatePhrases("二 百五")
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
let keys = Array("-41").map {
|
||||||
|
String($0)
|
||||||
|
}
|
||||||
|
for key in keys {
|
||||||
|
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print("Expecting AssociatedPhrases.")
|
||||||
|
print("\(state)")
|
||||||
|
// XCTAssertTrue(state is InputState.AssociatedPhrases, "\(state)")
|
||||||
|
if let state = state as? InputState.AssociatedPhrases {
|
||||||
|
// XCTAssertTrue(state.candidates.contains("百五"))
|
||||||
|
}
|
||||||
|
mgrPrefs.associatedPhrasesEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNoAssociatedPhrases() {
|
||||||
|
let enabled = mgrPrefs.associatedPhrasesEnabled
|
||||||
|
mgrPrefs.associatedPhrasesEnabled = false
|
||||||
|
var state: InputStateProtocol = InputState.Empty()
|
||||||
|
let keys = Array("aul ").map {
|
||||||
|
String($0)
|
||||||
|
}
|
||||||
|
for key in keys {
|
||||||
|
let input = InputSignal(inputText: key, keyCode: 0, charCode: charCode(key), flags: [])
|
||||||
|
_ = handler.handle(input: input, state: state) { newState in
|
||||||
|
state = newState
|
||||||
|
|
||||||
|
} errorCallback: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertTrue(state is InputState.Empty, "\(state)")
|
||||||
|
mgrPrefs.associatedPhrasesEnabled = enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - StringView Ranges Extension (by Isaac Xen)
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
fileprivate func ranges(splitBy separator: Element) -> [Range<String.Index>] {
|
||||||
|
var startIndex = startIndex
|
||||||
|
return split(separator: separator).reduce(into: []) { ranges, substring in
|
||||||
|
_ = range(of: substring, range: startIndex..<endIndex).map { range in
|
||||||
|
ranges.append(range)
|
||||||
|
startIndex = range.upperBound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension vChewing.LMAssociates {
|
||||||
|
public mutating func forceOpenStringInstead(_ strData: String) {
|
||||||
|
strData.ranges(splitBy: "\n").forEach {
|
||||||
|
let neta = strData[$0].split(separator: " ")
|
||||||
|
if neta.count >= 2 {
|
||||||
|
let theKey = String(neta[0])
|
||||||
|
if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" {
|
||||||
|
let theValue = $0
|
||||||
|
rangeMap[theKey, default: []].append(theValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension vChewing.LMInstantiator {
|
||||||
|
public func forceOpenStringInsteadForAssociatePhrases(_ strData: String) {
|
||||||
|
lmAssociates.forceOpenStringInstead(strData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension KeyHandler {
|
||||||
|
public func forceOpenStringInsteadForAssociatePhrases(_ strData: String) {
|
||||||
|
currentLM.forceOpenStringInsteadForAssociatePhrases(strData + "\n")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,276 @@
|
||||||
|
// Copyright (c) 2021 and onwards Zonble Yang (MIT-NTL License).
|
||||||
|
// All possible vChewing-specific modifications are of:
|
||||||
|
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||||
|
/*
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
1. The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
2. No trademark license is granted to use the trade names, trademarks, service
|
||||||
|
marks, or product names of Contributor, except as required to fulfill notice
|
||||||
|
requirements above.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import vChewing
|
||||||
|
|
||||||
|
class PrefManagerTests: XCTestCase {
|
||||||
|
func reset() {
|
||||||
|
mgrPrefs.allKeys.forEach {
|
||||||
|
UserDefaults.standard.removeObject(forKey: $0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSnapshot() -> [String: Any] {
|
||||||
|
var dict = [String: Any]()
|
||||||
|
mgrPrefs.allKeys.forEach {
|
||||||
|
dict[$0] = UserDefaults.standard.object(forKey: $0)
|
||||||
|
}
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
|
||||||
|
func restore(from snapshot: [String: Any]) {
|
||||||
|
mgrPrefs.allKeys.forEach {
|
||||||
|
UserDefaults.standard.set(snapshot[$0], forKey: $0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var snapshot: [String: Any]?
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
snapshot = makeSnapshot()
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tearDownWithError() throws {
|
||||||
|
if let snapshot = snapshot {
|
||||||
|
restore(from: snapshot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMandarinParser() {
|
||||||
|
XCTAssert(mgrPrefs.mandarinParser == 0)
|
||||||
|
mgrPrefs.mandarinParser = 1
|
||||||
|
XCTAssert(mgrPrefs.mandarinParser == 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMandarinParserName() {
|
||||||
|
XCTAssert(mgrPrefs.mandarinParserName == "Standard")
|
||||||
|
mgrPrefs.mandarinParser = 1
|
||||||
|
XCTAssert(mgrPrefs.mandarinParserName == "ETen")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBasisKeyboardLayoutPreferenceKey() {
|
||||||
|
XCTAssert(mgrPrefs.basicKeyboardLayout == "com.apple.keylayout.ZhuyinBopomofo")
|
||||||
|
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC"
|
||||||
|
XCTAssert(mgrPrefs.basicKeyboardLayout == "com.apple.keylayout.ABC")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCandidateTextSize() {
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 18)
|
||||||
|
|
||||||
|
mgrPrefs.candidateListTextSize = 16
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 16)
|
||||||
|
|
||||||
|
mgrPrefs.candidateListTextSize = 11
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 12)
|
||||||
|
mgrPrefs.candidateListTextSize = 197
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 196)
|
||||||
|
|
||||||
|
mgrPrefs.candidateListTextSize = 12
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 12)
|
||||||
|
mgrPrefs.candidateListTextSize = 196
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 196)
|
||||||
|
|
||||||
|
mgrPrefs.candidateListTextSize = 13
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 13)
|
||||||
|
mgrPrefs.candidateListTextSize = 195
|
||||||
|
XCTAssert(mgrPrefs.candidateListTextSize == 195)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUseRearCursorMode() {
|
||||||
|
XCTAssert(mgrPrefs.useRearCursorMode == false)
|
||||||
|
mgrPrefs.useRearCursorMode = true
|
||||||
|
XCTAssert(mgrPrefs.useRearCursorMode == true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUseHorizontalCandidateList() {
|
||||||
|
XCTAssert(mgrPrefs.useHorizontalCandidateList == true)
|
||||||
|
mgrPrefs.useHorizontalCandidateList = false
|
||||||
|
XCTAssert(mgrPrefs.useHorizontalCandidateList == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testComposingBufferSize() {
|
||||||
|
XCTAssert(mgrPrefs.composingBufferSize == 20)
|
||||||
|
mgrPrefs.composingBufferSize = 10
|
||||||
|
XCTAssert(mgrPrefs.composingBufferSize == 10)
|
||||||
|
mgrPrefs.composingBufferSize = 4
|
||||||
|
XCTAssert(mgrPrefs.composingBufferSize == 10)
|
||||||
|
mgrPrefs.composingBufferSize = 50
|
||||||
|
XCTAssert(mgrPrefs.composingBufferSize == 40)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testChooseCandidateUsingSpace() {
|
||||||
|
XCTAssert(mgrPrefs.chooseCandidateUsingSpace == true)
|
||||||
|
mgrPrefs.chooseCandidateUsingSpace = false
|
||||||
|
XCTAssert(mgrPrefs.chooseCandidateUsingSpace == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testChineseConversionEnabled() {
|
||||||
|
XCTAssert(mgrPrefs.chineseConversionEnabled == false)
|
||||||
|
mgrPrefs.chineseConversionEnabled = true
|
||||||
|
XCTAssert(mgrPrefs.chineseConversionEnabled == true)
|
||||||
|
_ = mgrPrefs.toggleChineseConversionEnabled()
|
||||||
|
XCTAssert(mgrPrefs.chineseConversionEnabled == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHalfWidthPunctuationEnabled() {
|
||||||
|
XCTAssert(mgrPrefs.halfWidthPunctuationEnabled == false)
|
||||||
|
mgrPrefs.halfWidthPunctuationEnabled = true
|
||||||
|
XCTAssert(mgrPrefs.halfWidthPunctuationEnabled == true)
|
||||||
|
_ = mgrPrefs.toggleHalfWidthPunctuationEnabled()
|
||||||
|
XCTAssert(mgrPrefs.halfWidthPunctuationEnabled == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEscToCleanInputBuffer() {
|
||||||
|
XCTAssert(mgrPrefs.escToCleanInputBuffer == true)
|
||||||
|
mgrPrefs.escToCleanInputBuffer = false
|
||||||
|
XCTAssert(mgrPrefs.escToCleanInputBuffer == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCandidateTextFontName() {
|
||||||
|
XCTAssert(mgrPrefs.candidateTextFontName == nil)
|
||||||
|
mgrPrefs.candidateTextFontName = "Helvetica"
|
||||||
|
XCTAssert(mgrPrefs.candidateTextFontName == "Helvetica")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCandidateKeyLabelFontName() {
|
||||||
|
XCTAssert(mgrPrefs.candidateKeyLabelFontName == nil)
|
||||||
|
mgrPrefs.candidateKeyLabelFontName = "Helvetica"
|
||||||
|
XCTAssert(mgrPrefs.candidateKeyLabelFontName == "Helvetica")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCandidateKeys() {
|
||||||
|
XCTAssert(mgrPrefs.candidateKeys == mgrPrefs.defaultCandidateKeys)
|
||||||
|
mgrPrefs.candidateKeys = "abcd"
|
||||||
|
XCTAssert(mgrPrefs.candidateKeys == "abcd")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPhraseReplacementEnabledKey() {
|
||||||
|
XCTAssert(mgrPrefs.phraseReplacementEnabled == false)
|
||||||
|
mgrPrefs.phraseReplacementEnabled = true
|
||||||
|
XCTAssert(mgrPrefs.phraseReplacementEnabled == true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CandidateKeyValidationTests: XCTestCase {
|
||||||
|
func testEmpty() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.empty {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSpaces() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: " ")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.empty {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInvalidKeys() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "中文字元")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.invalidCharacters {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testInvalidLatinLetters() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "üåçøöacpo")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.invalidCharacters {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSpaceInBetween() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "1 2 3 4")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.containSpace {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDuplicatedKeys() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "aabbccdd")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.duplicatedCharacters {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTooShort1() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "abc")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.tooShort {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTooShort2() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "abcd")
|
||||||
|
} catch {
|
||||||
|
XCTFail("Should be safe")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTooLong1() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "qwertyuiopasdfgh")
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
} catch mgrPrefs.CandidateKeyError.tooLong {
|
||||||
|
} catch {
|
||||||
|
XCTFail("exception not thrown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTooLong2() {
|
||||||
|
do {
|
||||||
|
try mgrPrefs.validate(candidateKeys: "qwertyuiopasdfg")
|
||||||
|
} catch {
|
||||||
|
XCTFail("Should be safe")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (c) 2021 and onwards Zonble Yang (MIT-NTL License).
|
||||||
|
// All possible vChewing-specific modifications are of:
|
||||||
|
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||||
|
/*
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
1. The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
2. No trademark license is granted to use the trade names, trademarks, service
|
||||||
|
marks, or product names of Contributor, except as required to fulfill notice
|
||||||
|
requirements above.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
@testable import vChewing
|
||||||
|
|
||||||
|
class VersionUpdateApiTests: XCTestCase {
|
||||||
|
func testFetchVersionUpdateInfo() {
|
||||||
|
let exp = expectation(description: "wait for 3 seconds")
|
||||||
|
_ = VersionUpdateApi.check(forced: true) { result in
|
||||||
|
exp.fulfill()
|
||||||
|
switch result {
|
||||||
|
case .success:
|
||||||
|
break
|
||||||
|
case .failure(let error):
|
||||||
|
XCTFail(error.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wait(for: [exp], timeout: 20.0)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue