mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 04:09:17 +00:00
fix: the locale runtime the card ships is the code the tests prove (#354)
The production LANGUAGE_RUNTIME was a handwritten twin of the tested LanguageRuntime class (germanDictionary/Pending/Failed): equivalent on the day it was written, invisible to every i18n-runtime test afterwards. The registry now exports one page-scoped `new LanguageRuntime(LANGUAGE_REGISTRY, …)` instance — the whole existing suite starts proving the object production actually runs, and a contract unit (instanceof + source free of the old field names) keeps the duplicate from returning. The class gains an optional `loadFailed(code)` hook — fired once when a dictionary load settles into English fallback — and the registry fans it out through `subscribeLanguageLoadFailures`. Only the View card subscribes (it alone owns toast infrastructure): a failed language pack now shows the new `toast.locale_load_failed` message (en/ru/de) instead of a console-only warning; space card and both GUI editors keep the console warning as before. Proofs: contract unit, hook unit, subscription unit; smoke_german_locale extended — the both-attempts-failed scenario now asserts the visible toast; two new registry mutants (handwritten-twin returns, toast dropped). Issue: #354 User-Visible: yes
This commit is contained in:
@@ -634,6 +634,45 @@ const MUTANT_DEFINITIONS = [
|
||||
replace: ' // mutant: pointer capture removed\n const plan = resolution.plan;',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'language-runtime-handwritten-duplicate',
|
||||
guard: 'node --test --test-name-pattern="#354" test/i18n-runtime.test.mjs',
|
||||
because: 'a handwritten twin of LanguageRuntime looks equivalent today and rots tomorrow — '
|
||||
+ 'the i18n suite must prove the object production actually runs (#354 К1/К3)',
|
||||
patches: [{
|
||||
file: 'src/i18n/registry.ts',
|
||||
find: 'export const LANGUAGE_RUNTIME: LanguageRuntimeContract = new LanguageRuntime(\n'
|
||||
+ ' LANGUAGE_REGISTRY,\n'
|
||||
+ ' BUILD_FINGERPRINT,\n'
|
||||
+ ' console.warn,\n'
|
||||
+ ' (code) => {\n'
|
||||
+ ' for (const listener of languageLoadFailureListeners) listener(code);\n'
|
||||
+ ' },\n'
|
||||
+ ');',
|
||||
replace: 'const twin = new LanguageRuntime(LANGUAGE_REGISTRY, BUILD_FINGERPRINT, '
|
||||
+ 'console.warn, (code) => {\n'
|
||||
+ ' for (const listener of languageLoadFailureListeners) listener(code);\n'
|
||||
+ '});\n'
|
||||
+ 'export const LANGUAGE_RUNTIME: LanguageRuntimeContract = {\n'
|
||||
+ ' state: (code) => twin.state(code),\n'
|
||||
+ ' dictionary: (code) => twin.dictionary(code),\n'
|
||||
+ ' ensure: (code) => twin.ensure(code),\n'
|
||||
+ '};',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'locale-failure-toast-dropped',
|
||||
guard: 'node demo/smoke_german_locale.mjs',
|
||||
because: 'a failed dictionary must be visible on the View card, not only a console line — '
|
||||
+ 'a German user on a stale tab silently reading English is the N7 hole (#354 К2)',
|
||||
patches: [{
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: " this._languageFailureUnsub = subscribeLanguageLoadFailures(() => {\n"
|
||||
+ " this._showToast(this._t('toast.locale_load_failed'));\n"
|
||||
+ ' });',
|
||||
replace: ' this._languageFailureUnsub = undefined;',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'lazy-loader-network-failure-terminal',
|
||||
guard: 'node --test --test-name-pattern="#353 AC1" test/editor-runtime-loader.test.mjs',
|
||||
|
||||
Reference in New Issue
Block a user