mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Node >= 21 exposes a global `navigator` reporting the machine's own language,
so gating detection on `navigator` let a non-browser boot of the client tree
resolve to `en` instead of the documented fallback; `window` is the browser
test. `navigator.languages` is spec-required but absent on some embedders and
older WebViews, where spreading it would throw at boot, so the walk tolerates
its absence and `navigator.language` covers that host.
The per-spec pin boilerplate collapses into one suite-level
`usePinnedBrowserLanguages('zh-CN')`, which owns the rationale in
dsh-client-test-runtime, and the English-browser e2e scenario now clears the
console warnings channel too — its page has no closing inventory spec.
30 lines
1.3 KiB
TypeScript
30 lines
1.3 KiB
TypeScript
/**
|
|
* Browser-language pin for specs that assert localized copy. A fresh
|
|
* LocaleService with no stored preference opens in the language `navigator`
|
|
* asks for, and jsdom reports the runner's own (`en-US`) — so a spec asserting
|
|
* the product's Chinese copy states the browser it assumes instead of
|
|
* inheriting the machine's.
|
|
*/
|
|
import { afterEach, beforeEach } from 'vitest'
|
|
|
|
/**
|
|
* Pin `navigator.languages`/`navigator.language` for every test in the
|
|
* calling file (or describe block), restoring the environment's own values
|
|
* afterwards. Call at suite level, like the other vitest hooks.
|
|
* @param primary - most preferred BCP 47 tag; also becomes `navigator.language`.
|
|
* @param rest - further tags in preference order.
|
|
*/
|
|
export function usePinnedBrowserLanguages(primary: string, ...rest: string[]): void {
|
|
beforeEach(() => {
|
|
Object.defineProperty(navigator, 'languages', { value: [primary, ...rest], configurable: true })
|
|
Object.defineProperty(navigator, 'language', { value: primary, configurable: true })
|
|
})
|
|
afterEach(() => {
|
|
// Deleting the own properties uncovers the environment's own accessors
|
|
// again (Navigator declares both readonly, hence the erased receiver).
|
|
const own = navigator as unknown as Record<string, unknown>
|
|
delete own.languages
|
|
delete own.language
|
|
})
|
|
}
|