Skip to content

Commit c7091ab

Browse files
committed
Add test that verifies watched directories and files when resolution of module references sibling folder to root with symlLink
1 parent 58f4c6f commit c7091ab

3 files changed

Lines changed: 88 additions & 32 deletions

File tree

src/harness/unittests/tscWatchMode.ts

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ namespace ts.tscWatch {
1010
import checkArray = TestFSWithWatch.checkArray;
1111
import libFile = TestFSWithWatch.libFile;
1212
import checkWatchedFiles = TestFSWithWatch.checkWatchedFiles;
13+
import checkWatchedFilesDetailed = TestFSWithWatch.checkWatchedFilesDetailed;
1314
import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
15+
import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed;
1416
import checkOutputContains = TestFSWithWatch.checkOutputContains;
1517
import checkOutputDoesNotContain = TestFSWithWatch.checkOutputDoesNotContain;
18+
import Tsc_WatchDirectory = TestFSWithWatch.Tsc_WatchDirectory;
1619

1720
export function checkProgramActualFiles(program: Program, expectedFiles: string[]) {
1821
checkArray(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles);
@@ -2379,7 +2382,7 @@ declare module "fs" {
23792382
});
23802383

23812384
describe("tsc-watch when watchDirectories implementation", () => {
2382-
function verifyRenamingFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) {
2385+
function verifyRenamingFileInSubFolder(tscWatchDirectory: Tsc_WatchDirectory) {
23832386
const projectFolder = "/a/username/project";
23842387
const projectSrcFolder = `${projectFolder}/src`;
23852388
const configFile: File = {
@@ -2399,8 +2402,8 @@ declare module "fs" {
23992402
const projectFolders = [projectFolder, projectSrcFolder, `${projectFolder}/node_modules/@types`];
24002403
// Watching files config file, file, lib file
24012404
const expectedWatchedFiles = files.map(f => f.path);
2402-
const expectedWatchedDirectories = tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory ? projectFolders : emptyArray;
2403-
if (tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.WatchFile) {
2405+
const expectedWatchedDirectories = tscWatchDirectory === Tsc_WatchDirectory.NonRecursiveWatchDirectory ? projectFolders : emptyArray;
2406+
if (tscWatchDirectory === Tsc_WatchDirectory.WatchFile) {
24042407
expectedWatchedFiles.push(...projectFolders);
24052408
}
24062409

@@ -2410,7 +2413,7 @@ declare module "fs" {
24102413
file.path = file.path.replace("file1.ts", "file2.ts");
24112414
expectedWatchedFiles[0] = file.path;
24122415
host.reloadFS(files);
2413-
if (tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.DynamicPolling) {
2416+
if (tscWatchDirectory === Tsc_WatchDirectory.DynamicPolling) {
24142417
// With dynamic polling the fs change would be detected only by running timeouts
24152418
host.runQueuedTimeoutCallbacks();
24162419
}
@@ -2429,21 +2432,21 @@ declare module "fs" {
24292432
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
24302433

24312434
// Watching config file, file, lib file and directories
2432-
TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedFiles", host.watchedFiles, expectedWatchedFiles, 1);
2433-
TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories, 1);
2435+
checkWatchedFilesDetailed(host, expectedWatchedFiles, 1);
2436+
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, 1, /*recursive*/ false);
24342437
}
24352438
}
24362439

24372440
it("uses watchFile when renaming file in subfolder", () => {
2438-
verifyRenamingFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.WatchFile);
2441+
verifyRenamingFileInSubFolder(Tsc_WatchDirectory.WatchFile);
24392442
});
24402443

24412444
it("uses non recursive watchDirectory when renaming file in subfolder", () => {
2442-
verifyRenamingFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory);
2445+
verifyRenamingFileInSubFolder(Tsc_WatchDirectory.NonRecursiveWatchDirectory);
24432446
});
24442447

24452448
it("uses non recursive dynamic polling when renaming file in subfolder", () => {
2446-
verifyRenamingFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.DynamicPolling);
2449+
verifyRenamingFileInSubFolder(Tsc_WatchDirectory.DynamicPolling);
24472450
});
24482451

24492452
it("when there are symlinks to folders in recursive folders", () => {
@@ -2482,7 +2485,7 @@ declare module "fs" {
24822485
};
24832486
const files = [file1, tsconfig, realA, realB, symLinkA, symLinkB, symLinkBInA, symLinkAInB];
24842487
const environmentVariables = createMap<string>();
2485-
environmentVariables.set("TSC_WATCHDIRECTORY", TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory);
2488+
environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory);
24862489
const host = createWatchedSystem(files, { environmentVariables, currentDirectory: cwd });
24872490
createWatchOfConfigFile("tsconfig.json", host);
24882491
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
@@ -2491,4 +2494,46 @@ declare module "fs" {
24912494
});
24922495
});
24932496
});
2497+
2498+
describe("tsc-watch with modules linked to sibling folder", () => {
2499+
const projectRoot = "/user/username/projects/project";
2500+
const mainPackageRoot = `${projectRoot}/main`;
2501+
const linkedPackageRoot = `${projectRoot}/linked-package`;
2502+
const mainFile: File = {
2503+
path: `${mainPackageRoot}/index.ts`,
2504+
content: "import { Foo } from '@scoped/linked-package'"
2505+
};
2506+
const config: File = {
2507+
path: `${mainPackageRoot}/tsconfig.json`,
2508+
content: JSON.stringify({
2509+
compilerOptions: { module: "commonjs", moduleResolution: "node", baseUrl: ".", rootDir: "." },
2510+
files: ["index.ts"]
2511+
})
2512+
};
2513+
const linkedPackageInMain: SymLink = {
2514+
path: `${mainPackageRoot}/node_modules/@scoped/linked-package`,
2515+
symLink: `${linkedPackageRoot}`
2516+
};
2517+
const linkedPackageJson: File = {
2518+
path: `${linkedPackageRoot}/package.json`,
2519+
content: JSON.stringify({ name: "@scoped/linked-package", version: "0.0.1", types: "dist/index.d.ts", main: "dist/index.js" })
2520+
};
2521+
const linkedPackageIndex: File = {
2522+
path: `${linkedPackageRoot}/dist/index.d.ts`,
2523+
content: "export * from './other';"
2524+
};
2525+
const linkedPackageOther: File = {
2526+
path: `${linkedPackageRoot}/dist/other.d.ts`,
2527+
content: 'export declare const Foo = "BAR";'
2528+
};
2529+
2530+
it("verify watched directories", () => {
2531+
const files = [libFile, mainFile, config, linkedPackageInMain, linkedPackageJson, linkedPackageIndex, linkedPackageOther];
2532+
const host = createWatchedSystem(files, { currentDirectory: mainPackageRoot });
2533+
createWatchOfConfigFile("tsconfig.json", host);
2534+
checkWatchedFilesDetailed(host, [libFile.path, mainFile.path, config.path, linkedPackageIndex.path, linkedPackageOther.path], 1);
2535+
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
2536+
checkWatchedDirectoriesDetailed(host, [mainPackageRoot, projectRoot, `${mainPackageRoot}/node_modules/@types`, `${projectRoot}/node_modules/@types`], 1, /*recursive*/ true);
2537+
});
2538+
});
24942539
}

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace ts.projectSystem {
1919
export import checkWatchedDirectories = TestFSWithWatch.checkWatchedDirectories;
2020
export import checkWatchedDirectoriesDetailed = TestFSWithWatch.checkWatchedDirectoriesDetailed;
2121
import safeList = TestFSWithWatch.safeList;
22+
import Tsc_WatchDirectory = TestFSWithWatch.Tsc_WatchDirectory;
2223

2324
export const customTypesMap = {
2425
path: <Path>"/typesMap.json",
@@ -6259,7 +6260,7 @@ namespace ts.projectSystem {
62596260
}
62606261

62616262
function verifyCalledOnEachEntryNTimes(callback: CalledMaps, expectedKeys: ReadonlyArray<string>, nTimes: number) {
6262-
TestFSWithWatch.checkMultiMapEachKeyWithCount(callback, calledMaps[callback], expectedKeys, nTimes);
6263+
TestFSWithWatch.checkMultiMapKeyCount(callback, calledMaps[callback], expectedKeys, nTimes);
62636264
}
62646265

62656266
function verifyNoHostCalls() {
@@ -7813,14 +7814,10 @@ new C();`
78137814
checkCompleteEvent(session, 2, expectedSequenceId);
78147815
}
78157816

7816-
function createSingleWatchMap(paths: string[]) {
7817-
return arrayToMap(paths, p => p, () => 1);
7818-
}
7819-
78207817
function verifyWatchedFilesAndDirectories(host: TestServerHost, files: string[], directories: string[]) {
7821-
checkWatchedFilesDetailed(host, createSingleWatchMap(files.filter(f => f !== recognizersDateTimeSrcFile.path)));
7818+
checkWatchedFilesDetailed(host, files.filter(f => f !== recognizersDateTimeSrcFile.path), 1);
78227819
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
7823-
checkWatchedDirectoriesDetailed(host, createSingleWatchMap(directories), /*recursive*/ true);
7820+
checkWatchedDirectoriesDetailed(host, directories, 1, /*recursive*/ true);
78247821
}
78257822

78267823
function createSessionAndOpenFile(host: TestServerHost) {
@@ -8315,7 +8312,7 @@ new C();`
83158312
});
83168313

83178314
describe("tsserverProjectSystem watchDirectories implementation", () => {
8318-
function verifyCompletionListWithNewFileInSubFolder(tscWatchDirectory: TestFSWithWatch.Tsc_WatchDirectory) {
8315+
function verifyCompletionListWithNewFileInSubFolder(tscWatchDirectory: Tsc_WatchDirectory) {
83198316
const projectFolder = "/a/username/project";
83208317
const projectSrcFolder = `${projectFolder}/src`;
83218318
const configFile: File = {
@@ -8336,9 +8333,9 @@ new C();`
83368333
// All closed files(files other than index), project folder, project/src folder and project/node_modules/@types folder
83378334
const expectedWatchedFiles = arrayToMap(fileNames.slice(1), s => s, () => 1);
83388335
const expectedWatchedDirectories = createMap<number>();
8339-
const mapOfDirectories = tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory ?
8336+
const mapOfDirectories = tscWatchDirectory === Tsc_WatchDirectory.NonRecursiveWatchDirectory ?
83408337
expectedWatchedDirectories :
8341-
tscWatchDirectory === TestFSWithWatch.Tsc_WatchDirectory.WatchFile ?
8338+
tscWatchDirectory === Tsc_WatchDirectory.WatchFile ?
83428339
expectedWatchedFiles :
83438340
createMap();
83448341
// For failed resolution lookup and tsconfig files
@@ -8385,15 +8382,15 @@ new C();`
83858382
}
83868383

83878384
it("uses watchFile when file is added to subfolder, completion list has new file", () => {
8388-
verifyCompletionListWithNewFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.WatchFile);
8385+
verifyCompletionListWithNewFileInSubFolder(Tsc_WatchDirectory.WatchFile);
83898386
});
83908387

83918388
it("uses non recursive watchDirectory when file is added to subfolder, completion list has new file", () => {
8392-
verifyCompletionListWithNewFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.NonRecursiveWatchDirectory);
8389+
verifyCompletionListWithNewFileInSubFolder(Tsc_WatchDirectory.NonRecursiveWatchDirectory);
83938390
});
83948391

83958392
it("uses dynamic polling when file is added to subfolder, completion list has new file", () => {
8396-
verifyCompletionListWithNewFileInSubFolder(TestFSWithWatch.Tsc_WatchDirectory.DynamicPolling);
8393+
verifyCompletionListWithNewFileInSubFolder(Tsc_WatchDirectory.DynamicPolling);
83978394
});
83988395
});
83998396

src/harness/virtualFileSystemWithWatch.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,18 +175,17 @@ interface Array<T> {}`
175175
}
176176
}
177177

178-
export function checkMultiMapKeyCount(caption: string, actual: MultiMap<any>, expectedKeys: Map<number>) {
178+
export function checkMultiMapKeyCount(caption: string, actual: MultiMap<any>, expectedKeys: ReadonlyMap<number>): void;
179+
export function checkMultiMapKeyCount(caption: string, actual: MultiMap<any>, expectedKeys: ReadonlyArray<string>, eachKeyCount: number): void;
180+
export function checkMultiMapKeyCount(caption: string, actual: MultiMap<any>, expectedKeysMapOrArray: ReadonlyMap<number> | ReadonlyArray<string>, eachKeyCount?: number) {
181+
const expectedKeys = isArray(expectedKeysMapOrArray) ? arrayToMap(expectedKeysMapOrArray, s => s, () => eachKeyCount!) : expectedKeysMapOrArray;
179182
verifyMapSize(caption, actual, arrayFrom(expectedKeys.keys()));
180183
expectedKeys.forEach((count, name) => {
181184
assert.isTrue(actual.has(name), `${caption}: expected to contain ${name}, actual keys: ${arrayFrom(actual.keys())}`);
182185
assert.equal(actual.get(name)!.length, count, `${caption}: Expected to be have ${count} entries for ${name}. Actual entry: ${JSON.stringify(actual.get(name))}`);
183186
});
184187
}
185188

186-
export function checkMultiMapEachKeyWithCount(caption: string, actual: MultiMap<any>, expectedKeys: ReadonlyArray<string>, count: number) {
187-
return checkMultiMapKeyCount(caption, actual, arrayToMap(expectedKeys, s => s, () => count));
188-
}
189-
190189
export function checkArray(caption: string, actual: ReadonlyArray<string>, expected: ReadonlyArray<string>) {
191190
assert.equal(actual.length, expected.length, `${caption}: incorrect actual number of files, expected:\r\n${expected.join("\r\n")}\r\ngot: ${actual.join("\r\n")}`);
192191
for (const f of expected) {
@@ -198,16 +197,31 @@ interface Array<T> {}`
198197
checkMapKeys("watchedFiles", host.watchedFiles, expectedFiles);
199198
}
200199

201-
export function checkWatchedFilesDetailed(host: TestServerHost, expectedFiles: Map<number>) {
202-
checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedFiles);
200+
export function checkWatchedFilesDetailed(host: TestServerHost, expectedFiles: ReadonlyMap<number>): void;
201+
export function checkWatchedFilesDetailed(host: TestServerHost, expectedFiles: ReadonlyArray<string>, eachFileWatchCount: number): void;
202+
export function checkWatchedFilesDetailed(host: TestServerHost, expectedFiles: ReadonlyMap<number> | ReadonlyArray<string>, eachFileWatchCount?: number) {
203+
if (isArray(expectedFiles)) {
204+
checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedFiles, eachFileWatchCount!);
205+
}
206+
else {
207+
checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedFiles);
208+
}
203209
}
204210

205211
export function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[], recursive: boolean) {
206212
checkMapKeys(`watchedDirectories${recursive ? " recursive" : ""}`, recursive ? host.watchedDirectoriesRecursive : host.watchedDirectories, expectedDirectories);
207213
}
208214

209-
export function checkWatchedDirectoriesDetailed(host: TestServerHost, expectedDirectories: Map<number>, recursive: boolean) {
210-
checkMultiMapKeyCount(`watchedDirectories${recursive ? " recursive" : ""}`, recursive ? host.watchedDirectoriesRecursive : host.watchedDirectories, expectedDirectories);
215+
export function checkWatchedDirectoriesDetailed(host: TestServerHost, expectedDirectories: ReadonlyMap<number>, recursive: boolean): void;
216+
export function checkWatchedDirectoriesDetailed(host: TestServerHost, expectedDirectories: ReadonlyArray<string>, eachDirectoryWatchCount: number, recursive: boolean): void;
217+
export function checkWatchedDirectoriesDetailed(host: TestServerHost, expectedDirectories: ReadonlyMap<number> | ReadonlyArray<string>, recursiveOrEachDirectoryWatchCount: boolean | number, recursive?: boolean) {
218+
if (isArray(expectedDirectories)) {
219+
checkMultiMapKeyCount(`watchedDirectories${recursive ? " recursive" : ""}`, recursive ? host.watchedDirectoriesRecursive : host.watchedDirectories, expectedDirectories, recursiveOrEachDirectoryWatchCount as number);
220+
}
221+
else {
222+
recursive = recursiveOrEachDirectoryWatchCount as boolean;
223+
checkMultiMapKeyCount(`watchedDirectories${recursive ? " recursive" : ""}`, recursive ? host.watchedDirectoriesRecursive : host.watchedDirectories, expectedDirectories);
224+
}
211225
}
212226

213227
export function checkOutputContains(host: TestServerHost, expected: ReadonlyArray<string>) {

0 commit comments

Comments
 (0)