From 39ec69e26e972757a626f61ac2fce156f7b6e4fa Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 7 Dec 2018 12:34:16 -0800 Subject: [PATCH] Separate out tests for project loading events into their own unittest file --- src/testRunner/tsconfig.json | 1 + src/testRunner/unittests/tsserverHelpers.ts | 140 ++++----- .../unittests/tsserverProjectLoadingEvents.ts | 193 +++++++++++++ .../unittests/tsserverProjectSystem.ts | 268 ------------------ 4 files changed, 266 insertions(+), 336 deletions(-) create mode 100644 src/testRunner/unittests/tsserverProjectLoadingEvents.ts diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index a95bc106fb1..3b8308af890 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -88,6 +88,7 @@ "unittests/tsconfigParsing.ts", "unittests/tscWatchEmit.ts", "unittests/tscWatchMode.ts", + "unittests/tsserverProjectLoadingEvents.ts", "unittests/tsserverProjectSystem.ts", "unittests/typingsInstaller.ts", "unittests/versionCache.ts", diff --git a/src/testRunner/unittests/tsserverHelpers.ts b/src/testRunner/unittests/tsserverHelpers.ts index f5113b768fc..18e6f5c6194 100644 --- a/src/testRunner/unittests/tsserverHelpers.ts +++ b/src/testRunner/unittests/tsserverHelpers.ts @@ -15,13 +15,13 @@ namespace ts.projectSystem { export import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories; export import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed; - //const outputEventRegex = /Content\-Length: [\d]+\r\n\r\n/; - //function mapOutputToJson(s: string) { - // return convertToObject( - // parseJsonText("json.json", s.replace(outputEventRegex, "")), - // [] - // ); - //} + const outputEventRegex = /Content\-Length: [\d]+\r\n\r\n/; + export function mapOutputToJson(s: string) { + return convertToObject( + parseJsonText("json.json", s.replace(outputEventRegex, "")), + [] + ); + } export const customTypesMap = { path: "/typesMap.json", @@ -330,39 +330,39 @@ namespace ts.projectSystem { return new TestSession({ ...sessionOptions, ...opts }); } - //function createSessionWithEventTracking(host: server.ServerHost, eventName: T["eventName"], ...eventNames: T["eventName"][]) { - // const events: T[] = []; - // const session = createSession(host, { - // eventHandler: e => { - // if (e.eventName === eventName || eventNames.some(eventName => e.eventName === eventName)) { - // events.push(e as T); - // } - // } - // }); + export function createSessionWithEventTracking(host: server.ServerHost, eventName: T["eventName"], ...eventNames: T["eventName"][]) { + const events: T[] = []; + const session = createSession(host, { + eventHandler: e => { + if (e.eventName === eventName || eventNames.some(eventName => e.eventName === eventName)) { + events.push(e as T); + } + } + }); - // return { session, events }; - //} + return { session, events }; + } - //function createSessionWithDefaultEventHandler(host: TestServerHost, eventNames: T["event"] | T["event"][], opts: Partial = {}) { - // const session = createSession(host, { canUseEvents: true, ...opts }); + export function createSessionWithDefaultEventHandler(host: TestServerHost, eventNames: T["event"] | T["event"][], opts: Partial = {}) { + const session = createSession(host, { canUseEvents: true, ...opts }); - // return { - // session, - // getEvents, - // clearEvents - // }; + return { + session, + getEvents, + clearEvents + }; - // function getEvents() { - // return mapDefined(host.getOutput(), s => { - // const e = mapOutputToJson(s); - // return (isArray(eventNames) ? eventNames.some(eventName => e.event === eventName) : e.event === eventNames) ? e as T : undefined; - // }); - // } + function getEvents() { + return mapDefined(host.getOutput(), s => { + const e = mapOutputToJson(s); + return (isArray(eventNames) ? eventNames.some(eventName => e.event === eventName) : e.event === eventNames) ? e as T : undefined; + }); + } - // function clearEvents() { - // session.clearMessages(); - // } - //} + function clearEvents() { + session.clearMessages(); + } + } export interface CreateProjectServiceParameters { cancellationToken?: HostCancellationToken; @@ -467,23 +467,25 @@ namespace ts.projectSystem { // checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path)!.fileName), expectedFiles.map(file => file.path)); //} - //function protocolLocationFromSubstring(str: string, substring: string): protocol.Location { - // const start = str.indexOf(substring); - // Debug.assert(start !== -1); - // return protocolToLocation(str)(start); - //} - //function protocolToLocation(text: string): (pos: number) => protocol.Location { - // const lineStarts = computeLineStarts(text); - // return pos => { - // const x = computeLineAndCharacterOfPosition(lineStarts, pos); - // return { line: x.line + 1, offset: x.character + 1 }; - // }; - //} - //function protocolTextSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): protocol.TextSpan { - // const span = textSpanFromSubstring(str, substring, options); - // const toLocation = protocolToLocation(str); - // return { start: toLocation(span.start), end: toLocation(textSpanEnd(span)) }; - //} + export function protocolLocationFromSubstring(str: string, substring: string): protocol.Location { + const start = str.indexOf(substring); + Debug.assert(start !== -1); + return protocolToLocation(str)(start); + } + + function protocolToLocation(text: string): (pos: number) => protocol.Location { + const lineStarts = computeLineStarts(text); + return pos => { + const x = computeLineAndCharacterOfPosition(lineStarts, pos); + return { line: x.line + 1, offset: x.character + 1 }; + }; + } + + export function protocolTextSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): protocol.TextSpan { + const span = textSpanFromSubstring(str, substring, options); + const toLocation = protocolToLocation(str); + return { start: toLocation(span.start), end: toLocation(textSpanEnd(span)) }; + } //function protocolRenameSpanFromSubstring( // str: string, // substring: string, @@ -492,11 +494,12 @@ namespace ts.projectSystem { //): protocol.RenameTextSpan { // return { ...protocolTextSpanFromSubstring(str, substring, options), ...prefixSuffixText }; //} - //function textSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): TextSpan { - // const start = nthIndexOf(str, substring, options ? options.index : 0); - // Debug.assert(start !== -1); - // return createTextSpan(start, substring.length); - //} + + export function textSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): TextSpan { + const start = nthIndexOf(str, substring, options ? options.index : 0); + Debug.assert(start !== -1); + return createTextSpan(start, substring.length); + } //function protocolFileLocationFromSubstring(file: File, substring: string): protocol.FileLocationRequestArgs { // return { file: file.path, ...protocolLocationFromSubstring(file.content, substring) }; //} @@ -509,18 +512,19 @@ namespace ts.projectSystem { //function renameLocation(file: File, substring: string, options?: SpanFromSubstringOptions): RenameLocation { // return documentSpanFromSubstring(file, substring, options); //} - //interface SpanFromSubstringOptions { - // readonly index: number; - //} - //function nthIndexOf(str: string, substr: string, n: number): number { - // let index = -1; - // for (; n >= 0; n--) { - // index = str.indexOf(substr, index + 1); - // if (index === -1) return -1; - // } - // return index; - //} + export interface SpanFromSubstringOptions { + readonly index: number; + } + + function nthIndexOf(str: string, substr: string, n: number): number { + let index = -1; + for (; n >= 0; n--) { + index = str.indexOf(substr, index + 1); + if (index === -1) return -1; + } + return index; + } /** * Test server cancellation token used to mock host token cancellation requests. diff --git a/src/testRunner/unittests/tsserverProjectLoadingEvents.ts b/src/testRunner/unittests/tsserverProjectLoadingEvents.ts new file mode 100644 index 00000000000..0ff256bd692 --- /dev/null +++ b/src/testRunner/unittests/tsserverProjectLoadingEvents.ts @@ -0,0 +1,193 @@ +namespace ts.projectSystem { + describe("tsserverProjectLoadingEvents:: ProjectLoadingStart and ProjectLoadingFinish events", () => { + const projectRoot = "/user/username/projects"; + const aTs: File = { + path: `${projectRoot}/a/a.ts`, + content: "export class A { }" + }; + const configA: File = { + path: `${projectRoot}/a/tsconfig.json`, + content: "{}" + }; + const bTsPath = `${projectRoot}/b/b.ts`; + const configBPath = `${projectRoot}/b/tsconfig.json`; + const files = [libFile, aTs, configA]; + + function verifyProjectLoadingStartAndFinish(createSession: (host: TestServerHost) => { + session: TestSession; + getNumberOfEvents: () => number; + clearEvents: () => void; + verifyProjectLoadEvents: (expected: [server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent]) => void; + }) { + function createSessionToVerifyEvent(files: ReadonlyArray) { + const host = createServerHost(files); + const originalReadFile = host.readFile; + const { session, getNumberOfEvents, clearEvents, verifyProjectLoadEvents } = createSession(host); + host.readFile = file => { + if (file === configA.path || file === configBPath) { + assert.equal(getNumberOfEvents(), 1, "Event for loading is sent before reading config file"); + } + return originalReadFile.call(host, file); + }; + const service = session.getProjectService(); + return { host, session, verifyEvent, verifyEventWithOpenTs, service, getNumberOfEvents }; + + function verifyEvent(project: server.Project, reason: string) { + verifyProjectLoadEvents([ + { eventName: server.ProjectLoadingStartEvent, data: { project, reason } }, + { eventName: server.ProjectLoadingFinishEvent, data: { project } } + ]); + clearEvents(); + } + + function verifyEventWithOpenTs(file: File, configPath: string, configuredProjects: number) { + openFilesForSession([file], session); + checkNumberOfProjects(service, { configuredProjects }); + const project = service.configuredProjects.get(configPath)!; + assert.isDefined(project); + verifyEvent(project, `Creating possible configured project for ${file.path} to open`); + } + } + + it("when project is created by open file", () => { + const bTs: File = { + path: bTsPath, + content: "export class B {}" + }; + const configB: File = { + path: configBPath, + content: "{}" + }; + const { verifyEventWithOpenTs } = createSessionToVerifyEvent(files.concat(bTs, configB)); + verifyEventWithOpenTs(aTs, configA.path, 1); + verifyEventWithOpenTs(bTs, configB.path, 2); + }); + + it("when change is detected in the config file", () => { + const { host, verifyEvent, verifyEventWithOpenTs, service } = createSessionToVerifyEvent(files); + verifyEventWithOpenTs(aTs, configA.path, 1); + + host.writeFile(configA.path, configA.content); + host.checkTimeoutQueueLengthAndRun(2); + const project = service.configuredProjects.get(configA.path)!; + verifyEvent(project, `Change in config file detected`); + }); + + it("when opening original location project", () => { + const aDTs: File = { + path: `${projectRoot}/a/a.d.ts`, + content: `export declare class A { +} +//# sourceMappingURL=a.d.ts.map +` + }; + const aDTsMap: File = { + path: `${projectRoot}/a/a.d.ts.map`, + content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}` + }; + const bTs: File = { + path: bTsPath, + content: `import {A} from "../a/a"; new A();` + }; + const configB: File = { + path: configBPath, + content: JSON.stringify({ + references: [{ path: "../a" }] + }) + }; + + const { service, session, verifyEventWithOpenTs, verifyEvent } = createSessionToVerifyEvent(files.concat(aDTs, aDTsMap, bTs, configB)); + verifyEventWithOpenTs(bTs, configB.path, 1); + + session.executeCommandSeq({ + command: protocol.CommandTypes.References, + arguments: { + file: bTs.path, + ...protocolLocationFromSubstring(bTs.content, "A()") + } + }); + + checkNumberOfProjects(service, { configuredProjects: 2 }); + const project = service.configuredProjects.get(configA.path)!; + assert.isDefined(project); + verifyEvent(project, `Creating project for original file: ${aTs.path} for location: ${aDTs.path}`); + }); + + describe("with external projects and config files ", () => { + const projectFileName = `${projectRoot}/a/project.csproj`; + + function createSession(lazyConfiguredProjectsFromExternalProject: boolean) { + const { session, service, verifyEvent: verifyEventWorker, getNumberOfEvents } = createSessionToVerifyEvent(files); + service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); + service.openExternalProject({ + projectFileName, + rootFiles: toExternalFiles([aTs.path, configA.path]), + options: {} + }); + checkNumberOfProjects(service, { configuredProjects: 1 }); + return { session, service, verifyEvent, getNumberOfEvents }; + + function verifyEvent() { + const projectA = service.configuredProjects.get(configA.path)!; + assert.isDefined(projectA); + verifyEventWorker(projectA, `Creating configured project in external project: ${projectFileName}`); + } + } + + it("when lazyConfiguredProjectsFromExternalProject is false", () => { + const { verifyEvent } = createSession(/*lazyConfiguredProjectsFromExternalProject*/ false); + verifyEvent(); + }); + + it("when lazyConfiguredProjectsFromExternalProject is true and file is opened", () => { + const { verifyEvent, getNumberOfEvents, session } = createSession(/*lazyConfiguredProjectsFromExternalProject*/ true); + assert.equal(getNumberOfEvents(), 0); + + openFilesForSession([aTs], session); + verifyEvent(); + }); + + it("when lazyConfiguredProjectsFromExternalProject is disabled", () => { + const { verifyEvent, getNumberOfEvents, service } = createSession(/*lazyConfiguredProjectsFromExternalProject*/ true); + assert.equal(getNumberOfEvents(), 0); + + service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: false } }); + verifyEvent(); + }); + }); + } + + describe("when using event handler", () => { + verifyProjectLoadingStartAndFinish(host => { + const { session, events } = createSessionWithEventTracking(host, server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent); + return { + session, + getNumberOfEvents: () => events.length, + clearEvents: () => events.length = 0, + verifyProjectLoadEvents: expected => assert.deepEqual(events, expected) + }; + }); + }); + + describe("when using default event handler", () => { + verifyProjectLoadingStartAndFinish(host => { + const { session, getEvents, clearEvents } = createSessionWithDefaultEventHandler(host, [server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent]); + return { + session, + getNumberOfEvents: () => getEvents().length, + clearEvents, + verifyProjectLoadEvents + }; + + function verifyProjectLoadEvents(expected: [server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent]) { + const actual = getEvents().map(e => ({ eventName: e.event, data: e.body })); + const mappedExpected = expected.map(e => { + const { project, ...rest } = e.data; + return { eventName: e.eventName, data: { projectName: project.getProjectName(), ...rest } }; + }); + assert.deepEqual(actual, mappedExpected); + } + }); + }); + }); +} diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index 214ddabdb85..74522bcca8d 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -1,46 +1,4 @@ namespace ts.projectSystem { - const outputEventRegex = /Content\-Length: [\d]+\r\n\r\n/; - function mapOutputToJson(s: string) { - return convertToObject( - parseJsonText("json.json", s.replace(outputEventRegex, "")), - [] - ); - } - - function createSessionWithEventTracking(host: server.ServerHost, eventName: T["eventName"], ...eventNames: T["eventName"][]) { - const events: T[] = []; - const session = createSession(host, { - eventHandler: e => { - if (e.eventName === eventName || eventNames.some(eventName => e.eventName === eventName)) { - events.push(e as T); - } - } - }); - - return { session, events }; - } - - function createSessionWithDefaultEventHandler(host: TestServerHost, eventNames: T["event"] | T["event"][], opts: Partial = {}) { - const session = createSession(host, { canUseEvents: true, ...opts }); - - return { - session, - getEvents, - clearEvents - }; - - function getEvents() { - return mapDefined(host.getOutput(), s => { - const e = mapOutputToJson(s); - return (isArray(eventNames) ? eventNames.some(eventName => e.event === eventName) : e.event === eventNames) ? e as T : undefined; - }); - } - - function clearEvents() { - session.clearMessages(); - } - } - function getNodeModuleDirectories(dir: string) { return getRootsToWatchWithAncestorDirectory(dir, nodeModules); } @@ -57,23 +15,6 @@ namespace ts.projectSystem { checkArray("ScriptInfos files", arrayFrom(projectService.filenameToScriptInfo.values(), info => info.fileName), expectedFiles); } - function protocolLocationFromSubstring(str: string, substring: string): protocol.Location { - const start = str.indexOf(substring); - Debug.assert(start !== -1); - return protocolToLocation(str)(start); - } - function protocolToLocation(text: string): (pos: number) => protocol.Location { - const lineStarts = computeLineStarts(text); - return pos => { - const x = computeLineAndCharacterOfPosition(lineStarts, pos); - return { line: x.line + 1, offset: x.character + 1 }; - }; - } - function protocolTextSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): protocol.TextSpan { - const span = textSpanFromSubstring(str, substring, options); - const toLocation = protocolToLocation(str); - return { start: toLocation(span.start), end: toLocation(textSpanEnd(span)) }; - } function protocolRenameSpanFromSubstring( str: string, substring: string, @@ -82,11 +23,6 @@ namespace ts.projectSystem { ): protocol.RenameTextSpan { return { ...protocolTextSpanFromSubstring(str, substring, options), ...prefixSuffixText }; } - function textSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): TextSpan { - const start = nthIndexOf(str, substring, options ? options.index : 0); - Debug.assert(start !== -1); - return createTextSpan(start, substring.length); - } function protocolFileLocationFromSubstring(file: File, substring: string): protocol.FileLocationRequestArgs { return { file: file.path, ...protocolLocationFromSubstring(file.content, substring) }; } @@ -99,18 +35,6 @@ namespace ts.projectSystem { function renameLocation(file: File, substring: string, options?: SpanFromSubstringOptions): RenameLocation { return documentSpanFromSubstring(file, substring, options); } - interface SpanFromSubstringOptions { - readonly index: number; - } - - function nthIndexOf(str: string, substr: string, n: number): number { - let index = -1; - for (; n >= 0; n--) { - index = str.indexOf(substr, index + 1); - if (index === -1) return -1; - } - return index; - } interface ErrorInformation { diagnosticMessage: DiagnosticMessage; @@ -7843,198 +7767,6 @@ new C();` }); }); - describe("tsserverProjectSystem ProjectLoadingStart and ProjectLoadingFinish events", () => { - const projectRoot = "/user/username/projects"; - const aTs: File = { - path: `${projectRoot}/a/a.ts`, - content: "export class A { }" - }; - const configA: File = { - path: `${projectRoot}/a/tsconfig.json`, - content: "{}" - }; - const bTsPath = `${projectRoot}/b/b.ts`; - const configBPath = `${projectRoot}/b/tsconfig.json`; - const files = [libFile, aTs, configA]; - - function verifyProjectLoadingStartAndFinish(createSession: (host: TestServerHost) => { - session: TestSession; - getNumberOfEvents: () => number; - clearEvents: () => void; - verifyProjectLoadEvents: (expected: [server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent]) => void; - }) { - function createSessionToVerifyEvent(files: ReadonlyArray) { - const host = createServerHost(files); - const originalReadFile = host.readFile; - const { session, getNumberOfEvents, clearEvents, verifyProjectLoadEvents } = createSession(host); - host.readFile = file => { - if (file === configA.path || file === configBPath) { - assert.equal(getNumberOfEvents(), 1, "Event for loading is sent before reading config file"); - } - return originalReadFile.call(host, file); - }; - const service = session.getProjectService(); - return { host, session, verifyEvent, verifyEventWithOpenTs, service, getNumberOfEvents }; - - function verifyEvent(project: server.Project, reason: string) { - verifyProjectLoadEvents([ - { eventName: server.ProjectLoadingStartEvent, data: { project, reason } }, - { eventName: server.ProjectLoadingFinishEvent, data: { project } } - ]); - clearEvents(); - } - - function verifyEventWithOpenTs(file: File, configPath: string, configuredProjects: number) { - openFilesForSession([file], session); - checkNumberOfProjects(service, { configuredProjects }); - const project = service.configuredProjects.get(configPath)!; - assert.isDefined(project); - verifyEvent(project, `Creating possible configured project for ${file.path} to open`); - } - } - - it("when project is created by open file", () => { - const bTs: File = { - path: bTsPath, - content: "export class B {}" - }; - const configB: File = { - path: configBPath, - content: "{}" - }; - const { verifyEventWithOpenTs } = createSessionToVerifyEvent(files.concat(bTs, configB)); - verifyEventWithOpenTs(aTs, configA.path, 1); - verifyEventWithOpenTs(bTs, configB.path, 2); - }); - - it("when change is detected in the config file", () => { - const { host, verifyEvent, verifyEventWithOpenTs, service } = createSessionToVerifyEvent(files); - verifyEventWithOpenTs(aTs, configA.path, 1); - - host.writeFile(configA.path, configA.content); - host.checkTimeoutQueueLengthAndRun(2); - const project = service.configuredProjects.get(configA.path)!; - verifyEvent(project, `Change in config file detected`); - }); - - it("when opening original location project", () => { - const aDTs: File = { - path: `${projectRoot}/a/a.d.ts`, - content: `export declare class A { -} -//# sourceMappingURL=a.d.ts.map -` - }; - const aDTsMap: File = { - path: `${projectRoot}/a/a.d.ts.map`, - content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}` - }; - const bTs: File = { - path: bTsPath, - content: `import {A} from "../a/a"; new A();` - }; - const configB: File = { - path: configBPath, - content: JSON.stringify({ - references: [{ path: "../a" }] - }) - }; - - const { service, session, verifyEventWithOpenTs, verifyEvent } = createSessionToVerifyEvent(files.concat(aDTs, aDTsMap, bTs, configB)); - verifyEventWithOpenTs(bTs, configB.path, 1); - - session.executeCommandSeq({ - command: protocol.CommandTypes.References, - arguments: { - file: bTs.path, - ...protocolLocationFromSubstring(bTs.content, "A()") - } - }); - - checkNumberOfProjects(service, { configuredProjects: 2 }); - const project = service.configuredProjects.get(configA.path)!; - assert.isDefined(project); - verifyEvent(project, `Creating project for original file: ${aTs.path} for location: ${aDTs.path}`); - }); - - describe("with external projects and config files ", () => { - const projectFileName = `${projectRoot}/a/project.csproj`; - - function createSession(lazyConfiguredProjectsFromExternalProject: boolean) { - const { session, service, verifyEvent: verifyEventWorker, getNumberOfEvents } = createSessionToVerifyEvent(files); - service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); - service.openExternalProject({ - projectFileName, - rootFiles: toExternalFiles([aTs.path, configA.path]), - options: {} - }); - checkNumberOfProjects(service, { configuredProjects: 1 }); - return { session, service, verifyEvent, getNumberOfEvents }; - - function verifyEvent() { - const projectA = service.configuredProjects.get(configA.path)!; - assert.isDefined(projectA); - verifyEventWorker(projectA, `Creating configured project in external project: ${projectFileName}`); - } - } - - it("when lazyConfiguredProjectsFromExternalProject is false", () => { - const { verifyEvent } = createSession(/*lazyConfiguredProjectsFromExternalProject*/ false); - verifyEvent(); - }); - - it("when lazyConfiguredProjectsFromExternalProject is true and file is opened", () => { - const { verifyEvent, getNumberOfEvents, session } = createSession(/*lazyConfiguredProjectsFromExternalProject*/ true); - assert.equal(getNumberOfEvents(), 0); - - openFilesForSession([aTs], session); - verifyEvent(); - }); - - it("when lazyConfiguredProjectsFromExternalProject is disabled", () => { - const { verifyEvent, getNumberOfEvents, service } = createSession(/*lazyConfiguredProjectsFromExternalProject*/ true); - assert.equal(getNumberOfEvents(), 0); - - service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: false } }); - verifyEvent(); - }); - }); - } - - describe("when using event handler", () => { - verifyProjectLoadingStartAndFinish(host => { - const { session, events } = createSessionWithEventTracking(host, server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent); - return { - session, - getNumberOfEvents: () => events.length, - clearEvents: () => events.length = 0, - verifyProjectLoadEvents: expected => assert.deepEqual(events, expected) - }; - }); - }); - - describe("when using default event handler", () => { - verifyProjectLoadingStartAndFinish(host => { - const { session, getEvents, clearEvents } = createSessionWithDefaultEventHandler(host, [server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent]); - return { - session, - getNumberOfEvents: () => getEvents().length, - clearEvents, - verifyProjectLoadEvents - }; - - function verifyProjectLoadEvents(expected: [server.ProjectLoadingStartEvent, server.ProjectLoadingFinishEvent]) { - const actual = getEvents().map(e => ({ eventName: e.event, data: e.body })); - const mappedExpected = expected.map(e => { - const { project, ...rest } = e.data; - return { eventName: e.eventName, data: { projectName: project.getProjectName(), ...rest } }; - }); - assert.deepEqual(actual, mappedExpected); - } - }); - }); - }); - describe("tsserverProjectSystem syntax operations", () => { function navBarFull(session: TestSession, file: File) { return JSON.stringify(session.executeCommandSeq({