Skip to content

Commit 9386833

Browse files
committed
refactor: add func getNlsConfiguration & tests
This PR refactors part of vscode.ts and adds a function to get the NLS Configuration. This makes the code more readable and easier to test. And it adds multiple tests for this part of the codebase.
1 parent aa08f84 commit 9386833

File tree

2 files changed

+128
-4
lines changed

2 files changed

+128
-4
lines changed

src/browser/pages/vscode.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,54 @@ const options = getOptions()
55
// TODO: Add proper types.
66
/* eslint-disable @typescript-eslint/no-explicit-any */
77

8-
let nlsConfig: any
8+
export const nlsConfigElementId = "vscode-remote-nls-configuration"
9+
10+
type NlsConfiguration = {
11+
locale: string
12+
availableLanguages: { [key: string]: string } | {}
13+
_languagePackId?: string
14+
_translationsConfigFile?: string
15+
_cacheRoot?: string
16+
_resolvedLanguagePackCoreLocation?: string
17+
_corruptedFile?: string
18+
_languagePackSupport?: boolean
19+
loadBundle?: any
20+
}
21+
22+
/**
23+
* A helper function to get the NLS Configuration settings.
24+
*
25+
* This is used by VSCode for localizations (i.e. changing
26+
* the display language).
27+
**/
28+
export function getNlsConfiguration(document: Document) {
29+
const nlsConfigElement = document?.getElementById(nlsConfigElementId)
30+
const nlsConfig = nlsConfigElement?.getAttribute("data-settings")
31+
32+
if (!document || !nlsConfigElement || !nlsConfig) {
33+
return undefined
34+
}
35+
36+
try {
37+
return JSON.parse(nlsConfig) as NlsConfiguration
38+
} catch (error) {
39+
console.error("[vscode] Failed to read or parse the NLS configuration.", error)
40+
return undefined
41+
}
42+
}
43+
44+
let nlsConfig: NlsConfiguration | undefined
945
try {
10-
nlsConfig = JSON.parse(document.getElementById("vscode-remote-nls-configuration")!.getAttribute("data-settings")!)
11-
if (nlsConfig._resolvedLanguagePackCoreLocation) {
46+
nlsConfig = getNlsConfiguration(document)
47+
if (nlsConfig?._resolvedLanguagePackCoreLocation) {
1248
const bundles = Object.create(null)
1349
nlsConfig.loadBundle = (bundle: any, _language: any, cb: any): void => {
1450
const result = bundles[bundle]
1551
if (result) {
1652
return cb(undefined, result)
1753
}
1854
// FIXME: Only works if path separators are /.
19-
const path = nlsConfig._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
55+
const path = nlsConfig?._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
2056
fetch(`${options.base}/vscode/resource/?path=${encodeURIComponent(path)}`)
2157
.then((response) => response.json())
2258
.then((json) => {

test/unit/browser/vscode.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* @jest-environment jsdom
3+
*/
4+
import { JSDOM } from "jsdom"
5+
import { getNlsConfiguration, nlsConfigElementId } from "../../../src/browser/pages/vscode"
6+
import { createLoggerMock } from "../../utils/helpers"
7+
8+
describe("vscode", () => {
9+
describe("getNlsConfiguration", () => {
10+
const loggerModule = createLoggerMock()
11+
beforeEach(() => {
12+
jest.clearAllMocks()
13+
jest.mock("@coder/logger", () => loggerModule)
14+
const { window } = new JSDOM()
15+
global.window = window as unknown as Window & typeof globalThis
16+
global.document = window.document
17+
global.navigator = window.navigator
18+
global.location = window.location
19+
})
20+
21+
afterAll(() => {
22+
jest.restoreAllMocks()
23+
})
24+
25+
it("should return undefined if Document is undefined", () => {
26+
const actual = getNlsConfiguration(undefined as any as Document)
27+
const expected = undefined
28+
expect(actual).toBe(expected)
29+
})
30+
it("should return undefined if no nlsConfigElement", () => {
31+
const actual = getNlsConfiguration(global.document)
32+
const expected = undefined
33+
expect(actual).toBe(expected)
34+
})
35+
it("should return undefined if no nlsConfig", () => {
36+
const mockElement = document.createElement("div")
37+
mockElement.setAttribute("id", nlsConfigElementId)
38+
document.body.appendChild(mockElement)
39+
40+
const actual = getNlsConfiguration(document)
41+
const expected = undefined
42+
expect(actual).toBe(expected)
43+
44+
document.body.removeChild(mockElement)
45+
})
46+
it("should log an error if it can't parse the nlsConfig", () => {
47+
const consoleError = console.error
48+
let errorMessage = ""
49+
50+
console.error = (x) => {
51+
errorMessage = x
52+
}
53+
54+
const mockElement = document.createElement("div")
55+
const dataSettings = {
56+
first: "Jane",
57+
last: "Doe",
58+
}
59+
60+
mockElement.setAttribute("id", nlsConfigElementId)
61+
mockElement.setAttribute("data-settings", JSON.stringify(dataSettings) + ",")
62+
document.body.appendChild(mockElement)
63+
64+
getNlsConfiguration(global.document)
65+
66+
expect(errorMessage).toBe("[vscode] Failed to read or parse the NLS configuration.")
67+
68+
console.error = consoleError
69+
document.body.removeChild(mockElement)
70+
})
71+
it("should return the correct configuration", () => {
72+
const mockElement = document.createElement("div")
73+
const dataSettings = {
74+
first: "Jane",
75+
last: "Doe",
76+
}
77+
78+
mockElement.setAttribute("id", nlsConfigElementId)
79+
mockElement.setAttribute("data-settings", JSON.stringify(dataSettings))
80+
document.body.appendChild(mockElement)
81+
// TODO add element to the Dom
82+
// TODO test when DOM is there b
83+
const actual = getNlsConfiguration(global.document)
84+
expect(actual).toStrictEqual(dataSettings)
85+
document.body.removeChild(mockElement)
86+
})
87+
})
88+
})

0 commit comments

Comments
 (0)