From 53cbc046d2d994abab784f463f26e93f011ee1e9 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 15 Mar 2021 18:04:30 -0700 Subject: [PATCH] Refactor the test for easy maintainability (#43262) --- .../tsserver/projectReferenceCompileOnSave.ts | 2449 ++++++++++++++--- 1 file changed, 2138 insertions(+), 311 deletions(-) diff --git a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts index 083c64aabe..97132be83b 100644 --- a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts +++ b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts @@ -33,194 +33,13 @@ fn2(); }) }; - interface VerifySingleScenarioWorker extends VerifySingleScenario { - withProject: boolean; - } - function verifySingleScenarioWorker({ - withProject, scenario, openFiles, requestArgs, change, expectedResult - }: VerifySingleScenarioWorker) { - it(scenario, () => { - const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( - createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) - ); - const session = createSession(host); - openFilesForSession(openFiles(), session); - const reqArgs = requestArgs(); - const { - expectedAffected, - expectedEmit: { expectedEmitSuccess, expectedFiles }, - expectedEmitOutput - } = expectedResult(withProject); - - if (change) { - session.executeCommandSeq({ - command: protocol.CommandTypes.CompileOnSaveAffectedFileList, - arguments: { file: dependencyTs.path } - }); - const { file, insertString } = change(); - if (session.getProjectService().openFiles.has(file.path as Path)) { - const toLocation = protocolToLocation(file.content); - const location = toLocation(file.content.length); - session.executeCommandSeq({ - command: protocol.CommandTypes.Change, - arguments: { - file: file.path, - ...location, - endLine: location.line, - endOffset: location.offset, - insertString - } - }); - } - else { - host.writeFile(file.path, `${file.content}${insertString}`); - } - host.writtenFiles.clear(); - } - - const args = withProject ? reqArgs : { file: reqArgs.file }; - // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: protocol.CommandTypes.CompileOnSaveAffectedFileList, - arguments: args - }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; - assert.deepEqual(actualAffectedFiles, expectedAffected, "Affected files"); - - // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: protocol.CommandTypes.CompileOnSaveEmitFile, - arguments: args - }).response; - assert.deepEqual(actualEmit, expectedEmitSuccess, "Emit files"); - assert.equal(host.writtenFiles.size, expectedFiles.length); - for (const file of expectedFiles) { - assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); - } - - // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: protocol.CommandTypes.EmitOutput, - arguments: args - }).response as EmitOutput; - assert.deepEqual(actualEmitOutput, expectedEmitOutput, "Emit output"); - }); - } - - interface VerifySingleScenario { - scenario: string; - openFiles: () => readonly File[]; - requestArgs: () => protocol.FileRequestArgs; - skipWithoutProject?: boolean; - change?: () => SingleScenarioChange; - expectedResult: GetSingleScenarioResult; - } - function verifySingleScenario(scenario: VerifySingleScenario) { - if (!scenario.skipWithoutProject) { - describe("without specifying project file", () => { - verifySingleScenarioWorker({ - withProject: false, - ...scenario - }); - }); - } - describe("with specifying project file", () => { - verifySingleScenarioWorker({ - withProject: true, - ...scenario - }); - }); - } - - interface SingleScenarioExpectedEmit { - expectedEmitSuccess: boolean; - expectedFiles: readonly File[]; - } - interface SingleScenarioResult { - expectedAffected: protocol.CompileOnSaveAffectedFileListSingleProject[]; - expectedEmit: SingleScenarioExpectedEmit; - expectedEmitOutput: EmitOutput; - } - type GetSingleScenarioResult = (withProject: boolean) => SingleScenarioResult; - interface SingleScenarioChange { - file: File; - insertString: string; - } - interface ScenarioDetails { - scenarioName: string; - requestArgs: () => protocol.FileRequestArgs; - skipWithoutProject?: boolean; - initial: GetSingleScenarioResult; - localChangeToDependency: GetSingleScenarioResult; - localChangeToUsage: GetSingleScenarioResult; - changeToDependency: GetSingleScenarioResult; - changeToUsage: GetSingleScenarioResult; - } - interface VerifyScenario { - openFiles: () => readonly File[]; - scenarios: readonly ScenarioDetails[]; - } - const localChange = "function fn3() { }"; const change = `export ${localChange}`; const changeJs = `function fn3() { } exports.fn3 = fn3;`; const changeDts = "export declare function fn3(): void;"; - function verifyScenario({ openFiles, scenarios }: VerifyScenario) { - for (const { - scenarioName, requestArgs, skipWithoutProject, initial, - localChangeToDependency, localChangeToUsage, - changeToDependency, changeToUsage - } of scenarios) { - describe(scenarioName, () => { - verifySingleScenario({ - scenario: "with initial file open", - openFiles, - requestArgs, - skipWithoutProject, - expectedResult: initial - }); - verifySingleScenario({ - scenario: "with local change to dependency", - openFiles, - requestArgs, - skipWithoutProject, - change: () => ({ file: dependencyTs, insertString: localChange }), - expectedResult: localChangeToDependency - }); - - verifySingleScenario({ - scenario: "with local change to usage", - openFiles, - requestArgs, - skipWithoutProject, - change: () => ({ file: usageTs, insertString: localChange }), - expectedResult: localChangeToUsage - }); - - verifySingleScenario({ - scenario: "with change to dependency", - openFiles, - requestArgs, - skipWithoutProject, - change: () => ({ file: dependencyTs, insertString: change }), - expectedResult: changeToDependency - }); - - verifySingleScenario({ - scenario: "with change to usage", - openFiles, - requestArgs, - skipWithoutProject, - change: () => ({ file: usageTs, insertString: change }), - expectedResult: changeToUsage - }); - }); - } - } - - function expectedAffectedFiles(config: File, fileNames: File[]): protocol.CompileOnSaveAffectedFileListSingleProject { + function expectedAffectedFiles(config: File, fileNames: readonly File[]): protocol.CompileOnSaveAffectedFileListSingleProject { return { projectFileName: config.path, fileNames: fileNames.map(f => f.path), @@ -228,24 +47,21 @@ exports.fn3 = fn3;`; }; } - function expectedUsageEmit(appendJsText?: string): SingleScenarioExpectedEmit { + function expectedUsageEmitFiles(appendJsText?: string): readonly File[] { const appendJs = appendJsText ? `${appendJsText} ` : ""; - return { - expectedEmitSuccess: true, - expectedFiles: [{ - path: `${usageLocation}/usage.js`, - content: `"use strict"; + return [{ + path: `${usageLocation}/usage.js`, + content: `"use strict"; exports.__esModule = true;${appendJsText === changeJs ? "\nexports.fn3 = void 0;" : ""} var fns_1 = require("../decls/fns"); (0, fns_1.fn1)(); (0, fns_1.fn2)(); ${appendJs}` - }] - }; + }]; } - function expectedEmitOutput({ expectedFiles }: SingleScenarioExpectedEmit): EmitOutput { + function expectedEmitOutput(expectedFiles: readonly File[]): EmitOutput { return { outputFiles: expectedFiles.map(({ path, content }) => ({ name: path, @@ -257,17 +73,6 @@ ${appendJs}` }; } - function expectedUsageEmitOutput(appendJsText?: string): EmitOutput { - return expectedEmitOutput(expectedUsageEmit(appendJsText)); - } - - function noEmit(): SingleScenarioExpectedEmit { - return { - expectedEmitSuccess: false, - expectedFiles: emptyArray - }; - } - function noEmitOutput(): EmitOutput { return { emitSkipped: true, @@ -276,17 +81,15 @@ ${appendJs}` }; } - function expectedDependencyEmit(appendJsText?: string, appendDtsText?: string): SingleScenarioExpectedEmit { + function expectedDependencyEmitFiles(appendJsText?: string, appendDtsText?: string): readonly File[] { const appendJs = appendJsText ? `${appendJsText} ` : ""; const appendDts = appendDtsText ? `${appendDtsText} ` : ""; - return { - expectedEmitSuccess: true, - expectedFiles: [ - { - path: `${dependecyLocation}/fns.js`, - content: `"use strict"; + return [ + { + path: `${dependecyLocation}/fns.js`, + content: `"use strict"; exports.__esModule = true; ${appendJsText === changeJs ? "exports.fn3 = " : ""}exports.fn2 = exports.fn1 = void 0; function fn1() { } @@ -294,118 +97,2142 @@ exports.fn1 = fn1; function fn2() { } exports.fn2 = fn2; ${appendJs}` - }, - { - path: `${tscWatch.projectRoot}/decls/fns.d.ts`, - content: `export declare function fn1(): void; -export declare function fn2(): void; -${appendDts}` - } - ] - }; - } - - function expectedDependencyEmitOutput(appendJsText?: string, appendDtsText?: string): EmitOutput { - return expectedEmitOutput(expectedDependencyEmit(appendJsText, appendDtsText)); - } - - function scenarioDetailsOfUsage(isDependencyOpen?: boolean): ScenarioDetails[] { - return [ - { - scenarioName: "Of usageTs", - requestArgs: () => ({ file: usageTs.path, projectFileName: usageConfig.path }), - initial: () => initialUsageTs(), - // no change to usage so same as initial only usage file - localChangeToDependency: () => initialUsageTs(), - localChangeToUsage: () => initialUsageTs(localChange), - changeToDependency: () => initialUsageTs(), - changeToUsage: () => initialUsageTs(changeJs) }, { - scenarioName: "Of dependencyTs in usage project", - requestArgs: () => ({ file: dependencyTs.path, projectFileName: usageConfig.path }), - skipWithoutProject: !!isDependencyOpen, - initial: () => initialDependencyTs(), - localChangeToDependency: () => initialDependencyTs(/*noUsageFiles*/ true), - localChangeToUsage: () => initialDependencyTs(/*noUsageFiles*/ true), - changeToDependency: () => initialDependencyTs(), - changeToUsage: () => initialDependencyTs(/*noUsageFiles*/ true) + path: `${tscWatch.projectRoot}/decls/fns.d.ts`, + content: `export declare function fn1(): void; +export declare function fn2(): void; +${appendDts}` } ]; - - function initialUsageTs(jsText?: string) { - return { - expectedAffected: [ - expectedAffectedFiles(usageConfig, [usageTs]) - ], - expectedEmit: expectedUsageEmit(jsText), - expectedEmitOutput: expectedUsageEmitOutput(jsText) - }; - } - - function initialDependencyTs(noUsageFiles?: true) { - return { - expectedAffected: [ - expectedAffectedFiles(usageConfig, noUsageFiles ? [] : [usageTs]) - ], - expectedEmit: noEmit(), - expectedEmitOutput: noEmitOutput() - }; - } - } - - function scenarioDetailsOfDependencyWhenOpen(): ScenarioDetails { - return { - scenarioName: "Of dependencyTs", - requestArgs: () => ({ file: dependencyTs.path, projectFileName: dependencyConfig.path }), - initial, - localChangeToDependency: withProject => ({ - expectedAffected: withProject ? - [ - expectedAffectedFiles(dependencyConfig, [dependencyTs]) - ] : - [ - expectedAffectedFiles(usageConfig, []), - expectedAffectedFiles(dependencyConfig, [dependencyTs]) - ], - expectedEmit: expectedDependencyEmit(localChange), - expectedEmitOutput: expectedDependencyEmitOutput(localChange) - }), - localChangeToUsage: withProject => initial(withProject, /*noUsageFiles*/ true), - changeToDependency: withProject => initial(withProject, /*noUsageFiles*/ undefined, changeJs, changeDts), - changeToUsage: withProject => initial(withProject, /*noUsageFiles*/ true) - }; - - function initial(withProject: boolean, noUsageFiles?: true, appendJs?: string, appendDts?: string): SingleScenarioResult { - return { - expectedAffected: withProject ? - [ - expectedAffectedFiles(dependencyConfig, [dependencyTs]) - ] : - [ - expectedAffectedFiles(usageConfig, noUsageFiles ? [] : [usageTs]), - expectedAffectedFiles(dependencyConfig, [dependencyTs]) - ], - expectedEmit: expectedDependencyEmit(appendJs, appendDts), - expectedEmitOutput: expectedDependencyEmitOutput(appendJs, appendDts) - }; - } } describe("when dependency project is not open", () => { - verifyScenario({ - openFiles: () => [usageTs], - scenarios: scenarioDetailsOfUsage() + describe("Of usageTs", () => { + it("with initial file open, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with initial file open, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(localChange); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(localChange); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(changeJs); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(changeJs); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + }); + + describe("Of dependencyTs in usage project", () => { + it("with initial file open, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with initial file open, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with local change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with local change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with local change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with local change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); }); }); describe("when the depedency file is open", () => { - verifyScenario({ - openFiles: () => [usageTs, dependencyTs], - scenarios: [ - ...scenarioDetailsOfUsage(/*isDependencyOpen*/ true), - scenarioDetailsOfDependencyWhenOpen(), - ] + describe("Of usageTs", () => { + it("with initial file open, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with initial file open, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(localChange); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(localChange); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(changeJs); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedUsageEmitFiles(changeJs); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: usageTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + }); + + describe("Of dependencyTs in usage project", () => { + it("with initial file open, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with local change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with local change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + it("with change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response; + assert.isFalse(actualEmit, "Emit files"); + assert.equal(host.writtenFiles.size, 0); + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); + }); + }); + + describe("Of dependencyTs", () => { + it("with initial file open, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]), + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with initial file open, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray), + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(localChange); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(localChange); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray), + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with local change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: localChange + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to dependency, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, [usageTs]), + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(changeJs, changeDts); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to dependency, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(dependencyTs.content); + const location = toLocation(dependencyTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: dependencyTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(changeJs, changeDts); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to usage, without specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(usageConfig, emptyArray), + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); + it("with change to usage, with specifying project file", () => { + const host = TestFSWithWatch.changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) + ); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); + + session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path } + }); + const toLocation = protocolToLocation(usageTs.content); + const location = toLocation(usageTs.content.length); + session.executeCommandSeq({ + command: protocol.CommandTypes.Change, + arguments: { + file: usageTs.path, + ...location, + endLine: location.line, + endOffset: location.offset, + insertString: change + } + }); + host.writtenFiles.clear(); + + // Verify CompileOnSaveAffectedFileList + const actualAffectedFiles = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveAffectedFileList, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as protocol.CompileOnSaveAffectedFileListSingleProject[]; + assert.deepEqual(actualAffectedFiles, [ + expectedAffectedFiles(dependencyConfig, [dependencyTs]) + ], "Affected files"); + + // Verify CompileOnSaveEmit + const actualEmit = session.executeCommandSeq({ + command: protocol.CommandTypes.CompileOnSaveEmitFile, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response; + assert.isTrue(actualEmit, "Emit files"); + const expectedFiles = expectedDependencyEmitFiles(); + assert.equal(host.writtenFiles.size, expectedFiles.length); + for (const file of expectedFiles) { + assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); + } + + // Verify EmitOutput + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: protocol.CommandTypes.EmitOutput, + arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } + }).response as EmitOutput; + assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); + }); }); }); }); @@ -486,4 +2313,4 @@ ${appendDts}` assert.equal(host.readFile(sourceJs), expectedSiblingJs); }); }); -} +} \ No newline at end of file