spiegel-keyman/mac/KeymanSettings/Tests/KeymanSettingsTests/KeymanSettingsTests.swift
2026-07-16 13:30:53 -04:00

290 lines
13 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Keyman is copyright (C) SIL Global. MIT License.
*
* Created by Shawn Schantz on 2026-03-06
*
* Tests for KeymanSettings package
*
*/
import Testing
import Foundation
@testable import KeymanSettings
@Suite("Settings Container") struct SettingsContainersTests {
fileprivate init() async throws {
print("init")
}
@Test("Check settings creation") @MainActor func testSettingsCreation() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey, hittiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
#expect(settingsContainer.multiKeyboardPackages.isEmpty)
#expect(settingsContainer.singleKeyboardPackages.isEmpty)
settingsContainer.loadPackages()
#expect(settingsContainer.findInstalledPackage(with: packageRepo.testPackageId) != nil)
#expect(defaultsRepo.readEnabledKeyboards().contains(moabiteKeyboardKey))
}
@Test("Check finding packages by UUID") @MainActor func testFindPackage() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey, hittiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
// verify that we can find that test package and cannot find the null package
#expect(settingsContainer.findInstalledPackage(with: packageRepo.testPackageId) != nil)
#expect(settingsContainer.findInstalledPackage(with: packageRepo.nullPackageId) == nil)
}
@Test("Check remove package") @MainActor func testRemovePackage() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey, hittiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
// verify that we cannot find the test package after removing it
#expect(settingsContainer.findInstalledPackage(with: packageRepo.testPackageId) != nil)
settingsContainer.removeMultipleKeyboardPackage(at: 0)
#expect(settingsContainer.findInstalledPackage(with: packageRepo.testPackageId) == nil)
}
/**
* test whether an uninstalled keyboard is removed from the list of enabled keyboards when calling `validateSettings()`
*/
@Test("Check settings validation ") @MainActor func testSettingsValidation() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey, uninstalledKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
settingsContainer.validateUserDefaults()
let enabledKeyboards = defaultsRepo.readEnabledKeyboards()
#expect(!enabledKeyboards.contains(uninstalledKeyboardKey))
#expect(enabledKeyboards.contains(moabiteKeyboardKey))
}
/**
* test whether keyboard state changes from disabled to enabled when settings are applied
*/
@Test("Check settings applied ") @MainActor func testSettingsApplied() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey, hittiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
let package = try #require(settingsContainer.findInstalledPackage(with: packageRepo.testPackageId))
// the hittite keyboard is initialized as disabled
#expect(!package.isKeyboardEnabled(keyboardKey: hittiteKeyboardKey))
// it should be enabled after user defaults are applied
settingsContainer.applyUserDefaultsToInstalledPackages()
#expect(package.isKeyboardEnabled(keyboardKey: hittiteKeyboardKey))
}
@Test("Check get installed keyboards") @MainActor func testGetInstalledKeyboards() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey, hittiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
// verify that two keyboards are installed
#expect(settingsContainer.getInstalledKeyboardKeys().count == 2)
}
@Test("Check get enabled keyboards") @MainActor func testGetEnabledKeyboards() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
// verify that one keyboard is enabled
#expect(settingsContainer.getEnabledKeyboardKeys().count == 1)
}
@Test("Check keyboard enabled") @MainActor func testIsKeyboardEnabled() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
// verify that moabite keyboard is enabled
#expect(settingsContainer.isKeyboardEnabled(packageId: packageRepo.testPackageId, keyboardKey: moabiteKeyboardKey))
}
@Test("Check enable keyboard") @MainActor func testEnableKeyboard() async throws {
let defaultsRepo = DefaultsRepoStub(enabledKeyboards: Set([moabiteKeyboardKey]))
let packageRepo = PackageRepoStub()
let settingsContainer = SettingsContainer(defaultsRepo: defaultsRepo, packageRepo: packageRepo)
settingsContainer.loadPackages()
// verify that the hittite keyboard changes from disabled to enabled
#expect(!settingsContainer.isKeyboardEnabled(packageId: packageRepo.testPackageId, keyboardKey: hittiteKeyboardKey))
settingsContainer.setKeyboardEnabled(packageId: packageRepo.testPackageId, keyboardKey: hittiteKeyboardKey, enabled: true)
#expect(settingsContainer.isKeyboardEnabled(packageId: packageRepo.testPackageId, keyboardKey: hittiteKeyboardKey))
}
}
@Suite("Check Keyman paths") struct KeymanPathsTests {
fileprivate init() async throws {
print("init")
}
@Test("Check Keyman 17 documents directory") func testKeyman17DocumentsDirectory() async throws {
let documentsDirectory = try #require(KeymanPaths().keyman17DocumentsDirectory)
#expect(documentsDirectory.absoluteString.hasSuffix("Documents/"))
}
@Test("Check Keyman 17 packages directory") func testKeyman17KeyboardsDirectory() async throws {
#expect(true)
let keyboardsDirectory = try #require(KeymanPaths().keyman17PackagesDirectory)
#expect(keyboardsDirectory.absoluteString.hasSuffix("Documents/Keyman-Keyboards/"))
}
@Test("Check Keyman 18 support directory") func testKeyman18SupportDirectory() async throws {
#expect(true)
let supportDirectory = try #require(KeymanPaths().keyman18SupportDirectory)
#expect(supportDirectory.absoluteString.hasSuffix("Library/Application%20Support/"))
}
@Test("Check Keyman 18 data directory") func testKeyman18SupportKeymanDirectory() async throws {
#expect(true)
let supportDirectory = try #require(KeymanPaths().keyman18DataDirectory)
#expect(supportDirectory.absoluteString.hasSuffix("Library/Application%20Support/keyman.inputmethod.Keyman/"))
}
@Test("Check Keyman 18 packages directory") func testKeyman18SupportKeyboardsDirectory() async throws {
#expect(true)
let keyboardsDirectory = try #require(KeymanPaths().keyman18PackagesDirectory)
#expect(keyboardsDirectory.absoluteString.hasSuffix("Library/Application%20Support/keyman.inputmethod.Keyman/Keyman-Keyboards/"))
}
@Test("Check Keyman 19 container data directory") func testKeyman19ContainerDataDirectory() async throws {
#expect(true)
let containerDirectory = try KeymanPaths().keyman19ContainerDirectory
#expect(containerDirectory.absoluteString.hasSuffix("Group%20Containers/group.com.keyman/"))
}
@Test("Check Keyman 19 packages directory") func testKeyman19KeyboardsDirectory() async throws {
#expect(true)
let keyboardsDirectory = try KeymanPaths().keyman19PackagesDirectory
#expect(keyboardsDirectory.absoluteString.hasSuffix("Group%20Containers/group.com.keyman/Library/Application%20Support/Keyman-Packages/"))
}
}
// defaults read test.suite.name
@Suite("UserDefaults check") struct KeymanSettingsRepositoryTests {
var settingsRepo: DefaultsRepo
let hittiteKeyboardKey = "/sil_extinct/hittite.kmx"
let moabiteKeyboardKey = "/sil_extinct/moabite.kmx"
fileprivate init() async throws {
print("init Settings")
do {
try self.settingsRepo = DefaultsRepository(suiteName: "test.suite.name")
} catch UserDefaultsError.unknownSuite {
fatalError("Cannot access UserDefaults suite.")
} catch {
fatalError("Cannot access UserDefaults suite.")
}
}
@Test("Write and read selected keyboard") func writeSelectedKeyboard() async throws {
settingsRepo.writeSelectedKeyboard(keyboardName: moabiteKeyboardKey)
#expect(settingsRepo.readSelectedKeyboard() == moabiteKeyboardKey)
}
@Test("Write and read enabled keyboards") func writeEnabledKeyboards() async throws {
settingsRepo.writeEnabledKeyboards(enabledKeyboardsArray: [hittiteKeyboardKey, moabiteKeyboardKey])
#expect(settingsRepo.readEnabledKeyboards().count == 2)
#expect(settingsRepo.readEnabledKeyboards().contains(hittiteKeyboardKey))
#expect(settingsRepo.readEnabledKeyboards().contains(moabiteKeyboardKey))
}
}
@Suite("Read Keyman package") struct KeymanPackageRepositoryTests {
let packageRepo: PackageRepository
let kmpUrl: URL
let source: PackageSource?
let fakePackageUrl: URL = URL(fileURLWithPath: "/fake/test/destination/amharic-fake")
fileprivate init() async throws {
try packageRepo = PackageRepository()
self.kmpUrl = try #require(Bundle.module.url(forResource: "amharic.kmp", withExtension: "json"))
source = try packageRepo.readPackage(packageDirectoryUrl: fakePackageUrl, kmpFileUrl: self.kmpUrl)
}
@Test("Read package name") func readPackageName() async throws {
let packageSource = try #require(source)
#expect(packageSource.packageName == "GFF Amharic Keyboard")
}
@Test("Read package version") func readPackageVersion() async throws {
let packageSource = try #require(source)
#expect(packageSource.packageVersion == "3.1.2")
}
@Test("Read copyright") func readCopyright() async throws {
let packageSource = try #require(source)
#expect(packageSource.copyright == "© Geʾez Frontier Foundation, SIL International")
}
@Test("Read keyboard count") func readKeyboardCount() async throws {
let packageSource = try #require(source)
#expect(packageSource.keyboards?.count == 1)
}
@Test("Read keyboard name") func readKeyboardName() async throws {
let packageSource = try #require(source)
let keyboard = try #require(packageSource.keyboards?.first)
#expect(keyboard.name == "አማርኛ (Amharic)")
}
/**
* Ensure that Keyboard objects are correctly created from Keyboardsource
*/
@Suite("Check keyboard state") struct KeyboardStateTests {
let packageRepo: PackageRepository
let kmpUrl: URL
let packageSource: PackageSource?
let fakePackageUrl: URL = URL(fileURLWithPath: "/fake/test/destination/amharic-fake")
fileprivate init() async throws {
try packageRepo = PackageRepository()
self.kmpUrl = try #require(Bundle.module.url(forResource: "amharic.kmp", withExtension: "json"))
self.packageSource = try packageRepo.readPackage(packageDirectoryUrl: fakePackageUrl, kmpFileUrl: self.kmpUrl)
}
@Test("Check keyboard is disabled") func checkKeyboardDisabled() async throws {
let package = try #require(self.packageSource)
let directoryUrl = try #require(package.directoryUrl)
let keyboards = try #require(package.keyboards)
let keyboardSource = try #require(keyboards.first)
let keyboard = Keyboard(keyboardSource: keyboardSource, directoryUrl: directoryUrl)
#expect(keyboard.enabled)
}
@Test("Check keyboard key") func checkKeyboardKey() async throws {
let package = try #require(self.packageSource)
let directoryUrl = try #require(package.directoryUrl)
let keyboards = try #require(package.keyboards)
let keyboardSource = try #require(keyboards.first)
let keyboard = Keyboard(keyboardSource: keyboardSource, directoryUrl: directoryUrl)
#expect(keyboard.keyboardKey == "/amharic-fake/gff_amharic.kmx")
}
}
}