• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts.tscWatch {
2    import getFileFromProject = TestFSWithWatch.getTsBuildProjectFile;
3    describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedirect", () => {
4        interface VerifyWatchInput {
5            files: readonly TestFSWithWatch.FileOrFolderOrSymLink[];
6            config: string;
7            subScenario: string;
8        }
9
10        function verifyWatch({ files, config, subScenario }: VerifyWatchInput, alreadyBuilt: boolean) {
11            const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(
12                createWatchedSystem(files),
13                alreadyBuilt ? (sys, originalRead) => {
14                    solutionBuildWithBaseline(sys, [config], originalRead);
15                    sys.clearOutput();
16                } : undefined
17            );
18            const host = createWatchCompilerHostOfConfigFileForBaseline({
19                configFileName: config,
20                system: sys,
21                cb,
22            });
23            host.useSourceOfProjectReferenceRedirect = returnTrue;
24            const watch = createWatchProgram(host);
25            runWatchBaseline({
26                scenario: "sourceOfProjectReferenceRedirect",
27                subScenario: `${subScenario}${alreadyBuilt ? " when solution is already built" : ""}`,
28                commandLineArgs: ["--w", "--p", config],
29                sys,
30                baseline,
31                oldSnap,
32                getPrograms,
33                changes: emptyArray,
34                watchOrSolution: watch
35            });
36        }
37
38        function verifyScenario(input: () => VerifyWatchInput) {
39            it("when solution is not built", () => {
40                verifyWatch(input(), /*alreadyBuilt*/ false);
41            });
42
43            it("when solution is already built", () => {
44                verifyWatch(input(), /*alreadyBuilt*/ true);
45            });
46        }
47
48        describe("with simple project", () => {
49            verifyScenario(() => {
50                const baseConfig = getFileFromProject("demo", "tsconfig-base.json");
51                const coreTs = getFileFromProject("demo", "core/utilities.ts");
52                const coreConfig = getFileFromProject("demo", "core/tsconfig.json");
53                const animalTs = getFileFromProject("demo", "animals/animal.ts");
54                const dogTs = getFileFromProject("demo", "animals/dog.ts");
55                const indexTs = getFileFromProject("demo", "animals/index.ts");
56                const animalsConfig = getFileFromProject("demo", "animals/tsconfig.json");
57                return {
58                    files: [{ path: libFile.path, content: libContent }, baseConfig, coreTs, coreConfig, animalTs, dogTs, indexTs, animalsConfig],
59                    config: animalsConfig.path,
60                    subScenario: "with simple project"
61                };
62            });
63        });
64
65        describe("when references are monorepo like with symlinks", () => {
66            interface Packages {
67                bPackageJson: File;
68                aTest: File;
69                bFoo: File;
70                bBar: File;
71                bSymlink: SymLink;
72                subScenario: string;
73            }
74            function verifySymlinkScenario(packages: () => Packages) {
75                describe("when preserveSymlinks is turned off", () => {
76                    verifySymlinkScenarioWorker(packages, {});
77                });
78                describe("when preserveSymlinks is turned on", () => {
79                    verifySymlinkScenarioWorker(packages, { preserveSymlinks: true });
80                });
81            }
82
83            function verifySymlinkScenarioWorker(packages: () => Packages, extraOptions: CompilerOptions) {
84                verifyScenario(() => {
85                    const { bPackageJson, aTest, bFoo, bBar, bSymlink, subScenario } = packages();
86                    const aConfig = config("A", extraOptions, ["../B"]);
87                    const bConfig = config("B", extraOptions);
88                    return {
89                        files: [libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink],
90                        config: aConfig.path,
91                        subScenario: `${subScenario}${extraOptions.preserveSymlinks ? " with preserveSymlinks" : ""}`
92                    };
93                });
94            }
95
96            function config(packageName: string, extraOptions: CompilerOptions, references?: string[]): File {
97                return {
98                    path: `${projectRoot}/packages/${packageName}/tsconfig.json`,
99                    content: JSON.stringify({
100                        compilerOptions: {
101                            outDir: "lib",
102                            rootDir: "src",
103                            composite: true,
104                            ...extraOptions
105                        },
106                        include: ["src"],
107                        ...(references ? { references: references.map(path => ({ path })) } : {})
108                    })
109                };
110            }
111
112            function file(packageName: string, fileName: string, content: string): File {
113                return {
114                    path: `${projectRoot}/packages/${packageName}/src/${fileName}`,
115                    content
116                };
117            }
118
119            function verifyMonoRepoLike(scope = "") {
120                describe("when packageJson has types field", () => {
121                    verifySymlinkScenario(() => ({
122                        bPackageJson: {
123                            path: `${projectRoot}/packages/B/package.json`,
124                            content: JSON.stringify({
125                                main: "lib/index.js",
126                                types: "lib/index.d.ts"
127                            })
128                        },
129                        aTest: file("A", "index.ts", `import { foo } from '${scope}b';
130import { bar } from '${scope}b/lib/bar';
131foo();
132bar();
133`),
134                        bFoo: file("B", "index.ts", `export function foo() { }`),
135                        bBar: file("B", "bar.ts", `export function bar() { }`),
136                        bSymlink: {
137                            path: `${projectRoot}/node_modules/${scope}b`,
138                            symLink: `${projectRoot}/packages/B`
139                        },
140                        subScenario: `when packageJson has types field${scope ? " with scoped package" : ""}`
141                    }));
142                });
143
144                describe("when referencing file from subFolder", () => {
145                    verifySymlinkScenario(() => ({
146                        bPackageJson: {
147                            path: `${projectRoot}/packages/B/package.json`,
148                            content: "{}"
149                        },
150                        aTest: file("A", "test.ts", `import { foo } from '${scope}b/lib/foo';
151import { bar } from '${scope}b/lib/bar/foo';
152foo();
153bar();
154`),
155                        bFoo: file("B", "foo.ts", `export function foo() { }`),
156                        bBar: file("B", "bar/foo.ts", `export function bar() { }`),
157                        bSymlink: {
158                            path: `${projectRoot}/node_modules/${scope}b`,
159                            symLink: `${projectRoot}/packages/B`
160                        },
161                        subScenario: `when referencing file from subFolder${scope ? " with scoped package" : ""}`
162                    }));
163                });
164            }
165            describe("when package is not scoped", () => {
166                verifyMonoRepoLike();
167            });
168            describe("when package is scoped", () => {
169                verifyMonoRepoLike("@issue/");
170            });
171        });
172    });
173}
174