[WIP] initial version of tests

This commit is contained in:
Vladimir Matveev
2016-08-13 23:09:14 -07:00
parent d07261af4f
commit 253d5d6ce9
6 changed files with 150 additions and 26 deletions
@@ -1,4 +1,5 @@
/// <reference path="..\harness.ts" />
/// <reference path="../../server/typingsInstaller/typingsInstaller.ts" />
namespace ts {
function notImplemented(): any {
@@ -26,6 +27,57 @@ namespace ts {
content: libFileContent
};
abstract class TestTypingsInstaller extends server.typingsInstaller.TypingsInstaller implements server.ITypingsInstaller {
protected projectService: server.ProjectService;
constructor(private readonly host: server.ServerHost) {
super();
}
abstract cachePath: string;
safeFileList = <Path>"";
packageNameToTypingLocation: Map<string> = {};
postInstallActions: (( map: (t: string[]) => string[]) => void)[] = [];
runPostInstallActions(map: (t: string[]) => string[]) {
for (const f of this.postInstallActions) {
f(map);
}
this.postInstallActions = [];
}
attach(projectService: server.ProjectService) {
this.projectService = projectService;
}
getInstallTypingHost() {
return this.host;
}
installPackage(packageName: string) {
return true;
}
isPackageInstalled(packageName: string) {
return true;
}
runTsd(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void) {
this.postInstallActions.push(map => {
postInstallAction(map(typingsToInstall));
})
}
sendResponse(response: server.InstallTypingsResponse) {
this.projectService.updateTypingsForProject(response);
}
enqueueInstallTypingsRequest(project: server.Project, typingOptions: TypingOptions) {
const request = server.createInstallTypingsRequest(project, typingOptions, this.safeFileList, this.packageNameToTypingLocation, this.cachePath);
this.install(request)
}
}
function getExecutingFilePathFromLibFile(libFilePath: string): string {
return combinePaths(getDirectoryPath(libFile.path), "tsc.js");
}
@@ -1408,4 +1460,61 @@ namespace ts {
checkNumberOfProjects(projectService, { configuredProjects: 0 });
});
});
describe("typings installer", () => {
it("configured projects (tsd installed) 1", () => {
const file1 = {
path: "/a/b/app.js",
content: ""
};
const tsconfig = {
path: "/a/b/tsconfig.json",
content: JSON.stringify({
compilerOptions: {
allowJs: true
},
typingOptions: {
enableAutoDiscovery: true
}
})
};
const packageJson = {
path: "/a/b/package.json",
content: JSON.stringify({
name: "test",
dependencies: {
jquery: "^3.1.0"
}
})
};
const jquery = {
path: "/a/data/jquery/jquery.d.ts",
content: "declare const $: { x: number }"
};
const host = createServerHost([file1, tsconfig, packageJson]);
class TypingInstaller extends TestTypingsInstaller {
cachePath = "/a/data/";
constructor(host: server.ServerHost) {
super(host)
}
};
const installer = new TypingInstaller(host);
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useSingleInferredProject*/ true, installer);
projectService.openClientFile(file1.path);
checkNumberOfProjects(projectService, { configuredProjects: 1 })
const p = projectService.configuredProjects[0];
checkProjectActualFiles(p, [ file1.path ]);
installer.runPostInstallActions(t => {
assert.deepEqual(t, ["jquery"]);
host.reloadFS([file1, tsconfig, packageJson, jquery]);
return ["jquery/jquery.d.ts"];
});
checkNumberOfProjects(projectService, { configuredProjects: 1 })
checkProjectActualFiles(p, [ file1.path, jquery.path ]);
});
});
}
+15 -1
View File
@@ -182,7 +182,12 @@ namespace ts.server {
this.toCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
this.directoryWatchers = new DirectoryWatchers(this);
this.throttledOperations = new ThrottledOperations(host);
this.typingsCache = new TypingsCache(typingsInstaller || nullTypingsInstaller);
const installer = typingsInstaller || nullTypingsInstaller;
installer.attach(this);
this.typingsCache = new TypingsCache(installer);
// ts.disableIncrementalParsing = true;
this.hostConfiguration = {
@@ -201,6 +206,15 @@ namespace ts.server {
this.ensureInferredProjectsUpToDate();
}
updateTypingsForProject(response: InstallTypingsResponse): void {
const project = this.findProject(response.projectName);
if (!project) {
return;
}
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings);
project.updateGraph();
}
setCompilerOptionsForInferredProjects(compilerOptions: CompilerOptions): void {
this.compilerOptionsForInferredProjects = compilerOptions;
for (const proj of this.inferredProjects) {
+10 -14
View File
@@ -161,7 +161,7 @@ namespace ts.server {
class NodeTypingsInstaller implements ITypingsInstaller {
private installer: NodeChildProcess;
private session: Session;
private projectService: ProjectService;
private cachePath: string;
constructor(private readonly logger: server.Logger) {
@@ -176,8 +176,8 @@ namespace ts.server {
}
}
bind(session: Session) {
this.session = session;
attach(projectService: ProjectService) {
this.projectService = projectService;
if (this.logger.hasLevel(LogLevel.requestTime)) {
this.logger.info("Binding...")
}
@@ -187,16 +187,13 @@ namespace ts.server {
}
enqueueInstallTypingsRequest(project: Project, typingOptions: TypingOptions): void {
const request: InstallTypingsRequest = {
projectName: project.getProjectName(),
fileNames: project.getFileNames(),
compilerOptions: project.getCompilerOptions(),
const request = createInstallTypingsRequest(
project,
typingOptions,
projectRootPath: <Path>(project.projectKind === ProjectKind.Inferred ? "" : getDirectoryPath(project.getProjectName())), // TODO: fixme
safeListPath: <Path>(combinePaths(process.cwd(), "typingSafeList.json")), // TODO: fixme
packageNameToTypingLocation: {}, // TODO: fixme
cachePath: this.cachePath
};
/*safeListPath*/ <Path>(combinePaths(process.cwd(), "typingSafeList.json")), // TODO: fixme
/*packageNameToTypingLocation*/ {}, // TODO: fixme
this.cachePath
);
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Sending request: ${JSON.stringify(request)}`);
}
@@ -207,14 +204,13 @@ namespace ts.server {
if (this.logger.hasLevel(LogLevel.verbose)) {
this.logger.info(`Received response: ${JSON.stringify(response)}`)
}
this.session.onTypingsInstalled(response);
this.projectService.updateTypingsForProject(response);
}
}
class IOSession extends Session {
constructor(host: ServerHost, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean, logger: server.Logger) {
super(host, cancellationToken, useSingleInferredProject, new NodeTypingsInstaller(logger), Buffer.byteLength, maxUncompressedMessageSize, compress, process.hrtime, logger);
(<NodeTypingsInstaller>this.typingsInstaller).bind(this);
}
exit() {
-10
View File
@@ -1452,16 +1452,6 @@ namespace ts.server {
}
}
public onTypingsInstalled(response: InstallTypingsResponse) {
const project = this.projectService.findProject(response.projectName);
if (!project) {
return;
}
this.projectService.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings);
project.updateGraph();
}
public onMessage(message: string) {
this.gcTimer.scheduleCollect();
let start: number[];
+3 -1
View File
@@ -3,10 +3,12 @@
namespace ts.server {
export interface ITypingsInstaller {
enqueueInstallTypingsRequest(p: Project, typingOptions: TypingOptions): void;
attach(projectService: ProjectService): void;
}
export const nullTypingsInstaller: ITypingsInstaller = {
enqueueInstallTypingsRequest: () => {}
enqueueInstallTypingsRequest: () => {},
attach: (projectService: ProjectService) => {}
};
class TypingsCacheEntry {
+13
View File
@@ -30,6 +30,19 @@ namespace ts.server {
export type Types = Err | Info | Perf;
}
export function createInstallTypingsRequest(project: Project, typingOptions: TypingOptions, safeListPath: Path, packageNameToTypingLocation: Map<string>, cachePath: string): InstallTypingsRequest {
return {
projectName: project.getProjectName(),
fileNames: project.getFileNames(),
compilerOptions: project.getCompilerOptions(),
typingOptions,
projectRootPath: <Path>(project.projectKind === ProjectKind.Inferred ? "" : getDirectoryPath(project.getProjectName())), // TODO: fixme
safeListPath,
packageNameToTypingLocation,
cachePath
};
}
export namespace Errors {
export const NoProject = new Error("No Project.");
export const ProjectLanguageServiceDisabled = new Error("The project's language service is disabled.");