feat: add full test coverage browser/vscode

This commit is contained in:
Joe Previte 2021-08-27 15:37:27 -07:00
parent c0d62da127
commit 79b4e4780d
No known key found for this signature in database
GPG Key ID: 2C91590C6B742C24
4 changed files with 82 additions and 20 deletions

View File

@ -24,13 +24,13 @@ type NlsConfiguration = {
* Helper function to create the path to the bundle * Helper function to create the path to the bundle
* for getNlsConfiguration. * for getNlsConfiguration.
*/ */
export function createBundlePath(_resolvedLanguagePackCoreLocation: string, bundle: string) { export function createBundlePath(_resolvedLanguagePackCoreLocation: string | undefined, bundle: string) {
// NOTE@jsjoeio - this comment was here before me // NOTE@jsjoeio - this comment was here before me
// Refers to operating systems that use a different path separator. // Refers to operating systems that use a different path separator.
// Probably just Windows but we're not sure if "/" breaks on Windows // Probably just Windows but we're not sure if "/" breaks on Windows
// so we'll leave it alone for now. // so we'll leave it alone for now.
// FIXME: Only works if path separators are /. // FIXME: Only works if path separators are /.
return _resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json" return (_resolvedLanguagePackCoreLocation || "") + "/" + bundle.replace(/\//g, "!") + ".nls.json"
} }
/** /**
@ -72,20 +72,22 @@ export function getNlsConfiguration(_document: Document, base: string) {
type LoadBundleCallback = (_: undefined, result?: string) => void type LoadBundleCallback = (_: undefined, result?: string) => void
nlsConfig.loadBundle = (bundle: string, _language: string, cb: LoadBundleCallback): void => { nlsConfig.loadBundle = async (bundle: string, _language: string, cb: LoadBundleCallback): Promise<void> => {
const result = bundles[bundle] const result = bundles[bundle]
if (result) { if (result) {
return cb(undefined, result) return cb(undefined, result)
} }
// FIXME: Only works if path separators are /.
const path = createBundlePath(nlsConfig._resolvedLanguagePackCoreLocation || "", bundle) try {
fetch(`${base}/vscode/resource/?path=${encodeURIComponent(path)}`) const path = createBundlePath(nlsConfig._resolvedLanguagePackCoreLocation, bundle)
.then((response) => response.json()) const response = await fetch(`${base}/vscode/resource/?path=${encodeURIComponent(path)}`)
.then((json) => { const json = await response.json()
bundles[bundle] = json bundles[bundle] = json
cb(undefined, json) return cb(undefined, json)
}) } catch (error) {
.catch(cb) return cb(error)
}
} }
} }

View File

@ -7,14 +7,15 @@
"@types/jsdom": "^16.2.6", "@types/jsdom": "^16.2.6",
"@types/node-fetch": "^2.5.8", "@types/node-fetch": "^2.5.8",
"@types/supertest": "^2.0.10", "@types/supertest": "^2.0.10",
"@types/wtfnode": "^0.7.0",
"argon2": "^0.28.0", "argon2": "^0.28.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"jest-fetch-mock": "^3.0.3",
"jsdom": "^16.4.0", "jsdom": "^16.4.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"playwright": "^1.12.1", "playwright": "^1.12.1",
"supertest": "^6.1.1", "supertest": "^6.1.1",
"ts-jest": "^26.4.4", "ts-jest": "^26.4.4",
"@types/wtfnode": "^0.7.0",
"wtfnode": "^0.9.0" "wtfnode": "^0.9.0"
}, },
"resolutions": { "resolutions": {

View File

@ -1,6 +1,7 @@
/** /**
* @jest-environment jsdom * @jest-environment jsdom
*/ */
import fetchMock from "jest-fetch-mock"
import { JSDOM } from "jsdom" import { JSDOM } from "jsdom"
import { import {
getNlsConfiguration, getNlsConfiguration,
@ -20,6 +21,11 @@ describe("vscode", () => {
// We use underscores to not confuse with global values // We use underscores to not confuse with global values
const { window: _window } = new JSDOM() const { window: _window } = new JSDOM()
_document = _window.document _document = _window.document
fetchMock.enableMocks()
})
afterEach(() => {
fetchMock.resetMocks()
}) })
it("should throw an error if no nlsConfigElement", () => { it("should throw an error if no nlsConfigElement", () => {
@ -60,7 +66,7 @@ describe("vscode", () => {
_document.body.removeChild(mockElement) _document.body.removeChild(mockElement)
}) })
it("should return have loadBundle property if _resolvedLangaugePackCoreLocation", () => { it("should return and have a loadBundle property if _resolvedLangaugePackCoreLocation", async () => {
const mockElement = _document.createElement("div") const mockElement = _document.createElement("div")
const dataSettings = { const dataSettings = {
locale: "en", locale: "en",
@ -76,6 +82,32 @@ describe("vscode", () => {
expect(nlsConfig._resolvedLanguagePackCoreLocation).not.toBe(undefined) expect(nlsConfig._resolvedLanguagePackCoreLocation).not.toBe(undefined)
expect(nlsConfig.loadBundle).not.toBe(undefined) expect(nlsConfig.loadBundle).not.toBe(undefined)
const mockCallbackFn = jest.fn((_, bundle) => {
return bundle
})
fetchMock.mockOnce(JSON.stringify({ key: "hello world" }))
// Ensure that load bundle works as expected
// by mocking the fetch response and checking that the callback
// had the expected value
await nlsConfig.loadBundle("hello", "en", mockCallbackFn)
expect(mockCallbackFn).toHaveBeenCalledTimes(1)
expect(mockCallbackFn).toHaveBeenCalledWith(undefined, { key: "hello world" })
// Call it again to ensure it loads from the cache
// it should return the same value
await nlsConfig.loadBundle("hello", "en", mockCallbackFn)
expect(mockCallbackFn).toHaveBeenCalledTimes(2)
expect(mockCallbackFn).toHaveBeenCalledWith(undefined, { key: "hello world" })
fetchMock.mockReject(new Error("fake error message"))
const mockCallbackFn2 = jest.fn((error) => error)
// Call it for a different bundle and mock a failed fetch call
// to ensure we get the expected error
const error = await nlsConfig.loadBundle("goodbye", "es", mockCallbackFn2)
expect(error.message).toEqual("fake error message")
// Clean up
_document.body.removeChild(mockElement) _document.body.removeChild(mockElement)
}) })
}) })
@ -87,6 +119,13 @@ describe("vscode", () => {
const actual = createBundlePath(_resolvedLangaugePackCoreLocation, bundle) const actual = createBundlePath(_resolvedLangaugePackCoreLocation, bundle)
expect(actual).toBe(expected) expect(actual).toBe(expected)
}) })
it("should return the correct path (even if _resolvedLangaugePackCoreLocation is undefined)", () => {
const _resolvedLangaugePackCoreLocation = undefined
const bundle = "/bundle.js"
const expected = "/!bundle.js.nls.json"
const actual = createBundlePath(_resolvedLangaugePackCoreLocation, bundle)
expect(actual).toBe(expected)
})
}) })
describe("setBodyBackgroundToThemeBackgroundColor", () => { describe("setBodyBackgroundToThemeBackgroundColor", () => {
let _document: Document let _document: Document
@ -228,11 +267,6 @@ describe("vscode", () => {
}, },
recordStats: true, recordStats: true,
// TODO@jsjoeio address trustedTypesPolicy part
// might need to look up types
// and find a way to test the function
// maybe extract function into function
// and test manually
trustedTypesPolicy: undefined, trustedTypesPolicy: undefined,
"vs/nls": { "vs/nls": {
availableLanguages: {}, availableLanguages: {},
@ -280,6 +314,11 @@ describe("vscode", () => {
expect(loader.trustedTypesPolicy).not.toBe(undefined) expect(loader.trustedTypesPolicy).not.toBe(undefined)
expect(loader.trustedTypesPolicy.name).toBe("amdLoader") expect(loader.trustedTypesPolicy.name).toBe("amdLoader")
// Check that we can actually create a script URL
// using the createScriptURL on the loader object
const scriptUrl = loader.trustedTypesPolicy.createScriptURL("http://localhost/foo.js")
expect(scriptUrl).toBe("http://localhost/foo.js")
}) })
}) })
describe("_createScriptURL", () => { describe("_createScriptURL", () => {

View File

@ -1757,6 +1757,13 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
cross-fetch@^3.0.4:
version "3.1.4"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==
dependencies:
node-fetch "2.6.1"
cross-spawn@^6.0.0: cross-spawn@^6.0.0:
version "6.0.5" version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@ -2800,6 +2807,14 @@ jest-environment-node@^26.6.2:
jest-mock "^26.6.2" jest-mock "^26.6.2"
jest-util "^26.6.2" jest-util "^26.6.2"
jest-fetch-mock@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b"
integrity sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==
dependencies:
cross-fetch "^3.0.4"
promise-polyfill "^8.1.3"
jest-get-type@^26.3.0: jest-get-type@^26.3.0:
version "26.3.0" version "26.3.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" 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:
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161"
integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==
node-fetch@^2.6.1: node-fetch@2.6.1, node-fetch@^2.6.1:
version "2.6.1" version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@ -3762,6 +3777,11 @@ progress@^2.0.3:
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
promise-polyfill@^8.1.3:
version "8.2.0"
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.2.0.tgz#367394726da7561457aba2133c9ceefbd6267da0"
integrity sha512-k/TC0mIcPVF6yHhUvwAp7cvL6I2fFV7TzF1DuGPI8mBh4QQazf36xCKEHKTZKRysEoTQoQdKyP25J8MPJp7j5g==
prompts@^2.0.1: prompts@^2.0.1:
version "2.4.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7"