From 287b6a53d474bfc3f99ea22dd2b3fd608f84f0e3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 9 Mar 2022 08:41:07 -0800 Subject: [PATCH] New test better tests UpdateFileSystem Plus fix associated mistakes in the code found by the test. --- src/server/editorServices.ts | 5 +- .../tsserver/applyChangesToOpenFiles.ts | 117 ++++-------------- src/vfs/fakesHosts.ts | 33 +++++ 3 files changed, 63 insertions(+), 92 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 98a9581753b..a4b991deb2a 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -757,7 +757,7 @@ namespace ts.server { readonly currentDirectory: NormalizedPath; readonly toCanonicalFileName: (f: string) => string; - public readonly host: ServerHost; + public host: ServerHost; public fs: vfs.FileSystem | undefined; public readonly logger: Logger; public readonly cancellationToken: HostCancellationToken; @@ -3704,7 +3704,8 @@ namespace ts.server { cwd: "/", // maybe not needed meta: { } // probably not needed }) - ;(this.session as any).host = new fakes.FakeCompilerHost(this.fs, {}) // TODO: Grab the real current options + ;(this as any).host = new fakes.FakeServerHost(this.fs, { executingFilePath: "TEST" }) + ;(this.session as any).host = this.host } if (createdFiles) { let it diff --git a/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts b/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts index f5314fb9e0d..fd2d2970973 100644 --- a/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts +++ b/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts @@ -1,10 +1,6 @@ namespace ts.projectSystem { // TODO: Make a separate file at some point describe("unittests:: tsserver:: updateFileSystem", () => { - interface Verify { - applyChangesToOpen: (session: TestSession) => void; - openFile1Again: (session: TestSession) => void; - } const config: protocol.FileSystemRequestArgs = { file: "/a/b/tsconfig.json", fileContent: "{}" @@ -17,18 +13,6 @@ namespace ts.projectSystem { file: "/a/b/app.ts", fileContent: "import { xyz } from './file3'; let x = xyz" }; - const appFile: File = { - path: "/a/b/app.ts", - content: "import { xyz } from './file3'; let x = xyz" - }; - const file3File: File = { - path: "/a/b/file3.ts", - content: "export let xyz = 1;" - } - const configFile: File = { - path: "/a/b/tsconfig.json", - content: "{}" - }; const file1: protocol.FileSystemRequestArgs = { file: "/a/b/commonFile1.ts", fileContent: "let x = 1" @@ -37,7 +21,7 @@ namespace ts.projectSystem { file: "/a/b/commonFile2.ts", fileContent: "let y = 1" }; - const libFileFile: protocol.FileSystemRequestArgs = { + const lib: protocol.FileSystemRequestArgs = { file: "/a/lib/lib.d.ts", fileContent: `/// interface Boolean {} @@ -56,16 +40,22 @@ interface Array { length: number; [n: number]: T; }` return `// some copy right notice ${'content' in file ? file.content : file.fileContent}`; } - function verify({ applyChangesToOpen, openFile1Again }: Verify) { - // TODO: Replace with createMemfsServerHost - const host = createServerHost([appFile, file3File, commonFile1, commonFile2, libFile, configFile]); - // const host = createServerHost([app, file3, commonFile1, commonFile2, libFile, configFile]); + it("with updateOpen request", () => { + // 1. Create a server host with no files, then updateFS and make sure everything works as before + // Things still to test + // 2. Send another updateFS request and assert that the vfs content changes + // 3. Send another updateFS request and assert that the internal reported content changes + // 4. Send a close message (or whatever will write a file?) and make sure that the vfs state is updated + // after file watchers are implemented: + // 5. send updateFS request with a create/update/delete of a watched file, assert that file watchers fired + // 6. probably some other watcher tests, not sure what + const host = createServerHost([]); // old path goes into virtualFileSystemWithWatch.ts, so I guess it's getting the old host, not the replaced one const session = createSession(host); session.executeCommandSeq({ command: protocol.CommandTypes.UpdateFileSystem, arguments:{ fileSystem: 'memfs', - created: [app, file3, file1, file2, libFileFile, config], + created: [app, file3, file1, file2, lib, config], deleted: [], // string[]; updated: [], //FileSystemRequestArgs[]; } @@ -89,35 +79,30 @@ ${'content' in file ? file.content : file.fileContent}`; }); verifyProjectVersion(project, 2); - // TODO: Verify file watchers have updated // Verify Texts verifyText(service, commonFile1.path, commonFile1.content); verifyText(service, commonFile2.path, commonFile2.content); verifyText(service, app.file, app.fileContent!); verifyText(service, file3.file, fileContentWithComment(file3)); - // Apply changes - applyChangesToOpen(session); - - // Verify again + session.executeCommandSeq({ + command: protocol.CommandTypes.UpdateFileSystem, + arguments:{ + fileSystem: 'memfs', + created: [], + deleted: [], // string[]; + updated: [], //FileSystemRequestArgs[]; + } + }); verifyProjectVersion(project, 3); - // Open file contents - verifyText(service, commonFile1.path, fileContentWithComment(commonFile1)); - verifyText(service, commonFile2.path, fileContentWithComment(commonFile2)); - verifyText(service, app.file, "let zzz = 10;let zz = 10;import { xyz } from './file3'; let x = xyz"); - verifyText(service, file3.file, file3.fileContent!); - // Open file1 again - openFile1Again(session); - assert.isTrue(service.getScriptInfo(commonFile1.path)!.isScriptOpen()); - - // Verify that file1 contents are changed - verifyProjectVersion(project, 4); + // Verify Texts verifyText(service, commonFile1.path, commonFile1.content); - verifyText(service, commonFile2.path, fileContentWithComment(commonFile2)); - verifyText(service, app.file, "let zzz = 10;let zz = 10;import { xyz } from './file3'; let x = xyz"); - verifyText(service, file3.file, file3.fileContent!); - } + verifyText(service, commonFile2.path, commonFile2.content); + verifyText(service, app.file, app.fileContent!); + verifyText(service, file3.file, fileContentWithComment(file3)); + + }); function verifyText(service: server.ProjectService, file: string, expected: string) { const info = service.getScriptInfo(file)!; @@ -129,54 +114,6 @@ ${'content' in file ? file.content : file.fileContent}`; function verifyProjectVersion(project: server.Project, expected: number) { assert.equal(Number(project.getProjectVersion()), expected); } - it("with updateOpen request", () => { - verify({ - applyChangesToOpen: session => session.executeCommandSeq({ - command: protocol.CommandTypes.UpdateOpen, - arguments: { - openFiles: [ - { - file: commonFile1.path, - fileContent: fileContentWithComment(commonFile1) - }, - { - file: commonFile2.path, - fileContent: fileContentWithComment(commonFile2) - } - ], - changedFiles: [ - { - fileName: app.file, - textChanges: [ - { - start: { line: 1, offset: 1 }, - end: { line: 1, offset: 1 }, - newText: "let zzz = 10;", - }, - { - start: { line: 1, offset: 1 }, - end: { line: 1, offset: 1 }, - newText: "let zz = 10;", - } - ] - } - ], - closedFiles: [ - file3.file - ] - } - }), - openFile1Again: session => session.executeCommandSeq({ - command: protocol.CommandTypes.UpdateOpen, - arguments: { - openFiles: [{ - file: commonFile1.path, - fileContent: commonFile1.content - }] - } - }), - }); - }); }) describe("unittests:: tsserver:: applyChangesToOpenFiles", () => { const configFile: File = { diff --git a/src/vfs/fakesHosts.ts b/src/vfs/fakesHosts.ts index 6a687bdab63..29063daaac8 100644 --- a/src/vfs/fakesHosts.ts +++ b/src/vfs/fakesHosts.ts @@ -214,6 +214,39 @@ namespace fakes { } } + /** + * @implements {server.ServerHost} but that would create a circular dependency + */ + export class FakeServerHost extends System { + watchFile(/*path: string, callback: ts.FileWatcherCallback, pollingInterval?: number, options?: ts.WatchOptions*/): ts.FileWatcher { + throw new Error("Not implemented: Still need to steal implementation from virtualFileSystemWithWatch.ts") + return { + close() { + } + } + } + watchDirectory(/*path: string, callback: ts.DirectoryWatcherCallback, recursive?: boolean, options?: ts.WatchOptions*/): ts.FileWatcher { + throw new Error("Not implemented: Still need to steal implementation from virtualFileSystemWithWatch.ts") + return { + close() { + } + } + } + setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any { + // TODO: Probably want to do a fake thing, actually (or parametrised by the constructor) + return setTimeout(callback, ms, ...args) + } + clearTimeout(timeoutId: any): void { + clearTimeout(timeoutId) + } + setImmediate(callback: (...args: any[]) => void, ...args: any[]): any { + return setImmediate(callback, ...args) + } + clearImmediate(timeoutId: any): void { + clearImmediate(timeoutId) + } + } + /** * A fake `ts.CompilerHost` that leverages a virtual file system. */