Skip to content

Commit 0b47a2d

Browse files
Add tests
1 parent bf4ec1d commit 0b47a2d

4 files changed

Lines changed: 171 additions & 7 deletions

File tree

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,11 @@ namespace ts.projectSystem {
243243
}
244244
}
245245

246-
export function createSession(host: server.ServerHost, opts: Partial<server.SessionOptions> = {}) {
246+
export function createSession(host: TestServerHost, opts: Partial<server.SessionOptions> = {}) {
247247
if (opts.typingsInstaller === undefined) {
248-
opts.typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/ 5, host);
248+
const globalTypingsCacheLocation = "/a/data";
249+
host.ensureFileOrFolder({ path: globalTypingsCacheLocation });
250+
opts.typingsInstaller = new TestTypingsInstaller(globalTypingsCacheLocation, /*throttleLimit*/ 5, host);
249251
}
250252

251253
if (opts.eventHandler !== undefined) {

src/harness/unittests/typingsInstaller.ts

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ namespace ts.projectSystem {
2222
}
2323

2424
class Installer extends TestTypingsInstaller {
25-
constructor(host: server.ServerHost, p?: InstallerParams, log?: TI.Log) {
25+
constructor(host: TestServerHost, p?: InstallerParams, log?: TI.Log) {
26+
host.ensureFileOrFolder({ path: (p && p.globalTypingsCacheLocation) || "/a/data" });
2627
super(
2728
(p && p.globalTypingsCacheLocation) || "/a/data",
2829
(p && p.throttleLimit) || 5,
@@ -1053,6 +1054,132 @@ namespace ts.projectSystem {
10531054
const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
10541055
assert.notEqual(version1, version2, "set of unresolved imports should change");
10551056
});
1057+
1058+
it("expired cache entry (inferred project, should install typings)", () => {
1059+
const file1 = {
1060+
path: "/a/b/app.js",
1061+
content: ""
1062+
};
1063+
const packageJson = {
1064+
path: "/a/b/package.json",
1065+
content: JSON.stringify({
1066+
name: "test",
1067+
dependencies: {
1068+
jquery: "^3.1.0"
1069+
}
1070+
})
1071+
};
1072+
const date = new Date();
1073+
date.setFullYear(date.getFullYear() - 1);
1074+
const timestamps = {
1075+
path: "/a/data/timestamps.json",
1076+
content: JSON.stringify({
1077+
entries: {
1078+
"@types/jquery": date.getTime()
1079+
}
1080+
})
1081+
};
1082+
const jquery = {
1083+
path: "/a/data/node_modules/@types/jquery/index.d.ts",
1084+
content: "declare const $: { x: number }"
1085+
};
1086+
const cacheConfig = {
1087+
path: "/a/data/package.json",
1088+
content: JSON.stringify({
1089+
dependencies: {
1090+
"types-registry": "^0.1.317"
1091+
},
1092+
devDependencies: {
1093+
"@types/jquery": "^3.2.16"
1094+
}
1095+
})
1096+
};
1097+
const host = createServerHost([file1, packageJson, jquery, timestamps, cacheConfig]);
1098+
const installer = new (class extends Installer {
1099+
constructor() {
1100+
super(host, { typesRegistry: createTypesRegistry("jquery") });
1101+
}
1102+
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
1103+
const installedTypings = ["@types/jquery"];
1104+
const typingFiles = [jquery];
1105+
executeCommand(this, host, installedTypings, typingFiles, cb);
1106+
}
1107+
})();
1108+
1109+
const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller: installer });
1110+
projectService.openClientFile(file1.path);
1111+
1112+
checkNumberOfProjects(projectService, { inferredProjects: 1 });
1113+
const p = projectService.inferredProjects[0];
1114+
checkProjectActualFiles(p, [file1.path]);
1115+
1116+
installer.installAll(/*expectedCount*/ 1);
1117+
1118+
checkNumberOfProjects(projectService, { inferredProjects: 1 });
1119+
checkProjectActualFiles(p, [file1.path, jquery.path]);
1120+
});
1121+
1122+
it("non-expired cache entry (inferred project, should not install typings)", () => {
1123+
const file1 = {
1124+
path: "/a/b/app.js",
1125+
content: ""
1126+
};
1127+
const packageJson = {
1128+
path: "/a/b/package.json",
1129+
content: JSON.stringify({
1130+
name: "test",
1131+
dependencies: {
1132+
jquery: "^3.1.0"
1133+
}
1134+
})
1135+
};
1136+
const timestamps = {
1137+
path: "/a/data/timestamps.json",
1138+
content: JSON.stringify({
1139+
entries: {
1140+
"@types/jquery": Date.now()
1141+
}
1142+
})
1143+
};
1144+
const cacheConfig = {
1145+
path: "/a/data/package.json",
1146+
content: JSON.stringify({
1147+
dependencies: {
1148+
"types-registry": "^0.1.317"
1149+
},
1150+
devDependencies: {
1151+
"@types/jquery": "^3.2.16"
1152+
}
1153+
})
1154+
};
1155+
const jquery = {
1156+
path: "/a/data/node_modules/@types/jquery/index.d.ts",
1157+
content: "declare const $: { x: number }"
1158+
};
1159+
const host = createServerHost([file1, packageJson, timestamps, cacheConfig, jquery]);
1160+
const installer = new (class extends Installer {
1161+
constructor() {
1162+
super(host, { typesRegistry: createTypesRegistry("jquery") });
1163+
}
1164+
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
1165+
const installedTypings: string[] = [];
1166+
const typingFiles: FileOrFolder[] = [];
1167+
executeCommand(this, host, installedTypings, typingFiles, cb);
1168+
}
1169+
})();
1170+
1171+
const projectService = createProjectService(host, { useSingleInferredProject: true, typingsInstaller: installer });
1172+
projectService.openClientFile(file1.path);
1173+
1174+
checkNumberOfProjects(projectService, { inferredProjects: 1 });
1175+
const p = projectService.inferredProjects[0];
1176+
checkProjectActualFiles(p, [file1.path]);
1177+
1178+
installer.installAll(/*expectedCount*/ 0);
1179+
1180+
checkNumberOfProjects(projectService, { inferredProjects: 1 });
1181+
checkProjectActualFiles(p, [file1.path]);
1182+
});
10561183
});
10571184

10581185
describe("Validate package name:", () => {
@@ -1211,6 +1338,38 @@ namespace ts.projectSystem {
12111338
filesToWatch: ["/bower_components", "/node_modules"],
12121339
});
12131340
});
1341+
1342+
it("should install expired typings", () => {
1343+
const date = new Date();
1344+
date.setFullYear(date.getFullYear() - 1);
1345+
1346+
const app = {
1347+
path: "/a/app.js",
1348+
content: ""
1349+
};
1350+
const cachePath = "/a/cache/";
1351+
const commander = {
1352+
path: cachePath + "node_modules/@types/commander/index.d.ts",
1353+
content: "export let x: number"
1354+
};
1355+
const node = {
1356+
path: cachePath + "node_modules/@types/node/index.d.ts",
1357+
content: "export let y: number"
1358+
};
1359+
const host = createServerHost([app]);
1360+
const cache = createMapFromTemplate<JsTyping.CachedTyping>({
1361+
node: { typingLocation: node.path, timestamp: Date.now() },
1362+
commander: { typingLocation: commander.path, timestamp: date.getTime() }
1363+
});
1364+
const logger = trackingLogger();
1365+
const result = JsTyping.discoverTypings(host, logger.log, [app.path], getDirectoryPath(<Path>app.path), emptySafeList, cache, { enable: true }, ["http", "commander"]);
1366+
assert.deepEqual(logger.finish(), [
1367+
'Inferred typings from unresolved imports: ["node","commander"]',
1368+
'Result: {"cachedTypingPaths":["/a/cache/node_modules/@types/node/index.d.ts"],"newTypingNames":["commander"],"filesToWatch":["/a/bower_components","/a/node_modules"]}',
1369+
]);
1370+
assert.deepEqual(result.cachedTypingPaths, [node.path]);
1371+
assert.deepEqual(result.newTypingNames, ["commander"]);
1372+
});
12141373
});
12151374

12161375
describe("telemetry events", () => {

src/harness/virtualFileSystemWithWatch.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,9 +383,11 @@ interface Array<T> {}`
383383
ensureFileOrFolder(fileOrDirectory: FileOrFolder, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean) {
384384
if (isString(fileOrDirectory.content)) {
385385
const file = this.toFile(fileOrDirectory);
386-
Debug.assert(!this.fs.get(file.path));
387-
const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath));
388-
this.addFileOrFolderInFolder(baseFolder, file, ignoreWatchInvokedWithTriggerAsFileCreate);
386+
// file may already exist when updating existing type declaration file
387+
if (!this.fs.get(file.path)) {
388+
const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath));
389+
this.addFileOrFolderInFolder(baseFolder, file, ignoreWatchInvokedWithTriggerAsFileCreate);
390+
}
389391
}
390392
else {
391393
const fullPath = getNormalizedAbsolutePath(fileOrDirectory.path, this.currentDirectory);

src/services/jsTyping.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ namespace ts.JsTyping {
3737
if (currentMonth) {
3838
comparisonDate.setMonth(11);
3939
comparisonDate.setFullYear(comparisonDate.getFullYear() - 1);
40-
} else {
40+
}
41+
else {
4142
comparisonDate.setMonth(currentMonth - 1);
4243
}
4344
return !typing || typing.timestamp < comparisonDate.getTime();

0 commit comments

Comments
 (0)