diff options
Diffstat (limited to 'js')
-rw-r--r-- | js/compiler_test.ts | 685 | ||||
-rw-r--r-- | js/unit_tests.ts | 2 |
2 files changed, 0 insertions, 687 deletions
diff --git a/js/compiler_test.ts b/js/compiler_test.ts deleted file mode 100644 index e3631641a..000000000 --- a/js/compiler_test.ts +++ /dev/null @@ -1,685 +0,0 @@ -// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -import { test, assert, assertEquals } from "./test_util.ts"; - -// We use a silly amount of `any` in these tests... - -/* eslint-disable @typescript-eslint/no-explicit-any */ - -const { Compiler, jsonEsmTemplate } = (Deno as any)._compiler; - -interface ModuleInfo { - moduleName: string | undefined; - filename: string | undefined; - mediaType: MediaType | undefined; - sourceCode: string | undefined; - outputCode: string | undefined; - sourceMap: string | undefined; -} - -// Since we can't/don't want to import all of TypeScript for this one enum, we -// we will replicate it from TypeScript. This does mean that if other script -// kinds are added in the future we would need to add them manually to the tests -enum ScriptKind { - Unknown = 0, - JS = 1, - JSX = 2, - TS = 3, - TSX = 4, - External = 5, - JSON = 6, - Deferred = 7 -} - -const compilerInstance = Compiler.instance(); - -// References to original items we are going to mock -const originals = { - _log: (compilerInstance as any)._log, - _os: (compilerInstance as any)._os, - _ts: (compilerInstance as any)._ts, - _service: (compilerInstance as any)._service -}; - -enum MediaType { - JavaScript = 0, - TypeScript = 1, - Json = 2, - Unknown = 3 -} - -function mockModuleInfo( - moduleName: string | undefined, - filename: string | undefined, - mediaType: MediaType | undefined, - sourceCode: string | undefined, - outputCode: string | undefined, - sourceMap: string | undefined -): ModuleInfo { - return { - moduleName, - filename, - mediaType, - sourceCode, - outputCode, - sourceMap - }; -} - -// Some fixtures we will use in testing -const fooBarTsSource = `import * as deno from "deno"; -console.log(deno); -export const foo = "bar"; -`; - -const fooBazTsSource = `import { foo } from "./bar.ts"; -console.log(foo); -`; - -const modASource = `import { B } from "./modB.ts"; - -export class A { - b = new B(); -}; -`; - -const modAModuleInfo = mockModuleInfo( - "modA", - "/root/project/modA.ts", - MediaType.TypeScript, - modASource, - undefined, - undefined -); - -const modBSource = `import { A } from "./modA.ts"; - -export class B { - a = new A(); -}; -`; - -const modBModuleInfo = mockModuleInfo( - "modB", - "/root/project/modB.ts", - MediaType.TypeScript, - modBSource, - undefined, - undefined -); - -const fooBarTsOutput = `import * as deno from "deno"; -console.log(deno); -export const foo = "bar"; -//# sourceMappingURL=bar.js.map -//# sourceURL=/root/project/foo/bar.ts`; - -const fooBarTsSourcemap = `{"version":3,"file":"bar.js","sourceRoot":"","sources":["file:///root/project/foo/bar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAClB,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC"}`; - -const loadConfigSource = `import * as config from "./config.json"; -console.log(config.foo.baz); -`; -const configJsonSource = `{"foo":{"bar": true,"baz": ["qat", 1]}}`; - -const moduleMap: { - [containFile: string]: { [moduleSpecifier: string]: ModuleInfo }; -} = { - "/root/project": { - "foo/bar.ts": mockModuleInfo( - "/root/project/foo/bar.ts", - "/root/project/foo/bar.ts", - MediaType.TypeScript, - fooBarTsSource, - null, - null - ), - "foo/baz.ts": mockModuleInfo( - "/root/project/foo/baz.ts", - "/root/project/foo/baz.ts", - MediaType.TypeScript, - fooBazTsSource, - null, - null - ), - "modA.ts": modAModuleInfo, - "some.txt": mockModuleInfo( - "/root/project/some.txt", - "/root/project/some.text", - MediaType.Unknown, - "console.log();", - null, - null - ), - "loadConfig.ts": mockModuleInfo( - "/root/project/loadConfig.ts", - "/root/project/loadConfig.ts", - MediaType.TypeScript, - loadConfigSource, - null, - null - ) - }, - "/root/project/foo/baz.ts": { - "./bar.ts": mockModuleInfo( - "/root/project/foo/bar.ts", - "/root/project/foo/bar.ts", - MediaType.TypeScript, - fooBarTsSource, - fooBarTsOutput, - fooBarTsSourcemap - ) - }, - "/root/project/modA.ts": { - "./modB.ts": modBModuleInfo - }, - "/root/project/modB.ts": { - "./modA.ts": modAModuleInfo - }, - "/root/project/loadConfig.ts": { - "./config.json": mockModuleInfo( - "/root/project/config.json", - "/root/project/config.json", - MediaType.Json, - configJsonSource, - null, - null - ) - }, - "/moduleKinds": { - "foo.ts": mockModuleInfo( - "foo", - "/moduleKinds/foo.ts", - MediaType.TypeScript, - "console.log('foo');", - undefined, - undefined - ), - "foo.d.ts": mockModuleInfo( - "foo", - "/moduleKinds/foo.d.ts", - MediaType.TypeScript, - "console.log('foo');", - undefined, - undefined - ), - "foo.js": mockModuleInfo( - "foo", - "/moduleKinds/foo.js", - MediaType.JavaScript, - "console.log('foo');", - undefined, - undefined - ), - "foo.json": mockModuleInfo( - "foo", - "/moduleKinds/foo.json", - MediaType.Json, - "console.log('foo');", - undefined, - undefined - ), - "foo.txt": mockModuleInfo( - "foo", - "/moduleKinds/foo.txt", - MediaType.JavaScript, - "console.log('foo');", - undefined, - undefined - ), - "empty_file.ts": mockModuleInfo( - "/moduleKinds/empty_file.ts", - "/moduleKinds/empty_file.ts", - MediaType.TypeScript, - "", - undefined, - undefined - ) - } -}; - -const moduleCache: { - [fileName: string]: ModuleInfo; -} = { - "/root/project/modA.ts": modAModuleInfo, - "/root/project/modB.ts": modBModuleInfo -}; - -let getEmitOutputStack: string[] = []; -let logStack: any[][] = []; -let codeCacheStack: Array<{ - fileName: string; - sourceCode: string; - outputCode: string; - sourceMap: string; -}> = []; -let codeFetchStack: Array<{ - moduleSpecifier: string; - containingFile: string; -}> = []; - -let mockDepsStack: string[][] = []; -let mockFactoryStack: any[] = []; - -function logMock(...args: any[]): void { - logStack.push(args); -} -const osMock = { - codeCache( - fileName: string, - sourceCode: string, - outputCode: string, - sourceMap: string - ): void { - codeCacheStack.push({ fileName, sourceCode, outputCode, sourceMap }); - if (fileName in moduleCache) { - moduleCache[fileName].sourceCode = sourceCode; - moduleCache[fileName].outputCode = outputCode; - moduleCache[fileName].sourceMap = sourceMap; - } else { - moduleCache[fileName] = mockModuleInfo( - fileName, - fileName, - MediaType.TypeScript, - sourceCode, - outputCode, - sourceMap - ); - } - }, - codeFetch(moduleSpecifier: string, containingFile: string): ModuleInfo { - codeFetchStack.push({ moduleSpecifier, containingFile }); - if (containingFile in moduleMap) { - if (moduleSpecifier in moduleMap[containingFile]) { - return moduleMap[containingFile][moduleSpecifier]; - } - } - return mockModuleInfo(null, null, null, null, null, null); - }, - exit(code: number): never { - throw new Error(`Unexpected call to os.exit(${code})`); - } -}; -const tsMock = { - createLanguageService() { - return {} as any; - }, - formatDiagnostics(diagnostics: ReadonlyArray<any>, _host: any): string { - return JSON.stringify(diagnostics.map(({ messageText }) => messageText)); - }, - formatDiagnosticsWithColorAndContext( - diagnostics: ReadonlyArray<any>, - _host: any - ): string { - return JSON.stringify(diagnostics.map(({ messageText }) => messageText)); - } -}; - -const serviceMock = { - getCompilerOptionsDiagnostics() { - return originals._service.getCompilerOptionsDiagnostics.call( - originals._service - ); - }, - getEmitOutput(fileName: string) { - getEmitOutputStack.push(fileName); - return originals._service.getEmitOutput.call(originals._service, fileName); - }, - getSemanticDiagnostics(fileName: string) { - return originals._service.getSemanticDiagnostics.call( - originals._service, - fileName - ); - }, - getSyntacticDiagnostics(fileName: string) { - return originals._service.getSyntacticDiagnostics.call( - originals._service, - fileName - ); - } -}; -const mocks = { - _log: logMock, - _os: osMock, - _ts: tsMock, - _service: serviceMock -}; - -/** - * Setup the mocks for a test - */ -function setup(): void { - // monkey patch mocks on instance - Object.assign(compilerInstance, mocks); -} - -/** - * Teardown the mocks for a test - */ -function teardown(): void { - // reset compiler internal state - (compilerInstance as any)._moduleMetaDataMap.clear(); - (compilerInstance as any)._fileNamesMap.clear(); - - // reset mock states - codeFetchStack = []; - codeCacheStack = []; - logStack = []; - getEmitOutputStack = []; - - assertEquals(mockDepsStack.length, 0); - assertEquals(mockFactoryStack.length, 0); - mockDepsStack = []; - mockFactoryStack = []; - - // restore original properties and methods - Object.assign(compilerInstance, originals); -} - -test(function testJsonEsmTemplate() { - const result = jsonEsmTemplate( - `{ "hello": "world", "foo": "bar" }`, - "/foo.ts" - ); - assertEquals( - result, - `const _json = JSON.parse(\`{ "hello": "world", "foo": "bar" }\`)\n` + - `export default _json;\n` + - `//# sourceURL=/foo.ts` - ); -}); - -test(function compilerInstance() { - assert(Compiler != null); - assert(Compiler.instance() != null); -}); - -// Testing the internal APIs - -test(function compilerCompile() { - // equal to `deno foo/bar.ts` - setup(); - const moduleMetaData = compilerInstance.compile( - "foo/bar.ts", - "/root/project" - ); - assertEquals(moduleMetaData.sourceCode, fooBarTsSource); - assertEquals(moduleMetaData.outputCode, fooBarTsOutput); - - assertEquals( - codeFetchStack.length, - 1, - "Module should have only been fetched once." - ); - assertEquals( - codeCacheStack.length, - 1, - "Compiled code should have only been cached once." - ); - const [codeCacheCall] = codeCacheStack; - assertEquals(codeCacheCall.fileName, "/root/project/foo/bar.ts"); - assertEquals(codeCacheCall.sourceCode, fooBarTsSource); - assertEquals(codeCacheCall.outputCode, fooBarTsOutput); - assertEquals(codeCacheCall.sourceMap, fooBarTsSourcemap); - teardown(); -}); - -test(function compilerCompilerMultiModule() { - // equal to `deno foo/baz.ts` - setup(); - compilerInstance.compile("foo/baz.ts", "/root/project"); - assertEquals(codeFetchStack.length, 2, "Two modules fetched."); - assertEquals(codeCacheStack.length, 1, "Only one module compiled."); - teardown(); -}); - -test(function compilerLoadJsonModule() { - setup(); - compilerInstance.compile("loadConfig.ts", "/root/project"); - assertEquals(codeFetchStack.length, 2, "Two modules fetched."); - assertEquals(codeCacheStack.length, 1, "Only one module compiled."); - teardown(); -}); - -test(function compilerResolveModule() { - setup(); - const moduleMetaData = compilerInstance.resolveModule( - "foo/baz.ts", - "/root/project" - ); - console.log(moduleMetaData); - assertEquals(moduleMetaData.sourceCode, fooBazTsSource); - assertEquals(moduleMetaData.outputCode, null); - assertEquals(moduleMetaData.sourceMap, null); - assertEquals(moduleMetaData.scriptVersion, "1"); - - assertEquals(codeFetchStack.length, 1, "Only initial module is resolved."); - teardown(); -}); - -test(function compilerResolveModuleUnknownMediaType() { - setup(); - let didThrow = false; - try { - compilerInstance.resolveModule("some.txt", "/root/project"); - } catch (e) { - assert(e instanceof Error); - assertEquals( - e.message, - `Unknown media type for: "some.txt" from "/root/project".` - ); - didThrow = true; - } - assert(didThrow); - teardown(); -}); - -test(function compilerRecompileFlag() { - setup(); - compilerInstance.compile("foo/bar.ts", "/root/project"); - assertEquals( - getEmitOutputStack.length, - 1, - "Expected only a single emitted file." - ); - // running compiler against same file should use cached code - compilerInstance.compile("foo/bar.ts", "/root/project"); - assertEquals( - getEmitOutputStack.length, - 1, - "Expected only a single emitted file." - ); - compilerInstance.recompile = true; - compilerInstance.compile("foo/bar.ts", "/root/project"); - assertEquals(getEmitOutputStack.length, 2, "Expected two emitted file."); - assert( - getEmitOutputStack[0] === getEmitOutputStack[1], - "Expected same file to be emitted twice." - ); - teardown(); -}); - -// TypeScript LanguageServiceHost APIs - -test(function compilerGetCompilationSettings() { - const expectedKeys = [ - "allowJs", - "checkJs", - "esModuleInterop", - "module", - "outDir", - "resolveJsonModule", - "sourceMap", - "stripComments", - "target" - ]; - const result = compilerInstance.getCompilationSettings(); - for (const key of expectedKeys) { - assert(key in result, `Expected "${key}" in compiler options.`); - } - assertEquals(Object.keys(result).length, expectedKeys.length); -}); - -test(function compilerGetNewLine() { - const result = compilerInstance.getNewLine(); - assertEquals(result, "\n", "Expected newline value of '\\n'."); -}); - -test(function compilerGetScriptFileNames() { - setup(); - compilerInstance.compile("foo/bar.ts", "/root/project"); - const result = compilerInstance.getScriptFileNames(); - assertEquals(result.length, 1, "Expected only a single filename."); - assertEquals(result[0], "/root/project/foo/bar.ts"); - teardown(); -}); - -test(function compilerGetScriptKind() { - setup(); - compilerInstance.resolveModule("foo.ts", "/moduleKinds"); - compilerInstance.resolveModule("foo.d.ts", "/moduleKinds"); - compilerInstance.resolveModule("foo.js", "/moduleKinds"); - compilerInstance.resolveModule("foo.json", "/moduleKinds"); - compilerInstance.resolveModule("foo.txt", "/moduleKinds"); - assertEquals( - compilerInstance.getScriptKind("/moduleKinds/foo.ts"), - ScriptKind.TS - ); - assertEquals( - compilerInstance.getScriptKind("/moduleKinds/foo.d.ts"), - ScriptKind.TS - ); - assertEquals( - compilerInstance.getScriptKind("/moduleKinds/foo.js"), - ScriptKind.JS - ); - assertEquals( - compilerInstance.getScriptKind("/moduleKinds/foo.json"), - ScriptKind.JSON - ); - assertEquals( - compilerInstance.getScriptKind("/moduleKinds/foo.txt"), - ScriptKind.JS - ); - teardown(); -}); - -test(function compilerGetScriptVersion() { - setup(); - const moduleMetaData = compilerInstance.compile( - "foo/bar.ts", - "/root/project" - ); - assertEquals( - compilerInstance.getScriptVersion(moduleMetaData.fileName), - "1", - "Expected known module to have script version of 1" - ); - teardown(); -}); - -test(function compilerGetScriptVersionUnknown() { - assertEquals( - compilerInstance.getScriptVersion("/root/project/unknown_module.ts"), - "", - "Expected unknown module to have an empty script version" - ); -}); - -test(function compilerGetScriptSnapshot() { - setup(); - const moduleMetaData = compilerInstance.resolveModule( - "foo/bar.ts", - "/root/project" - ); - const result = compilerInstance.getScriptSnapshot(moduleMetaData.fileName); - assert(result != null, "Expected snapshot to be defined."); - assertEquals(result.getLength(), fooBarTsSource.length); - assertEquals( - result.getText(0, 6), - "import", - "Expected .getText() to equal 'import'" - ); - assertEquals(result.getChangeRange(result), undefined); - // This is and optional part of the `IScriptSnapshot` API which we don't - // define, os checking for the lack of this property. - assert(!("dispose" in result)); - - assert( - result === moduleMetaData, - "result should strictly equal moduleMetaData" - ); - teardown(); -}); - -test(function compilerGetCurrentDirectory() { - assertEquals(compilerInstance.getCurrentDirectory(), ""); -}); - -test(function compilerGetDefaultLibFileName() { - setup(); - assertEquals( - compilerInstance.getDefaultLibFileName(), - "$asset$/lib.deno_runtime.d.ts" - ); - teardown(); -}); - -test(function compilerUseCaseSensitiveFileNames() { - assertEquals(compilerInstance.useCaseSensitiveFileNames(), true); -}); - -test(function compilerReadFile() { - let doesThrow = false; - try { - compilerInstance.readFile("foobar.ts"); - } catch (e) { - doesThrow = true; - assert(e.message.includes("Not implemented") === true); - } - assert(doesThrow); -}); - -test(function compilerFileExists() { - setup(); - const moduleMetaData = compilerInstance.resolveModule( - "foo/bar.ts", - "/root/project" - ); - assert(compilerInstance.fileExists(moduleMetaData.fileName)); - assert(compilerInstance.fileExists("$asset$/lib.deno_runtime.d.ts")); - assertEquals( - compilerInstance.fileExists("/root/project/unknown-module.ts"), - false - ); - teardown(); -}); - -test(function compilerResolveModuleNames() { - setup(); - const results = compilerInstance.resolveModuleNames( - ["foo/bar.ts", "foo/baz.ts", "deno"], - "/root/project" - ); - assertEquals(results.length, 3); - const fixtures: Array<[string, boolean]> = [ - ["/root/project/foo/bar.ts", false], - ["/root/project/foo/baz.ts", false], - ["$asset$/lib.deno_runtime.d.ts", true] - ]; - for (let i = 0; i < results.length; i++) { - const result = results[i]; - const [resolvedFileName, isExternalLibraryImport] = fixtures[i]; - assertEquals(result.resolvedFileName, resolvedFileName); - assertEquals(result.isExternalLibraryImport, isExternalLibraryImport); - } - teardown(); -}); - -test(function compilerResolveEmptyFile() { - setup(); - const result = compilerInstance.resolveModuleNames( - ["empty_file.ts"], - "/moduleKinds" - ); - assertEquals(result[0].resolvedFileName, "/moduleKinds/empty_file.ts"); - teardown(); -}); diff --git a/js/unit_tests.ts b/js/unit_tests.ts index 8b551b6fb..4df3ae16e 100644 --- a/js/unit_tests.ts +++ b/js/unit_tests.ts @@ -7,8 +7,6 @@ import "./blob_test.ts"; import "./buffer_test.ts"; import "./build_test.ts"; import "./chmod_test.ts"; -// TODO find a way to test the compiler with split snapshots -// import "./compiler_test.ts"; import "./console_test.ts"; import "./copy_file_test.ts"; import "./custom_event_test.ts"; |