Skip to content

Commit ed1ded5

Browse files
authored
Merge pull request #4055 from cdr/jsjoeio-tests-vscode
feat(testing): add tests for src/browser/pages/vscode to hit 100% coverage
2 parents ccd835c + 79b4e47 commit ed1ded5

File tree

4 files changed

+82
-20
lines changed

4 files changed

+82
-20
lines changed

src/browser/pages/vscode.ts

+14-12
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ type NlsConfiguration = {
2424
* Helper function to create the path to the bundle
2525
* for getNlsConfiguration.
2626
*/
27-
export function createBundlePath(_resolvedLanguagePackCoreLocation: string, bundle: string) {
27+
export function createBundlePath(_resolvedLanguagePackCoreLocation: string | undefined, bundle: string) {
2828
// NOTE@jsjoeio - this comment was here before me
2929
// Refers to operating systems that use a different path separator.
3030
// Probably just Windows but we're not sure if "/" breaks on Windows
3131
// so we'll leave it alone for now.
3232
// FIXME: Only works if path separators are /.
33-
return _resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
33+
return (_resolvedLanguagePackCoreLocation || "") + "/" + bundle.replace(/\//g, "!") + ".nls.json"
3434
}
3535

3636
/**
@@ -72,20 +72,22 @@ export function getNlsConfiguration(_document: Document, base: string) {
7272

7373
type LoadBundleCallback = (_: undefined, result?: string) => void
7474

75-
nlsConfig.loadBundle = (bundle: string, _language: string, cb: LoadBundleCallback): void => {
75+
nlsConfig.loadBundle = async (bundle: string, _language: string, cb: LoadBundleCallback): Promise<void> => {
7676
const result = bundles[bundle]
77+
7778
if (result) {
7879
return cb(undefined, result)
7980
}
80-
// FIXME: Only works if path separators are /.
81-
const path = createBundlePath(nlsConfig._resolvedLanguagePackCoreLocation || "", bundle)
82-
fetch(`${base}/vscode/resource/?path=${encodeURIComponent(path)}`)
83-
.then((response) => response.json())
84-
.then((json) => {
85-
bundles[bundle] = json
86-
cb(undefined, json)
87-
})
88-
.catch(cb)
81+
82+
try {
83+
const path = createBundlePath(nlsConfig._resolvedLanguagePackCoreLocation, bundle)
84+
const response = await fetch(`${base}/vscode/resource/?path=${encodeURIComponent(path)}`)
85+
const json = await response.json()
86+
bundles[bundle] = json
87+
return cb(undefined, json)
88+
} catch (error) {
89+
return cb(error)
90+
}
8991
}
9092
}
9193

test/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
"@types/jsdom": "^16.2.6",
88
"@types/node-fetch": "^2.5.8",
99
"@types/supertest": "^2.0.10",
10+
"@types/wtfnode": "^0.7.0",
1011
"argon2": "^0.28.0",
1112
"jest": "^26.6.3",
13+
"jest-fetch-mock": "^3.0.3",
1214
"jsdom": "^16.4.0",
1315
"node-fetch": "^2.6.1",
1416
"playwright": "^1.12.1",
1517
"supertest": "^6.1.1",
1618
"ts-jest": "^26.4.4",
17-
"@types/wtfnode": "^0.7.0",
1819
"wtfnode": "^0.9.0"
1920
},
2021
"resolutions": {

test/unit/browser/pages/vscode.test.ts

+45-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* @jest-environment jsdom
33
*/
4+
import fetchMock from "jest-fetch-mock"
45
import { JSDOM } from "jsdom"
56
import {
67
getNlsConfiguration,
@@ -20,6 +21,11 @@ describe("vscode", () => {
2021
// We use underscores to not confuse with global values
2122
const { window: _window } = new JSDOM()
2223
_document = _window.document
24+
fetchMock.enableMocks()
25+
})
26+
27+
afterEach(() => {
28+
fetchMock.resetMocks()
2329
})
2430

2531
it("should throw an error if no nlsConfigElement", () => {
@@ -60,7 +66,7 @@ describe("vscode", () => {
6066

6167
_document.body.removeChild(mockElement)
6268
})
63-
it("should return have loadBundle property if _resolvedLangaugePackCoreLocation", () => {
69+
it("should return and have a loadBundle property if _resolvedLangaugePackCoreLocation", async () => {
6470
const mockElement = _document.createElement("div")
6571
const dataSettings = {
6672
locale: "en",
@@ -76,6 +82,32 @@ describe("vscode", () => {
7682
expect(nlsConfig._resolvedLanguagePackCoreLocation).not.toBe(undefined)
7783
expect(nlsConfig.loadBundle).not.toBe(undefined)
7884

85+
const mockCallbackFn = jest.fn((_, bundle) => {
86+
return bundle
87+
})
88+
89+
fetchMock.mockOnce(JSON.stringify({ key: "hello world" }))
90+
// Ensure that load bundle works as expected
91+
// by mocking the fetch response and checking that the callback
92+
// had the expected value
93+
await nlsConfig.loadBundle("hello", "en", mockCallbackFn)
94+
expect(mockCallbackFn).toHaveBeenCalledTimes(1)
95+
expect(mockCallbackFn).toHaveBeenCalledWith(undefined, { key: "hello world" })
96+
97+
// Call it again to ensure it loads from the cache
98+
// it should return the same value
99+
await nlsConfig.loadBundle("hello", "en", mockCallbackFn)
100+
expect(mockCallbackFn).toHaveBeenCalledTimes(2)
101+
expect(mockCallbackFn).toHaveBeenCalledWith(undefined, { key: "hello world" })
102+
103+
fetchMock.mockReject(new Error("fake error message"))
104+
const mockCallbackFn2 = jest.fn((error) => error)
105+
// Call it for a different bundle and mock a failed fetch call
106+
// to ensure we get the expected error
107+
const error = await nlsConfig.loadBundle("goodbye", "es", mockCallbackFn2)
108+
expect(error.message).toEqual("fake error message")
109+
110+
// Clean up
79111
_document.body.removeChild(mockElement)
80112
})
81113
})
@@ -87,6 +119,13 @@ describe("vscode", () => {
87119
const actual = createBundlePath(_resolvedLangaugePackCoreLocation, bundle)
88120
expect(actual).toBe(expected)
89121
})
122+
it("should return the correct path (even if _resolvedLangaugePackCoreLocation is undefined)", () => {
123+
const _resolvedLangaugePackCoreLocation = undefined
124+
const bundle = "/bundle.js"
125+
const expected = "/!bundle.js.nls.json"
126+
const actual = createBundlePath(_resolvedLangaugePackCoreLocation, bundle)
127+
expect(actual).toBe(expected)
128+
})
90129
})
91130
describe("setBodyBackgroundToThemeBackgroundColor", () => {
92131
let _document: Document
@@ -228,11 +267,6 @@ describe("vscode", () => {
228267
},
229268
recordStats: true,
230269

231-
// TODO@jsjoeio address trustedTypesPolicy part
232-
// might need to look up types
233-
// and find a way to test the function
234-
// maybe extract function into function
235-
// and test manually
236270
trustedTypesPolicy: undefined,
237271
"vs/nls": {
238272
availableLanguages: {},
@@ -280,6 +314,11 @@ describe("vscode", () => {
280314

281315
expect(loader.trustedTypesPolicy).not.toBe(undefined)
282316
expect(loader.trustedTypesPolicy.name).toBe("amdLoader")
317+
318+
// Check that we can actually create a script URL
319+
// using the createScriptURL on the loader object
320+
const scriptUrl = loader.trustedTypesPolicy.createScriptURL("http://localhost/foo.js")
321+
expect(scriptUrl).toBe("http://localhost/foo.js")
283322
})
284323
})
285324
describe("_createScriptURL", () => {

test/yarn.lock

+21-1
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,13 @@ [email protected], core-util-is@~1.0.0:
17571757
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
17581758
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
17591759

1760+
cross-fetch@^3.0.4:
1761+
version "3.1.4"
1762+
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
1763+
integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==
1764+
dependencies:
1765+
node-fetch "2.6.1"
1766+
17601767
cross-spawn@^6.0.0:
17611768
version "6.0.5"
17621769
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@@ -2800,6 +2807,14 @@ jest-environment-node@^26.6.2:
28002807
jest-mock "^26.6.2"
28012808
jest-util "^26.6.2"
28022809

2810+
jest-fetch-mock@^3.0.3:
2811+
version "3.0.3"
2812+
resolved "https://registry.yarnpkg.com/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b"
2813+
integrity sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==
2814+
dependencies:
2815+
cross-fetch "^3.0.4"
2816+
promise-polyfill "^8.1.3"
2817+
28032818
jest-get-type@^26.3.0:
28042819
version "26.3.0"
28052820
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0"
@@ -3418,7 +3433,7 @@ node-addon-api@^3.0.2:
34183433
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161"
34193434
integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==
34203435

3421-
node-fetch@^2.6.1:
3436+
node-fetch@2.6.1, node-fetch@^2.6.1:
34223437
version "2.6.1"
34233438
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
34243439
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@@ -3762,6 +3777,11 @@ progress@^2.0.3:
37623777
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
37633778
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
37643779

3780+
promise-polyfill@^8.1.3:
3781+
version "8.2.0"
3782+
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.2.0.tgz#367394726da7561457aba2133c9ceefbd6267da0"
3783+
integrity sha512-k/TC0mIcPVF6yHhUvwAp7cvL6I2fFV7TzF1DuGPI8mBh4QQazf36xCKEHKTZKRysEoTQoQdKyP25J8MPJp7j5g==
3784+
37653785
prompts@^2.0.1:
37663786
version "2.4.0"
37673787
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7"

0 commit comments

Comments
 (0)