1describe("unittests:: Public APIs", () => { 2 function verifyApi(fileName: string) { 3 const builtFile = `built/local/${fileName}`; 4 const api = `api/${fileName}`; 5 let fileContent: string; 6 before(() => { 7 fileContent = Harness.IO.readFile(builtFile)!; 8 if (!fileContent) throw new Error(`File ${fileName} was not present in built/local`); 9 fileContent = fileContent.replace(/\r\n/g, "\n"); 10 }); 11 12 it("should be acknowledged when they change", () => { 13 Harness.Baseline.runBaseline(api, fileContent, { PrintDiff: true }); 14 }); 15 16 it("should compile", () => { 17 const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); 18 fs.linkSync(`${vfs.builtFolder}/${fileName}`, `${vfs.srcFolder}/${fileName}`); 19 const sys = new fakes.System(fs); 20 const host = new fakes.CompilerHost(sys); 21 const result = compiler.compileFiles(host, [`${vfs.srcFolder}/${fileName}`], {}); 22 assert(!result.diagnostics || !result.diagnostics.length, Harness.Compiler.minimalDiagnosticsToString(result.diagnostics, /*pretty*/ true)); 23 }); 24 } 25 26 describe("for the language service and compiler", () => { 27 verifyApi("typescript.d.ts"); 28 }); 29 30 describe("for the language server", () => { 31 verifyApi("tsserverlibrary.d.ts"); 32 }); 33}); 34 35describe("unittests:: Public APIs:: token to string", () => { 36 function assertDefinedTokenToString(initial: ts.SyntaxKind, last: ts.SyntaxKind) { 37 for (let t = initial; t <= last; t++) { 38 assert.isDefined(ts.tokenToString(t), `Expected tokenToString defined for ${ts.Debug.formatSyntaxKind(t)}`); 39 } 40 } 41 42 it("for punctuations", () => { 43 assertDefinedTokenToString(ts.SyntaxKind.FirstPunctuation, ts.SyntaxKind.LastPunctuation); 44 }); 45 it("for keywords", () => { 46 assertDefinedTokenToString(ts.SyntaxKind.FirstKeyword, ts.SyntaxKind.LastKeyword); 47 }); 48}); 49 50describe("unittests:: Public APIs:: createPrivateIdentifier", () => { 51 it("throws when name doesn't start with #", () => { 52 assert.throw(() => ts.factory.createPrivateIdentifier("not"), "Debug Failure. First character of private identifier must be #: not"); 53 }); 54}); 55 56describe("unittests:: Public APIs:: JSDoc newlines", () => { 57 it("are preserved verbatim", () => { 58 const testFilePath = "/file.ts"; 59 const testFileText = ` 60/** 61* @example 62* Some\n * text\r\n * with newlines. 63*/ 64function test() {}`; 65 66 const testSourceFile = ts.createSourceFile(testFilePath, testFileText, ts.ScriptTarget.Latest, /*setParentNodes*/ true); 67 const funcDec = testSourceFile.statements.find(ts.isFunctionDeclaration)!; 68 const tags = ts.getJSDocTags(funcDec); 69 assert.isDefined(tags[0].comment); 70 assert.equal(tags[0].comment, "Some\n text\r\n with newlines."); 71 }); 72}); 73 74describe("unittests:: Public APIs:: isPropertyName", () => { 75 it("checks if a PrivateIdentifier is a valid property name", () => { 76 const prop = ts.factory.createPrivateIdentifier("#foo"); 77 assert.isTrue(ts.isPropertyName(prop), "PrivateIdentifier must be a valid property name."); 78 }); 79}); 80 81describe("unittests:: Public APIs:: getTypeAtLocation", () => { 82 it("works on PropertyAccessExpression in implements clause", () => { 83 const content = `namespace Test { 84 export interface Test {} 85 } 86 class Foo implements Test.Test {}`; 87 88 const host = new fakes.CompilerHost(vfs.createFromFileSystem( 89 Harness.IO, 90 /*ignoreCase*/ true, 91 { documents: [new documents.TextDocument("/file.ts", content)], cwd: "/" })); 92 93 const program = ts.createProgram({ 94 host, 95 rootNames: ["/file.ts"], 96 options: { noLib: true } 97 }); 98 99 const checker = program.getTypeChecker(); 100 const file = program.getSourceFile("/file.ts")!; 101 const classDeclaration = file.statements.find(ts.isClassDeclaration)!; 102 const propertyAccess = classDeclaration.heritageClauses![0].types[0].expression as ts.PropertyAccessExpression; 103 const type = checker.getTypeAtLocation(propertyAccess); 104 assert.ok(!(type.flags & ts.TypeFlags.Any)); 105 assert.equal(type, checker.getTypeAtLocation(propertyAccess.name)); 106 }); 107 108 it("works on SourceFile", () => { 109 const content = `const foo = 1;`; 110 const host = new fakes.CompilerHost(vfs.createFromFileSystem( 111 Harness.IO, 112 /*ignoreCase*/ true, 113 { documents: [new documents.TextDocument("/file.ts", content)], cwd: "/" })); 114 115 const program = ts.createProgram({ 116 host, 117 rootNames: ["/file.ts"], 118 options: { noLib: true } 119 }); 120 121 const checker = program.getTypeChecker(); 122 const file = program.getSourceFile("/file.ts")!; 123 const type = checker.getTypeAtLocation(file); 124 assert.equal(type.flags, ts.TypeFlags.Any); 125 }); 126}); 127 128describe("unittests:: Public APIs:: validateLocaleAndSetLanguage", () => { 129 let savedUILocale: string | undefined; 130 beforeEach(() => savedUILocale = ts.getUILocale()); 131 afterEach(() => ts.setUILocale(savedUILocale)); 132 133 function verifyValidateLocale(locale: string, expectedToReadFile: boolean) { 134 it(`Verifying ${locale} ${expectedToReadFile ? "reads" : "does not read"} file`, () => { 135 const errors: ts.Diagnostic[] = []; 136 ts.validateLocaleAndSetLanguage(locale, { 137 getExecutingFilePath: () => "/tsc.js", 138 resolvePath: ts.identity, 139 fileExists: fileName => { 140 assert.isTrue(expectedToReadFile, `Locale : ${locale} ${expectedToReadFile ? "should" : "should not"} check if ${fileName} exists.`); 141 return expectedToReadFile; 142 }, 143 readFile: fileName => { 144 assert.isTrue(expectedToReadFile, `Locale : ${locale} ${expectedToReadFile ? "should" : "should not"} read ${fileName}.`); 145 // Throw error here so that actual change to localized diagnostics messages doesnt take place 146 throw new Error("cannot read file"); 147 } 148 }, errors); 149 }); 150 } 151 ts.supportedLocaleDirectories.forEach(locale => verifyValidateLocale(locale, /*expctedToReadFile*/ true)); 152 ["en", "en-us"].forEach(locale => verifyValidateLocale(locale, /*expctedToReadFile*/ false)); 153}); 154