Skip to content

Commit 8f86b4c

Browse files
committed
Add tests for library redirections
1 parent 0a98b32 commit 8f86b4c

26 files changed

+10739
-22
lines changed

Diff for: src/testRunner/tests.ts

+5
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ import "./unittests/tsbuild/graphOrdering";
7878
import "./unittests/tsbuild/inferredTypeFromTransitiveModule";
7979
import "./unittests/tsbuild/javascriptProjectEmit";
8080
import "./unittests/tsbuild/lateBoundSymbol";
81+
import "./unittests/tsbuild/libraryResolution";
8182
import "./unittests/tsbuild/moduleResolution";
8283
import "./unittests/tsbuild/moduleSpecifiers";
8384
import "./unittests/tsbuild/noEmit";
@@ -92,6 +93,7 @@ import "./unittests/tsbuild/sample";
9293
import "./unittests/tsbuild/transitiveReferences";
9394
import "./unittests/tsbuildWatch/configFileErrors";
9495
import "./unittests/tsbuildWatch/demo";
96+
import "./unittests/tsbuildWatch/libraryResolution";
9597
import "./unittests/tsbuildWatch/moduleResolution";
9698
import "./unittests/tsbuildWatch/noEmit";
9799
import "./unittests/tsbuildWatch/noEmitOnError";
@@ -105,6 +107,7 @@ import "./unittests/tsc/composite";
105107
import "./unittests/tsc/declarationEmit";
106108
import "./unittests/tsc/forceConsistentCasingInFileNames";
107109
import "./unittests/tsc/incremental";
110+
import "./unittests/tsc/libraryResolution";
108111
import "./unittests/tsc/listFilesOnly";
109112
import "./unittests/tsc/projectReferences";
110113
import "./unittests/tsc/projectReferencesConfig";
@@ -116,6 +119,7 @@ import "./unittests/tscWatch/nodeNextWatch";
116119
import "./unittests/tscWatch/emitAndErrorUpdates";
117120
import "./unittests/tscWatch/forceConsistentCasingInFileNames";
118121
import "./unittests/tscWatch/incremental";
122+
import "./unittests/tscWatch/libraryResolution";
119123
import "./unittests/tscWatch/moduleResolution";
120124
import "./unittests/tscWatch/programUpdates";
121125
import "./unittests/tscWatch/projectsWithReferences";
@@ -155,6 +159,7 @@ import "./unittests/tsserver/inlayHints";
155159
import "./unittests/tsserver/inferredProjects";
156160
import "./unittests/tsserver/jsdocTag";
157161
import "./unittests/tsserver/languageService";
162+
import "./unittests/tsserver/libraryResolution";
158163
import "./unittests/tsserver/maxNodeModuleJsDepth";
159164
import "./unittests/tsserver/metadataInResponse";
160165
import "./unittests/tsserver/moduleResolution";

Diff for: src/testRunner/unittests/helpers/contents.ts

+4
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ interface Symbol {
1919
readonly [Symbol.toStringTag]: string;
2020
}
2121
`;
22+
23+
export interface FsContents {
24+
[path: string]: string;
25+
}
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { FsContents, libContent } from "./contents";
2+
import { loadProjectFromFiles } from "./vfs";
3+
import { createServerHost, createWatchedSystem } from "./virtualFileSystemWithWatch";
4+
5+
function getFsContentsForLibResolution(libRedirection?: boolean): FsContents {
6+
return {
7+
"/home/src/projects/project1/utils.d.ts": `export const y = 10;`,
8+
"/home/src/projects/project1/file.ts": `export const file = 10;`,
9+
"/home/src/projects/project1/core.d.ts": `export const core = 10;`,
10+
"/home/src/projects/project1/index.ts": `export const x = "type1";`,
11+
"/home/src/projects/project1/tsconfig.json": JSON.stringify({
12+
compilerOptions: { composite: true, typeRoots: ["./typeroot1"], lib: ["es5", "dom"], traceResolution: true },
13+
}),
14+
"/home/src/projects/project1/typeroot1/sometype/index.d.ts": `export type TheNum = "type1";`,
15+
"/home/src/projects/project2/utils.d.ts": `export const y = 10;`,
16+
"/home/src/projects/project2/index.ts": `export const y = 10`,
17+
"/home/src/projects/project2/tsconfig.json": JSON.stringify({
18+
compilerOptions: { composite: true, lib: ["es5", "dom"], traceResolution: true },
19+
}),
20+
"/home/src/projects/project3/utils.d.ts": `export const y = 10;`,
21+
"/home/src/projects/project3/index.ts": `export const z = 10`,
22+
"/home/src/projects/project3/tsconfig.json": JSON.stringify({
23+
compilerOptions: { composite: true, lib: ["es5", "dom"], traceResolution: true },
24+
}),
25+
"/home/src/projects/project4/utils.d.ts": `export const y = 10;`,
26+
"/home/src/projects/project4/index.ts": `export const z = 10`,
27+
"/home/src/projects/project4/tsconfig.json": JSON.stringify({
28+
compilerOptions: { composite: true, lib: ["esnext", "dom"], traceResolution: true },
29+
}),
30+
"/home/src/lib/lib.es5.d.ts": libContent,
31+
"/home/src/lib/lib.esnext.d.ts": libContent,
32+
"/home/src/lib/lib.dom.d.ts": "interface DOMInterface { }",
33+
"/home/src/projects/node_modules/@typescript/unlreated/index.d.ts": "export const unrelated = 10;",
34+
...libRedirection ? {
35+
"/home/src/projects/node_modules/@typescript/lib-es5/index.d.ts": libContent,
36+
"/home/src/projects/node_modules/@typescript/lib-esnext/index.d.ts": libContent,
37+
"/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts": "interface DOMInterface { }",
38+
} : undefined
39+
};
40+
}
41+
42+
export function getFsForLibResolution(libRedirection: true | undefined) {
43+
return loadProjectFromFiles(
44+
getFsContentsForLibResolution(libRedirection),
45+
{
46+
cwd: "/home/src/projects",
47+
executingFilePath: "/home/src/lib/tsc.js",
48+
}
49+
);
50+
}
51+
52+
export function getSysForLibResolution(libRedirection?: true) {
53+
return createWatchedSystem(
54+
getFsContentsForLibResolution(libRedirection),
55+
{
56+
currentDirectory: "/home/src/projects",
57+
executingFilePath: "/home/src/lib/tsc.js",
58+
}
59+
);
60+
}
61+
62+
export function getServerHosForLibResolution(withoutConfig: true | undefined, libRedirection?: true) {
63+
const host = createServerHost(
64+
getFsContentsForLibResolution(libRedirection),
65+
{
66+
currentDirectory: "/home/src/projects",
67+
executingFilePath: "/home/src/lib/tsc.js",
68+
}
69+
);
70+
if (withoutConfig) {
71+
host.deleteFile("/home/src/projects/project1/tsconfig.json");
72+
}
73+
return host;
74+
}
75+
76+
export function getCommandLineArgsForLibResolution(withoutConfig: true | undefined) {
77+
return withoutConfig ?
78+
["project1/core.d.ts", "project1/utils.d.ts", "project1/file.ts", "project1/index.ts", "--lib", "es5,dom", "--traceResolution", "--explainFiles"] :
79+
["-p", "project1", "--explainFiles"];
80+
}

Diff for: src/testRunner/unittests/helpers/tsc.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export function testTscCompileLike(input: TestTscCompileLike) {
6969
const fs = inputFs.shadow();
7070

7171
// Create system
72-
const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc", env: environmentVariables }) as TscCompileSystem;
72+
const sys = new fakes.System(fs, { executingFilePath: `${fs.meta.get("defaultLibLocation")}/tsc`, env: environmentVariables }) as TscCompileSystem;
7373
sys.storeFilesChangingSignatureDuringEmit = true;
7474
sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`);
7575
sys.exit = exitCode => sys.exitCode = exitCode;

Diff for: src/testRunner/unittests/helpers/vfs.ts

+28-21
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,54 @@
11
import * as Harness from "../../_namespaces/Harness";
2+
import { getDirectoryPath } from "../../_namespaces/ts";
23
import * as vfs from "../../_namespaces/vfs";
34
import * as vpath from "../../_namespaces/vpath";
45
import { libContent } from "./contents";
56

7+
export interface FsOptions {
8+
libContentToAppend?: string;
9+
cwd?: string;
10+
executingFilePath?: string;
11+
}
12+
export type FsOptionsOrLibContentsToAppend = FsOptions | string;
13+
14+
function valueOfFsOptions(options: FsOptionsOrLibContentsToAppend | undefined, key: keyof FsOptions) {
15+
return typeof options === "string" ?
16+
key === "libContentToAppend" ? options : undefined :
17+
options?.[key];
18+
}
19+
620
/**
721
* Load project from disk into /src folder
822
*/
9-
1023
export function loadProjectFromDisk(
1124
root: string,
12-
libContentToAppend?: string
25+
options?: FsOptionsOrLibContentsToAppend
1326
): vfs.FileSystem {
1427
const resolver = vfs.createResolver(Harness.IO);
15-
const fs = new vfs.FileSystem(/*ignoreCase*/ true, {
16-
files: {
17-
["/src"]: new vfs.Mount(vpath.resolve(Harness.IO.getWorkspaceRoot(), root), resolver)
18-
},
19-
cwd: "/",
20-
meta: { defaultLibLocation: "/lib" },
21-
});
22-
addLibAndMakeReadonly(fs, libContentToAppend);
23-
return fs;
28+
return loadProjectFromFiles({
29+
["/src"]: new vfs.Mount(vpath.resolve(Harness.IO.getWorkspaceRoot(), root), resolver)
30+
}, options);
2431
}
32+
2533
/**
2634
* All the files must be in /src
2735
*/
28-
2936
export function loadProjectFromFiles(
3037
files: vfs.FileSet,
31-
libContentToAppend?: string
38+
options?: FsOptionsOrLibContentsToAppend,
3239
): vfs.FileSystem {
40+
const executingFilePath = valueOfFsOptions(options, "executingFilePath");
41+
const defaultLibLocation = executingFilePath ? getDirectoryPath(executingFilePath) : "/lib";
3342
const fs = new vfs.FileSystem(/*ignoreCase*/ true, {
3443
files,
35-
cwd: "/",
36-
meta: { defaultLibLocation: "/lib" },
44+
cwd: valueOfFsOptions(options, "cwd") || "/",
45+
meta: { defaultLibLocation },
3746
});
38-
addLibAndMakeReadonly(fs, libContentToAppend);
39-
return fs;
40-
}
41-
function addLibAndMakeReadonly(fs: vfs.FileSystem, libContentToAppend?: string) {
42-
fs.mkdirSync("/lib");
43-
fs.writeFileSync("/lib/lib.d.ts", libContentToAppend ? `${libContent}${libContentToAppend}` : libContent);
47+
const libContentToAppend = valueOfFsOptions(options, "libContentToAppend");
48+
fs.mkdirpSync(defaultLibLocation);
49+
fs.writeFileSync(`${defaultLibLocation}/lib.d.ts`, libContentToAppend ? `${libContent}${libContentToAppend}` : libContent);
4450
fs.makeReadonly();
51+
return fs;
4552
}
4653

4754
export function replaceText(fs: vfs.FileSystem, path: string, oldText: string, newText: string) {
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { getFsForLibResolution } from "../helpers/libraryResolution";
2+
import { verifyTsc } from "../helpers/tsc";
3+
4+
describe("unittests:: tsbuild:: libraryResolution:: library file resolution", () => {
5+
function verify(libRedirection?: true) {
6+
verifyTsc({
7+
scenario: "libraryResolution",
8+
subScenario: `with config${libRedirection ? " with redirection" : ""}`,
9+
fs: () => getFsForLibResolution(libRedirection),
10+
commandLineArgs: ["-b", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles"],
11+
baselinePrograms: true,
12+
});
13+
}
14+
verify();
15+
verify(/*libRedirection*/ true);
16+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { getSysForLibResolution } from "../helpers/libraryResolution";
2+
import { verifyTscWatch } from "../helpers/tscWatch";
3+
4+
describe("unittests:: tsbuildWatch:: watchMode:: libraryResolution:: library file resolution", () => {
5+
function verify(libRedirection?: true) {
6+
verifyTscWatch({
7+
scenario: "libraryResolution",
8+
subScenario: `with config${libRedirection ? " with redirection" : ""}`,
9+
sys: () => getSysForLibResolution(libRedirection),
10+
commandLineArgs: ["-b", "-w", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles", "--extendedDiagnostics"],
11+
});
12+
}
13+
verify();
14+
verify(/*libRedirection*/ true);
15+
});

Diff for: src/testRunner/unittests/tsc/libraryResolution.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { getCommandLineArgsForLibResolution, getFsForLibResolution } from "../helpers/libraryResolution";
2+
import { verifyTsc } from "../helpers/tsc";
3+
4+
describe("unittests:: tsc:: libraryResolution:: library file resolution", () => {
5+
function verify(libRedirection?: true, withoutConfig?: true) {
6+
verifyTsc({
7+
scenario: "libraryResolution",
8+
subScenario: `${withoutConfig ? "without" : "with"} config${libRedirection ? " with redirection" : ""}`,
9+
fs: () => getFsForLibResolution(libRedirection),
10+
commandLineArgs: getCommandLineArgsForLibResolution(withoutConfig),
11+
baselinePrograms: true,
12+
});
13+
}
14+
verify();
15+
verify(/*libRedirection*/ true);
16+
verify(/*libRedirection*/ undefined, /*withoutConfig*/ true);
17+
verify(/*libRedirection*/ true, /*withoutConfig*/ true);
18+
});
+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { getCommandLineArgsForLibResolution, getSysForLibResolution } from "../helpers/libraryResolution";
2+
import {
3+
TscWatchCompileChange,
4+
TscWatchSystem,
5+
verifyTscWatch
6+
} from "../helpers/tscWatch";
7+
8+
describe("unittests:: tsc-watch:: libraryResolution", () => {
9+
function commandLineArgs(withoutConfig: true | undefined) {
10+
return ["-w", ...getCommandLineArgsForLibResolution(withoutConfig), "--extendedDiagnostics"];
11+
}
12+
13+
function editOptions(withoutConfig: true | undefined, changeLib: (sys: TscWatchSystem) => void): TscWatchCompileChange[] {
14+
return withoutConfig ? [] : [
15+
{
16+
caption: "change program options to update module resolution",
17+
edit: sys => sys.writeFile("/home/src/projects/project1/tsconfig.json", JSON.stringify({
18+
compilerOptions: {
19+
composite: true,
20+
typeRoots: ["./typeroot1", "./typeroot2"],
21+
lib: ["es5", "dom"],
22+
traceResolution: true,
23+
},
24+
})),
25+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
26+
},
27+
{
28+
caption: "change program options to update module resolution and also update lib file",
29+
edit: sys => {
30+
sys.writeFile("/home/src/projects/project1/tsconfig.json", JSON.stringify({
31+
compilerOptions: {
32+
composite: true,
33+
typeRoots: ["./typeroot1"],
34+
lib: ["es5", "dom"],
35+
traceResolution: true,
36+
},
37+
}));
38+
changeLib(sys);
39+
},
40+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
41+
}
42+
];
43+
}
44+
function verify(withoutConfig?: true) {
45+
verifyTscWatch({
46+
scenario: "libraryResolution",
47+
subScenario: `${withoutConfig ? "without" : "with"} config`,
48+
sys: () => getSysForLibResolution(),
49+
commandLineArgs: commandLineArgs(withoutConfig),
50+
edits: [
51+
{
52+
caption: "write redirect file dom",
53+
edit: sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }),
54+
timeouts: sys => {
55+
sys.runQueuedTimeoutCallbacks();
56+
sys.runQueuedTimeoutCallbacks();
57+
}
58+
},
59+
{
60+
caption: "edit index",
61+
edit: sys => sys.appendFile("/home/src/projects/project1/index.ts", "export const xyz = 10;"),
62+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
63+
},
64+
{
65+
caption: "delete core",
66+
edit: sys => sys.deleteFile("/home/src/projects/project1/core.d.ts"),
67+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
68+
},
69+
{
70+
caption: "delete redirect file dom",
71+
edit: sys => sys.deleteFile("/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts"),
72+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
73+
},
74+
...editOptions(withoutConfig, sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" })),
75+
]
76+
});
77+
78+
verifyTscWatch({
79+
scenario: "libraryResolution",
80+
subScenario: `${withoutConfig ? "without" : "with"} config with redirection`,
81+
sys: () => getSysForLibResolution(/*libRedirection*/ true),
82+
commandLineArgs: commandLineArgs(withoutConfig),
83+
edits: [
84+
{
85+
caption: "delete redirect file dom",
86+
edit: sys => sys.deleteFile("/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts"),
87+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
88+
},
89+
{
90+
caption: "edit index",
91+
edit: sys => sys.appendFile("/home/src/projects/project1/index.ts", "export const xyz = 10;"),
92+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
93+
},
94+
{
95+
caption: "delete core",
96+
edit: sys => sys.deleteFile("/home/src/projects/project1/core.d.ts"),
97+
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
98+
},
99+
{
100+
caption: "write redirect file dom",
101+
edit: sys => sys.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }),
102+
timeouts: sys => {
103+
sys.runQueuedTimeoutCallbacks();
104+
sys.runQueuedTimeoutCallbacks();
105+
}
106+
},
107+
...editOptions(withoutConfig, sys => sys.deleteFile("/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts")),
108+
]
109+
});
110+
}
111+
verify();
112+
verify(/*withoutConfig*/ true);
113+
});

0 commit comments

Comments
 (0)