Files
OSGKeyboard/OSGKeyboardExtTests/RimeSchemaGeneratorTests.swift
T
Rocky 498f407585 feat(account): add managed credits and cloud gateway
Introduce optional Apple account-backed credits with scoped gateway access while preserving local and BYOK paths. Refresh assistant behavior, tests, privacy disclosures, docs, and the website for the 2.0 experience.
2026-08-20 11:43:21 +08:00

194 lines
7.8 KiB
Swift

// RimeSchemaGeneratorTests.swift
// OSGKeyboard · Ext unit tests
@testable import OSGKeyboardShared
import XCTest
final class RimeSchemaGeneratorTests: XCTestCase {
func testFuzzyRulesDefaultToOff() {
XCTAssertTrue(RimeSchemaGenerator.fuzzyRules([]).isEmpty)
}
func testFuzzyRulesAreOptInAndSymmetric() {
let rules = RimeSchemaGenerator.fuzzyRules([.nL, .anAng])
XCTAssertTrue(rules.contains("derive/^n/l/"))
XCTAssertTrue(rules.contains("derive/^l/n/"))
XCTAssertTrue(rules.contains("derive/ang$/an/"))
XCTAssertTrue(rules.contains("derive/an$/ang/"))
XCTAssertFalse(rules.contains { $0.contains("eng") })
}
func testMicrosoftAndSogouExposeIngSemicolonMapping() {
for schema in [
TypingInputSchema.microsoftDoublePinyin,
TypingInputSchema.sogouDoublePinyin
] {
let yaml = RimeSchemaGenerator.schema(for: schema, fuzzyPairs: [])
XCTAssertTrue(yaml.contains("xform/ing$/;/"))
XCTAssertTrue(yaml.contains("xform/^sh/U/"))
XCTAssertTrue(yaml.contains("xform/^ch/I/"))
XCTAssertTrue(yaml.contains("xform/^zh/V/"))
}
}
func testFuzzyRulesPrecedeDoublePinyinTransforms() throws {
let yaml = RimeSchemaGenerator.schema(
for: .microsoftDoublePinyin,
fuzzyPairs: [.nL]
)
let fuzzy = try XCTUnwrap(yaml.range(of: "derive/^n/l/"))
let transform = try XCTUnwrap(yaml.range(of: "xform/iu$/Q/"))
XCTAssertLessThan(fuzzy.lowerBound, transform.lowerBound)
}
func testDialectErasePrecedesFuzzyAndAbbrev() throws {
let yaml = RimeSchemaGenerator.schema(for: .fullPinyin, fuzzyPairs: [.nL])
let eraseN = try XCTUnwrap(yaml.range(of: "erase/^n$/"))
let fuzzy = try XCTUnwrap(yaml.range(of: "derive/^n/l/"))
let abbrev = try XCTUnwrap(yaml.range(of: "abbrev/^([a-z]).+$/$1/"))
XCTAssertLessThan(eraseN.lowerBound, fuzzy.lowerBound)
XCTAssertLessThan(fuzzy.lowerBound, abbrev.lowerBound)
}
func testAllSchemasEraseDialectSyllables() {
for schema in TypingInputSchema.allCases {
let yaml = RimeSchemaGenerator.schema(for: schema, fuzzyPairs: [])
XCTAssertTrue(yaml.contains("erase/^hm$/"), schema.rawValue)
XCTAssertTrue(yaml.contains("erase/^m$/"), schema.rawValue)
XCTAssertTrue(yaml.contains("erase/^n$/"), schema.rawValue)
XCTAssertTrue(yaml.contains("erase/^ng$/"), schema.rawValue)
}
}
func testZhAbbrevIsFullPinyinOnly() {
let full = RimeSchemaGenerator.schema(for: .fullPinyin, fuzzyPairs: [])
XCTAssertTrue(full.contains("abbrev/^([zcs]h).+$/$1/"))
for schema in [TypingInputSchema.microsoftDoublePinyin, .sogouDoublePinyin] {
let yaml = RimeSchemaGenerator.schema(for: schema, fuzzyPairs: [])
XCTAssertFalse(
yaml.contains("abbrev/^([zcs]h).+$/$1/"),
schema.rawValue
)
}
}
@MainActor
func testTypingConfigurationDefaultsToFullPinyinWithoutFuzzyPairs() {
let suiteName = "TypingInputConfigurationTests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defer { defaults.removePersistentDomain(forName: suiteName) }
let configuration = TypingInputConfiguration(defaults: defaults)
XCTAssertEqual(configuration.schema, .fullPinyin)
XCTAssertTrue(configuration.fuzzyPairs.isEmpty)
XCTAssertEqual(configuration.defaultInputMode, .voice)
XCTAssertFalse(configuration.rememberLastSurface)
}
@MainActor
func testDefaultInputModePersistsAndDefaultsToVoice() {
let suiteName = "TypingInputConfigurationTests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defer { defaults.removePersistentDomain(forName: suiteName) }
XCTAssertFalse(TypingInputConfiguration.prefersTypingOnOpen(defaults: defaults))
XCTAssertEqual(
TypingInputConfiguration.preferredSurfaceOnOpen(defaults: defaults),
.voice
)
XCTAssertNil(TypingInputConfiguration.preferredTypingLanguageOnOpen(defaults: defaults))
let configuration = TypingInputConfiguration(defaults: defaults)
configuration.defaultInputMode = .pinyin
XCTAssertTrue(TypingInputConfiguration.prefersTypingOnOpen(defaults: defaults))
XCTAssertEqual(TypingInputConfiguration(defaults: defaults).defaultInputMode, .pinyin)
XCTAssertEqual(
TypingInputConfiguration.preferredOpenPreference(defaults: defaults).surface,
.typing
)
XCTAssertEqual(
TypingInputConfiguration.preferredOpenPreference(defaults: defaults).typingLanguage,
.chinese
)
configuration.defaultInputMode = .english
XCTAssertEqual(
TypingInputConfiguration.preferredOpenPreference(defaults: defaults).typingLanguage,
.english
)
}
@MainActor
func testLegacyDefaultToTypingMigratesToPinyin() {
let suiteName = "TypingInputConfigurationTests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defer { defaults.removePersistentDomain(forName: suiteName) }
defaults.set(true, forKey: "typing.input.defaultToTyping")
let configuration = TypingInputConfiguration(defaults: defaults)
XCTAssertEqual(configuration.defaultInputMode, .pinyin)
XCTAssertEqual(
TypingInputConfiguration.preferredSurfaceOnOpen(defaults: defaults),
.typing
)
}
@MainActor
func testRememberLastSurfaceOverridesDefaultInputMode() {
let suiteName = "TypingInputConfigurationTests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defer { defaults.removePersistentDomain(forName: suiteName) }
let configuration = TypingInputConfiguration(defaults: defaults)
configuration.defaultInputMode = .pinyin
configuration.rememberLastSurface = true
TypingInputConfiguration.persistLastSurface(.voice, defaults: defaults)
XCTAssertEqual(
TypingInputConfiguration.preferredSurfaceOnOpen(defaults: defaults),
.voice
)
TypingInputConfiguration.persistLastSurface(.typing, defaults: defaults)
TypingInputConfiguration.persistLastTypingLanguage(.english, defaults: defaults)
let preference = TypingInputConfiguration.preferredOpenPreference(defaults: defaults)
XCTAssertEqual(preference.surface, .typing)
XCTAssertEqual(preference.typingLanguage, .english)
}
@MainActor
func testRememberLastSurfaceFallsBackWhenNothingPersisted() {
let suiteName = "TypingInputConfigurationTests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defer { defaults.removePersistentDomain(forName: suiteName) }
let configuration = TypingInputConfiguration(defaults: defaults)
configuration.defaultInputMode = .pinyin
configuration.rememberLastSurface = true
XCTAssertEqual(
TypingInputConfiguration.preferredSurfaceOnOpen(defaults: defaults),
.typing
)
XCTAssertEqual(
TypingInputConfiguration.preferredTypingLanguageOnOpen(defaults: defaults),
.chinese
)
}
@MainActor
func testLegacyAISurfaceMigratesToUnifiedAssistant() {
let suiteName = "TypingInputConfigurationTests.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suiteName)!
defer { defaults.removePersistentDomain(forName: suiteName) }
TypingInputConfiguration.persistLastSurface(.ai, defaults: defaults)
XCTAssertEqual(
TypingInputConfiguration.preferredSurfaceOnOpen(defaults: defaults),
.voice
)
}
}