fix(release): prepare 1.8 disclosures and licensed resources
Replace the unclear CLM source, align release and privacy disclosures, complete third-party notices, and keep the expanded test suites deterministic for release validation.
This commit is contained in:
@@ -22,8 +22,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
@MainActor
|
||||
func testChineseTypingDoesNotLoadEnglishLexicon() {
|
||||
EnglishLexicon.shared.unload()
|
||||
let typing = TypingSessionController()
|
||||
_ = typing.setLanguage(.chinese)
|
||||
let typing = makeTypingSession(language: .chinese)
|
||||
typing.enterTypingMode()
|
||||
XCTAssertFalse(EnglishLexicon.shared.isLoaded)
|
||||
_ = typing.setLanguage(.english)
|
||||
@@ -124,10 +123,10 @@ final class EnglishTypingTests: XCTestCase {
|
||||
func testEnglishShiftArmsAfterReturnLikeNotes() {
|
||||
// Simulates Notes: proxy preceding text gains a trailing newline after Return.
|
||||
var preceding = "Hello"
|
||||
let typing = TypingSessionController()
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { preceding }
|
||||
typing.autocapitalizationModeProvider = { .sentences }
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.syncAutocapitalization()
|
||||
XCTAssertFalse(typing.shiftActive, "mid-word should not arm Shift")
|
||||
|
||||
_ = typing.handleReturn()
|
||||
@@ -144,10 +143,10 @@ final class EnglishTypingTests: XCTestCase {
|
||||
func testEnglishShiftArmsWhenProxyLagsAfterReturn() {
|
||||
// Notes often still reports pre-Return context right after insertText("\n").
|
||||
var preceding = "Hello"
|
||||
let typing = TypingSessionController()
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { preceding }
|
||||
typing.autocapitalizationModeProvider = { .sentences }
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.syncAutocapitalization()
|
||||
|
||||
_ = typing.handleReturn()
|
||||
// Proxy intentionally stale — still "Hello" without "\n".
|
||||
@@ -159,10 +158,10 @@ final class EnglishTypingTests: XCTestCase {
|
||||
@MainActor
|
||||
func testEnglishShiftArmsWhenProxyLagsAfterPeriod() {
|
||||
var preceding = "Hello"
|
||||
let typing = TypingSessionController()
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { preceding }
|
||||
typing.autocapitalizationModeProvider = { .sentences }
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.syncAutocapitalization()
|
||||
|
||||
_ = typing.handleKey(".")
|
||||
typing.syncAutocapitalization(accountingForInsert: ".")
|
||||
@@ -171,9 +170,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
|
||||
@MainActor
|
||||
func testEnglishIdleShowsNoCandidatesUntilLetterTyped() {
|
||||
let typing = TypingSessionController()
|
||||
typing.suggestionsEnabled = true
|
||||
_ = typing.setLanguage(.english)
|
||||
let typing = makeTypingSession()
|
||||
typing.enterTypingMode()
|
||||
XCTAssertTrue(typing.composition.candidates.isEmpty)
|
||||
|
||||
@@ -202,9 +199,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
|
||||
@MainActor
|
||||
func testEnglishTypingEmitsCompletionsIntoComposition() {
|
||||
let typing = TypingSessionController()
|
||||
typing.suggestionsEnabled = true
|
||||
_ = typing.setLanguage(.english)
|
||||
let typing = makeTypingSession()
|
||||
typing.enterTypingMode()
|
||||
|
||||
_ = typing.handleKey("h")
|
||||
@@ -219,11 +214,9 @@ final class EnglishTypingTests: XCTestCase {
|
||||
func testOldWordBackspaceRehydratesSuggestionsFromDocumentContext() {
|
||||
var preceding = "board"
|
||||
let following = "\n"
|
||||
let typing = TypingSessionController()
|
||||
typing.suggestionsEnabled = true
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { preceding }
|
||||
typing.followingTextProvider = { following }
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.enterTypingMode()
|
||||
typing.synchronizeEnglishDocumentContext(caretMoved: true)
|
||||
|
||||
@@ -259,11 +252,9 @@ final class EnglishTypingTests: XCTestCase {
|
||||
@MainActor
|
||||
func testCandidateReplacementRejectsStaleDocumentAnchor() {
|
||||
var preceding = ""
|
||||
let typing = TypingSessionController()
|
||||
typing.suggestionsEnabled = true
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { preceding }
|
||||
typing.followingTextProvider = { "" }
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.enterTypingMode()
|
||||
|
||||
for key in ["b", "o", "a"] {
|
||||
@@ -286,11 +277,9 @@ final class EnglishTypingTests: XCTestCase {
|
||||
|
||||
@MainActor
|
||||
func testMidWordCaretSuppressesUnsafeBackwardOnlyReplacement() {
|
||||
let typing = TypingSessionController()
|
||||
typing.suggestionsEnabled = true
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { "boa" }
|
||||
typing.followingTextProvider = { "rd" }
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.enterTypingMode()
|
||||
|
||||
typing.synchronizeEnglishDocumentContext(caretMoved: true)
|
||||
@@ -302,11 +291,9 @@ final class EnglishTypingTests: XCTestCase {
|
||||
@MainActor
|
||||
func testStaleHostCallbackDoesNotDiscardLocalEnglishWord() {
|
||||
var preceding = ""
|
||||
let typing = TypingSessionController()
|
||||
typing.suggestionsEnabled = true
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { preceding }
|
||||
typing.followingTextProvider = { "" }
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.enterTypingMode()
|
||||
|
||||
let output = typing.handleKey("h")
|
||||
@@ -337,7 +324,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
|
||||
@MainActor
|
||||
func testPeriodShortcutReplacesDoubleSpace() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = makeTypingSession()
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.enterTypingMode()
|
||||
|
||||
@@ -356,7 +343,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
|
||||
@MainActor
|
||||
func testPeriodShortcutDoesNotFireAfterAnotherLetter() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = makeTypingSession()
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.enterTypingMode()
|
||||
|
||||
@@ -369,8 +356,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
|
||||
@MainActor
|
||||
func testPeriodShortcutDoesNotFireAfterSentenceTerminator() {
|
||||
let typing = TypingSessionController()
|
||||
_ = typing.setLanguage(.english)
|
||||
let typing = makeTypingSession()
|
||||
typing.precedingTextProvider = { "Hello." }
|
||||
typing.enterTypingMode()
|
||||
typing.syncAutocapitalization()
|
||||
@@ -382,8 +368,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
|
||||
@MainActor
|
||||
func testChineseSpaceDoesNotUsePeriodShortcut() {
|
||||
let typing = TypingSessionController()
|
||||
_ = typing.setLanguage(.chinese)
|
||||
let typing = makeTypingSession(language: .chinese)
|
||||
let first = typing.handleSpace()
|
||||
let second = typing.handleSpace()
|
||||
XCTAssertEqual(first.text, " ")
|
||||
@@ -526,9 +511,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defaults.removePersistentDomain(forName: suite)
|
||||
let store = EnglishLearningStore(defaults: defaults)
|
||||
let typing = TypingSessionController(learningStore: store)
|
||||
typing.suggestionsEnabled = true
|
||||
_ = typing.setLanguage(.english)
|
||||
let typing = makeTypingSession(learningStore: store)
|
||||
typing.enterTypingMode()
|
||||
|
||||
for character in ["t", "e", "h"] {
|
||||
@@ -545,9 +528,7 @@ final class EnglishTypingTests: XCTestCase {
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defaults.removePersistentDomain(forName: suite)
|
||||
let store = EnglishLearningStore(defaults: defaults)
|
||||
let typing = TypingSessionController(learningStore: store)
|
||||
typing.suggestionsEnabled = true
|
||||
_ = typing.setLanguage(.english)
|
||||
let typing = makeTypingSession(learningStore: store)
|
||||
typing.enterTypingMode()
|
||||
|
||||
for character in ["t", "e", "h"] {
|
||||
@@ -581,13 +562,28 @@ final class EnglishTypingTests: XCTestCase {
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defaults.removePersistentDomain(forName: suite)
|
||||
let store = EnglishLearningStore(defaults: defaults)
|
||||
let typing = TypingSessionController(learningStore: store)
|
||||
typing.suggestionsEnabled = true
|
||||
_ = typing.setLanguage(.english)
|
||||
let typing = makeTypingSession(learningStore: store)
|
||||
typing.enterTypingMode()
|
||||
return typing
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func makeTypingSession(
|
||||
learningStore: EnglishLearningStore? = nil,
|
||||
language: TypingInputLanguage = .english
|
||||
) -> TypingSessionController {
|
||||
let store = learningStore ?? EnglishLearningStore(
|
||||
defaults: UserDefaults(suiteName: "english.tests.\(UUID().uuidString)")!
|
||||
)
|
||||
let typing = TypingSessionController(
|
||||
engine: { NoopRimeEngine() },
|
||||
learningStore: store
|
||||
)
|
||||
typing.suggestionsEnabled = true
|
||||
_ = typing.setLanguage(language)
|
||||
return typing
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func apply(_ typing: TypingSessionController, _ output: TypingOutput) {
|
||||
typing.syncAutocapitalization(
|
||||
@@ -596,3 +592,26 @@ final class EnglishTypingTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private final class NoopRimeEngine: RimeEngineBridging {
|
||||
var composition: TypingComposition = .empty
|
||||
var isReady = true
|
||||
var schema: TypingInputSchema = .fullPinyin
|
||||
|
||||
func prepare() async throws {}
|
||||
func teardown() { composition = .empty }
|
||||
func setLanguage(_ language: TypingInputLanguage) {}
|
||||
@discardableResult
|
||||
func setSchema(_ schema: TypingInputSchema) -> Bool {
|
||||
self.schema = schema
|
||||
return true
|
||||
}
|
||||
func processCharacter(_ character: Character) -> String? { nil }
|
||||
func processBackspace() -> String? { nil }
|
||||
func processSpace() -> String? { " " }
|
||||
func processReturn() -> String? { "\n" }
|
||||
func selectCandidate(at index: Int) -> String { "" }
|
||||
func flushPreedit() -> String { "" }
|
||||
func clearComposition() { composition = .empty }
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ final class KeyboardSurfaceStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testKeyRowsFollowTypingLanguageOnNumberPage() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = TypingSessionController(engine: { TrackingStubRimeEngine() })
|
||||
typing.setPage(.numbers)
|
||||
XCTAssertEqual(typing.keyRows[1], ["-", "/", ":", ";", "(", ")", "¥", "@", "“", "”"])
|
||||
|
||||
@@ -325,7 +325,7 @@ final class KeyboardSurfaceStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testResourceRetryIsSkippedWhenNoErrorIsPending() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = TypingSessionController(engine: { TrackingStubRimeEngine() })
|
||||
XCTAssertNil(typing.lastError)
|
||||
XCTAssertFalse(typing.lastErrorNeedsHostDeployment)
|
||||
|
||||
@@ -338,7 +338,7 @@ final class KeyboardSurfaceStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testSharedCapsuleCanSelectSpecificTypingLanguage() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = TypingSessionController(engine: { TrackingStubRimeEngine() })
|
||||
XCTAssertEqual(typing.language, .chinese)
|
||||
|
||||
XCTAssertEqual(typing.setLanguage(.english), .none)
|
||||
@@ -349,7 +349,7 @@ final class KeyboardSurfaceStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testShiftStateProducesUppercaseKeyRows() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = TypingSessionController(engine: { TrackingStubRimeEngine() })
|
||||
XCTAssertFalse(typing.shiftActive)
|
||||
|
||||
_ = typing.handleKey("⇧")
|
||||
@@ -360,7 +360,7 @@ final class KeyboardSurfaceStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testManualShiftSurvivesAutocapitalizationSync() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = TypingSessionController(engine: { TrackingStubRimeEngine() })
|
||||
// Providers must be set before language switch (which syncs autocap).
|
||||
typing.precedingTextProvider = { "hello " } // mid-sentence: auto stays off
|
||||
typing.autocapitalizationModeProvider = { .sentences }
|
||||
@@ -376,7 +376,7 @@ final class KeyboardSurfaceStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testShiftHoldTypesUppercaseWithoutEnteringCapsLock() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = TypingSessionController(engine: { TrackingStubRimeEngine() })
|
||||
_ = typing.setLanguage(.english)
|
||||
typing.precedingTextProvider = { "hello " }
|
||||
typing.autocapitalizationModeProvider = { .sentences }
|
||||
@@ -396,7 +396,7 @@ final class KeyboardSurfaceStateTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testShiftHoldWithoutTypingActsAsTap() {
|
||||
let typing = TypingSessionController()
|
||||
let typing = TypingSessionController(engine: { TrackingStubRimeEngine() })
|
||||
typing.beginShiftHold()
|
||||
typing.endShiftHold()
|
||||
XCTAssertTrue(typing.shiftActive)
|
||||
|
||||
@@ -51,6 +51,7 @@ final class LibrimeIntegrationTests: XCTestCase {
|
||||
distributionVersion: "tests"
|
||||
)
|
||||
try bridge.start()
|
||||
defer { bridge.finalizeRuntime() }
|
||||
|
||||
let vectors: [(TypingInputSchema, String)] = [
|
||||
(.fullPinyin, "nihao"),
|
||||
@@ -141,40 +142,34 @@ final class LibrimeIntegrationTests: XCTestCase {
|
||||
let userFiles = fileManager.enumerator(atPath: user.path)?
|
||||
.compactMap { $0 as? String } ?? []
|
||||
XCTAssertTrue(userFiles.contains(where: { $0.contains("userdb") }))
|
||||
}
|
||||
|
||||
// Redeploy with one fuzzy pair and verify it affects actual Rime
|
||||
// candidates rather than just generated YAML.
|
||||
for schema in TypingInputSchema.allCases {
|
||||
try RimeSchemaGenerator.schema(for: schema, fuzzyPairs: [.nL]).write(
|
||||
to: shared.appendingPathComponent("\(schema.rawValue).schema.yaml"),
|
||||
atomically: true,
|
||||
encoding: .utf8
|
||||
)
|
||||
}
|
||||
let fuzzyDeployer = OSGRimeBridge(
|
||||
sharedDataDirectory: shared.path,
|
||||
userDataDirectory: user.path,
|
||||
distributionVersion: "tests-fuzzy"
|
||||
)
|
||||
try fuzzyDeployer.deploy(withFullCheck: true)
|
||||
fuzzyDeployer.finalizeRuntime()
|
||||
func testNLFuzzyMapsLihaoToNihao() throws {
|
||||
let env = try stagedRimeEnvironment(fuzzyPairs: [.nL])
|
||||
defer { try? env.fileManager.removeItem(at: env.root) }
|
||||
|
||||
let fuzzyBridge = OSGRimeBridge(
|
||||
sharedDataDirectory: shared.path,
|
||||
userDataDirectory: user.path,
|
||||
distributionVersion: "tests-fuzzy"
|
||||
let deployer = OSGRimeBridge(
|
||||
sharedDataDirectory: env.shared.path,
|
||||
userDataDirectory: env.user.path,
|
||||
distributionVersion: "tests-fuzzy-nl"
|
||||
)
|
||||
try fuzzyBridge.start()
|
||||
XCTAssertTrue(fuzzyBridge.selectSchema(TypingInputSchema.fullPinyin.rawValue))
|
||||
for scalar in "lihao".utf8 {
|
||||
XCTAssertTrue(fuzzyBridge.processKeyCode(Int32(scalar), modifiers: 0))
|
||||
}
|
||||
let fuzzySnapshot = fuzzyBridge.snapshot(withCandidateLimit: 100)
|
||||
try deployer.deploy(withFullCheck: true)
|
||||
deployer.finalizeRuntime()
|
||||
|
||||
let bridge = OSGRimeBridge(
|
||||
sharedDataDirectory: env.shared.path,
|
||||
userDataDirectory: env.user.path,
|
||||
distributionVersion: "tests-fuzzy-nl"
|
||||
)
|
||||
try bridge.start()
|
||||
defer { bridge.finalizeRuntime() }
|
||||
XCTAssertTrue(bridge.selectSchema(TypingInputSchema.fullPinyin.rawValue))
|
||||
type("lihao", on: bridge)
|
||||
let snapshot = bridge.snapshot(withCandidateLimit: 100)
|
||||
XCTAssertTrue(
|
||||
fuzzySnapshot.candidates.contains(where: { $0.text == "你好" }),
|
||||
"n/l fuzzy candidates: \(fuzzySnapshot.candidates.map(\.text).prefix(20))"
|
||||
snapshot.candidates.contains(where: { $0.text == "你好" }),
|
||||
"n/l fuzzy candidates: \(snapshot.candidates.map(\.text).prefix(20))"
|
||||
)
|
||||
fuzzyBridge.finalizeRuntime()
|
||||
}
|
||||
|
||||
func testPersonalDictionarySidecarPinsSameCodeCandidates() throws {
|
||||
@@ -541,7 +536,9 @@ final class LibrimeIntegrationTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
private func stagedRimeEnvironment() throws -> (
|
||||
private func stagedRimeEnvironment(
|
||||
fuzzyPairs: Set<PinyinFuzzyPair> = []
|
||||
) throws -> (
|
||||
root: URL,
|
||||
shared: URL,
|
||||
user: URL,
|
||||
@@ -569,7 +566,7 @@ final class LibrimeIntegrationTests: XCTestCase {
|
||||
encoding: .utf8
|
||||
)
|
||||
for schema in TypingInputSchema.allCases {
|
||||
try RimeSchemaGenerator.schema(for: schema, fuzzyPairs: []).write(
|
||||
try RimeSchemaGenerator.schema(for: schema, fuzzyPairs: fuzzyPairs).write(
|
||||
to: shared.appendingPathComponent("\(schema.rawValue).schema.yaml"),
|
||||
atomically: true,
|
||||
encoding: .utf8
|
||||
|
||||
Reference in New Issue
Block a user