Repo // Make UserDefaults unit-testable.
This commit is contained in:
parent
c5c99894a9
commit
3a8060bf88
|
@ -81,8 +81,8 @@ open class CtlCandidate: NSWindowController, CtlCandidateProtocol {
|
|||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
open var candidateFont = NSFont.systemFont(
|
||||
ofSize: min(196, max(12, Double(UserDefaults.standard.integer(forKey: "CandidateListTextSize"))))
|
||||
open var candidateFont: NSFont = NSFont.systemFont(
|
||||
ofSize: min(196, max(12, Double(UserDefaults.current.integer(forKey: "CandidateListTextSize"))))
|
||||
)
|
||||
|
||||
@discardableResult open func showNextLine() -> Bool {
|
||||
|
|
|
@ -133,7 +133,7 @@ public extension NSApplication {
|
|||
let appearanceDescription = NSApp.effectiveAppearance.debugDescription
|
||||
.lowercased()
|
||||
return appearanceDescription.contains("dark")
|
||||
} else if let appleInterfaceStyle = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") {
|
||||
} else if let appleInterfaceStyle = UserDefaults.current.string(forKey: "AppleInterfaceStyle") {
|
||||
return appleInterfaceStyle.lowercased().contains("dark")
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -49,14 +49,6 @@ public enum IMKHelper {
|
|||
"org.unknown.keylayout.vChewingMiTAC",
|
||||
]
|
||||
|
||||
public static var currentBasicKeyboardLayout: String {
|
||||
UserDefaults.standard.string(forKey: "BasicKeyboardLayout") ?? ""
|
||||
}
|
||||
|
||||
public static var isDynamicBasicKeyboardLayoutEnabled: Bool {
|
||||
Self.arrDynamicBasicKeyLayouts.contains(currentBasicKeyboardLayout) || !currentBasicKeyboardLayout.isEmpty
|
||||
}
|
||||
|
||||
public static var allowedAlphanumericalTISInputSources: [TISInputSource] {
|
||||
arrWhitelistedKeyLayoutsASCII.compactMap { TISInputSource.generate(from: $0) }
|
||||
}
|
||||
|
|
|
@ -230,22 +230,22 @@ public extension LMMgr {
|
|||
{
|
||||
return userDictPathDefault
|
||||
}
|
||||
if UserDefaults.standard.object(forKey: UserDef.kUserDataFolderSpecified.rawValue) != nil {
|
||||
if UserDefaults.current.object(forKey: UserDef.kUserDataFolderSpecified.rawValue) != nil {
|
||||
BookmarkManager.shared.loadBookmarks()
|
||||
if Self.checkIfSpecifiedUserDataFolderValid(userDictPathSpecified) {
|
||||
return userDictPathSpecified
|
||||
}
|
||||
UserDefaults.standard.removeObject(forKey: UserDef.kUserDataFolderSpecified.rawValue)
|
||||
UserDefaults.current.removeObject(forKey: UserDef.kUserDataFolderSpecified.rawValue)
|
||||
}
|
||||
return userDictPathDefault
|
||||
}
|
||||
|
||||
static func cassettePath() -> String {
|
||||
let rawCassettePath = PrefMgr.shared.cassettePath
|
||||
if UserDefaults.standard.object(forKey: UserDef.kCassettePath.rawValue) != nil {
|
||||
if UserDefaults.current.object(forKey: UserDef.kCassettePath.rawValue) != nil {
|
||||
BookmarkManager.shared.loadBookmarks()
|
||||
if Self.checkCassettePathValidity(rawCassettePath) { return rawCassettePath }
|
||||
UserDefaults.standard.removeObject(forKey: UserDef.kCassettePath.rawValue)
|
||||
UserDefaults.current.removeObject(forKey: UserDef.kCassettePath.rawValue)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -253,12 +253,12 @@ public extension LMMgr {
|
|||
// MARK: - 重設使用者語彙檔案目錄
|
||||
|
||||
static func resetSpecifiedUserDataFolder() {
|
||||
UserDefaults.standard.set(dataFolderPath(isDefaultFolder: true), forKey: UserDef.kUserDataFolderSpecified.rawValue)
|
||||
UserDefaults.current.set(dataFolderPath(isDefaultFolder: true), forKey: UserDef.kUserDataFolderSpecified.rawValue)
|
||||
Self.initUserLangModels()
|
||||
}
|
||||
|
||||
static func resetCassettePath() {
|
||||
UserDefaults.standard.set("", forKey: UserDef.kCassettePath.rawValue)
|
||||
UserDefaults.current.set("", forKey: UserDef.kCassettePath.rawValue)
|
||||
Self.loadCassetteData()
|
||||
}
|
||||
|
||||
|
|
|
@ -236,11 +236,11 @@ public class PrefMgr: PrefMgrProtocol {
|
|||
// 康熙轉換與 JIS 轉換不能同時開啟,否則會出現某些奇奇怪怪的情況
|
||||
if chineseConversionEnabled, shiftJISShinjitaiOutputEnabled {
|
||||
shiftJISShinjitaiOutputEnabled.toggle()
|
||||
UserDefaults.standard.set(
|
||||
UserDefaults.current.set(
|
||||
shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled.rawValue
|
||||
)
|
||||
}
|
||||
UserDefaults.standard.set(
|
||||
UserDefaults.current.set(
|
||||
chineseConversionEnabled, forKey: UserDef.kChineseConversionEnabled.rawValue
|
||||
)
|
||||
}
|
||||
|
@ -252,11 +252,11 @@ public class PrefMgr: PrefMgrProtocol {
|
|||
// 康熙轉換與 JIS 轉換不能同時開啟,否則會出現某些奇奇怪怪的情況
|
||||
if shiftJISShinjitaiOutputEnabled, chineseConversionEnabled {
|
||||
chineseConversionEnabled.toggle()
|
||||
UserDefaults.standard.set(
|
||||
UserDefaults.current.set(
|
||||
chineseConversionEnabled, forKey: UserDef.kChineseConversionEnabled.rawValue
|
||||
)
|
||||
}
|
||||
UserDefaults.standard.set(
|
||||
UserDefaults.current.set(
|
||||
shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled.rawValue
|
||||
)
|
||||
}
|
||||
|
|
|
@ -25,15 +25,15 @@ public extension PrefMgr {
|
|||
showNotificationsWhenTogglingCapsLock = false
|
||||
}
|
||||
if appleLanguages.isEmpty {
|
||||
UserDefaults.standard.removeObject(forKey: UserDef.kAppleLanguages.rawValue)
|
||||
UserDefaults.current.removeObject(forKey: UserDef.kAppleLanguages.rawValue)
|
||||
}
|
||||
// 自動糾正選字鍵 (利用其 didSet 特性)
|
||||
candidateKeys = candidateKeys
|
||||
// 客體黑名單資料類型升級。
|
||||
if let clients = UserDefaults.standard.object(
|
||||
if let clients = UserDefaults.current.object(
|
||||
forKey: UserDef.kClientsIMKTextInputIncapable.rawValue
|
||||
) as? [String] {
|
||||
UserDefaults.standard.removeObject(forKey: UserDef.kClientsIMKTextInputIncapable.rawValue)
|
||||
UserDefaults.current.removeObject(forKey: UserDef.kClientsIMKTextInputIncapable.rawValue)
|
||||
clients.forEach { neta in
|
||||
guard !clientsIMKTextInputIncapable.keys.contains(neta) else { return }
|
||||
clientsIMKTextInputIncapable[neta] = true
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
import XCTest
|
||||
|
||||
final class MainAssemblyTests: XCTestCase {
|
||||
func testExample() throws {
|
||||
override func setUpWithError() throws {
|
||||
UserDefaults.unitTests = .init(suiteName: "org.atelierInmu.vChewing.MainAssembly.UnitTests")
|
||||
UserDefaults.pendingUnitTests = true
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
UserDefaults.unitTests?.removeSuite(named: "org.atelierInmu.vChewing.MainAssembly.UnitTests")
|
||||
}
|
||||
|
||||
func testExample() throws {}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import SwiftUI
|
|||
import SwiftUIBackports
|
||||
|
||||
private let loc: String =
|
||||
(UserDefaults.standard.array(forKey: UserDef.kAppleLanguages.rawValue) as? [String] ?? ["auto"])[0]
|
||||
(UserDefaults.current.array(forKey: UserDef.kAppleLanguages.rawValue) as? [String] ?? ["auto"])[0]
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
extension VwrPhraseEditorUI {
|
||||
|
@ -31,7 +31,7 @@ public struct VwrPhraseEditorUI: View {
|
|||
)
|
||||
@Binding public var txtContent: String
|
||||
@ObservedObject public var fileChangeIndicator = FileObserveProject.shared
|
||||
@State private var selAutoReloadExternalModifications: Bool = UserDefaults.standard.bool(
|
||||
@State private var selAutoReloadExternalModifications: Bool = UserDefaults.current.bool(
|
||||
forKey: UserDef.kPhraseEditorAutoReloadExternalModifications.rawValue)
|
||||
@State var lblAddPhraseTag1 = PETerms.AddPhrases.locPhrase.localized.0
|
||||
@State var lblAddPhraseTag2 = PETerms.AddPhrases.locReadingOrStroke.localized.0
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// (c) 2022 and onwards The vChewing Project (MIT-NTL License).
|
||||
// ====================
|
||||
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||
// ... with NTL restriction stating that:
|
||||
// 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 defined in MIT License.
|
||||
|
||||
import AppKit
|
||||
import IMKUtils
|
||||
|
||||
// MARK: - IMKHelper Extension
|
||||
|
||||
public extension IMKHelper {
|
||||
static var currentBasicKeyboardLayout: String {
|
||||
UserDefaults.current.string(forKey: "BasicKeyboardLayout") ?? ""
|
||||
}
|
||||
|
||||
static var isDynamicBasicKeyboardLayoutEnabled: Bool {
|
||||
Self.arrDynamicBasicKeyLayouts.contains(currentBasicKeyboardLayout) || !currentBasicKeyboardLayout.isEmpty
|
||||
}
|
||||
}
|
|
@ -98,7 +98,7 @@ public enum UserDef: String, CaseIterable {
|
|||
|
||||
public static func resetAll() {
|
||||
UserDef.allCases.forEach {
|
||||
UserDefaults.standard.removeObject(forKey: $0.rawValue)
|
||||
UserDefaults.current.removeObject(forKey: $0.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ public enum UserDef: String, CaseIterable {
|
|||
let data = snapshot.data
|
||||
guard !data.isEmpty else { return }
|
||||
UserDef.allCases.forEach {
|
||||
UserDefaults.standard.set(data[$0.rawValue], forKey: $0.rawValue)
|
||||
UserDefaults.current.set(data[$0.rawValue], forKey: $0.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ public enum UserDef: String, CaseIterable {
|
|||
public var data: [String: Any] = [:]
|
||||
public init() {
|
||||
UserDef.allCases.forEach {
|
||||
data[$0.rawValue] = UserDefaults.standard.object(forKey: $0.rawValue)
|
||||
data[$0.rawValue] = UserDefaults.current.object(forKey: $0.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ public enum CandidateKey {
|
|||
}
|
||||
|
||||
public func vCLog(_ strPrint: StringLiteralType) {
|
||||
if UserDefaults.standard.bool(forKey: "_DebugMode") {
|
||||
if UserDefaults.current.bool(forKey: "_DebugMode") {
|
||||
NSLog("vChewingDebug: %@", strPrint)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,19 @@ public extension Bool {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - User Defaults Storage
|
||||
|
||||
public extension UserDefaults {
|
||||
// 內部標記,看輸入法是否處於測試模式。
|
||||
static var pendingUnitTests = false
|
||||
|
||||
static var unitTests = UserDefaults(suiteName: "UnitTests")
|
||||
|
||||
static var current: UserDefaults {
|
||||
pendingUnitTests ? .unitTests ?? .standard : .standard
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Property Wrapper
|
||||
|
||||
// Ref: https://www.avanderlee.com/swift/property-wrappers/
|
||||
|
@ -127,7 +140,7 @@ public extension Bool {
|
|||
public struct AppProperty<Value> {
|
||||
public let key: String
|
||||
public let defaultValue: Value
|
||||
public var container: UserDefaults = .standard
|
||||
public var container: UserDefaults { .current }
|
||||
public init(key: String, defaultValue: Value) {
|
||||
self.key = key
|
||||
self.defaultValue = defaultValue
|
||||
|
|
Loading…
Reference in New Issue