• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    describe("unittests:: tsc:: incremental::", () => {
3        verifyTscSerializedIncrementalEdits({
4            scenario: "incremental",
5            subScenario: "when passing filename for buildinfo on commandline",
6            fs: () => loadProjectFromFiles({
7                "/src/project/src/main.ts": "export const x = 10;",
8                "/src/project/tsconfig.json": Utils.dedent`
9                    {
10                        "compilerOptions": {
11                            "target": "es5",
12                            "module": "commonjs",
13                        },
14                        "include": [
15                            "src/**/*.ts"
16                        ]
17                    }`,
18            }),
19            commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo", "--explainFiles"],
20            incrementalScenarios: noChangeOnlyRuns
21        });
22
23        verifyTscSerializedIncrementalEdits({
24            scenario: "incremental",
25            subScenario: "when passing rootDir from commandline",
26            fs: () => loadProjectFromFiles({
27                "/src/project/src/main.ts": "export const x = 10;",
28                "/src/project/tsconfig.json": Utils.dedent`
29                    {
30                        "compilerOptions": {
31                            "incremental": true,
32                            "outDir": "dist",
33                        },
34                    }`,
35            }),
36            commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"],
37            incrementalScenarios: noChangeOnlyRuns
38        });
39
40        verifyTscSerializedIncrementalEdits({
41            scenario: "incremental",
42            subScenario: "with only dts files",
43            fs: () => loadProjectFromFiles({
44                "/src/project/src/main.d.ts": "export const x = 10;",
45                "/src/project/src/another.d.ts": "export const y = 10;",
46                "/src/project/tsconfig.json": "{}",
47            }),
48            commandLineArgs: ["--incremental", "--p", "src/project"],
49            incrementalScenarios: [
50                noChangeRun,
51                {
52                    buildKind: BuildKind.IncrementalDtsUnchanged,
53                    modifyFs: fs => appendText(fs, "/src/project/src/main.d.ts", "export const xy = 100;")
54                }
55            ]
56        });
57
58        verifyTscSerializedIncrementalEdits({
59            scenario: "incremental",
60            subScenario: "when passing rootDir is in the tsconfig",
61            fs: () => loadProjectFromFiles({
62                "/src/project/src/main.ts": "export const x = 10;",
63                "/src/project/tsconfig.json": Utils.dedent`
64                    {
65                        "compilerOptions": {
66                            "incremental": true,
67                            "outDir": "./built",
68                            "rootDir": "./"
69                        },
70                    }`,
71            }),
72            commandLineArgs: ["--p", "src/project"],
73            incrementalScenarios: noChangeOnlyRuns
74        });
75
76        describe("with noEmitOnError", () => {
77            let projFs: vfs.FileSystem;
78            before(() => {
79                projFs = loadProjectFromDisk("tests/projects/noEmitOnError");
80            });
81            after(() => {
82                projFs = undefined!;
83            });
84
85            function verifyNoEmitOnError(subScenario: string, fixModifyFs: TscIncremental["modifyFs"], modifyFs?: TscIncremental["modifyFs"]) {
86                verifyTscSerializedIncrementalEdits({
87                    scenario: "incremental",
88                    subScenario,
89                    fs: () => projFs,
90                    commandLineArgs: ["--incremental", "-p", "src"],
91                    modifyFs,
92                    incrementalScenarios: [
93                        noChangeRun,
94                        {
95                            buildKind: BuildKind.IncrementalDtsUnchanged,
96                            modifyFs: fixModifyFs
97                        },
98                        noChangeRun,
99                    ],
100                    baselinePrograms: true
101                });
102            }
103            verifyNoEmitOnError(
104                "with noEmitOnError syntax errors",
105                fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
106const a = {
107    lastName: 'sdsd'
108};`, "utf-8")
109            );
110
111            verifyNoEmitOnError(
112                "with noEmitOnError semantic errors",
113                fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
114const a: string = "hello";`, "utf-8"),
115                fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db";
116const a: string = 10;`, "utf-8"),
117            );
118        });
119
120        describe("when noEmit changes between compilation", () => {
121            verifyNoEmitChanges({ incremental: true });
122            verifyNoEmitChanges({ incremental: true, declaration: true });
123            verifyNoEmitChanges({ composite: true });
124
125            function verifyNoEmitChanges(compilerOptions: CompilerOptions) {
126                const noChangeRunWithNoEmit: TscIncremental = {
127                    subScenario: "No Change run with noEmit",
128                    commandLineArgs: ["--p", "src/project", "--noEmit"],
129                    ...noChangeRun,
130                };
131                const noChangeRunWithEmit: TscIncremental = {
132                    subScenario: "No Change run with emit",
133                    commandLineArgs: ["--p", "src/project"],
134                    ...noChangeRun,
135                };
136                let optionsString = "";
137                for (const key in compilerOptions) {
138                    if (hasProperty(compilerOptions, key)) {
139                        optionsString += ` ${key}`;
140                    }
141                }
142
143                verifyTscSerializedIncrementalEdits({
144                    scenario: "incremental",
145                    subScenario: `noEmit changes${optionsString}`,
146                    commandLineArgs: ["--p", "src/project"],
147                    fs,
148                    incrementalScenarios: [
149                        noChangeRunWithNoEmit,
150                        noChangeRunWithNoEmit,
151                        {
152                            subScenario: "Introduce error but still noEmit",
153                            commandLineArgs: ["--p", "src/project", "--noEmit"],
154                            modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
155                            buildKind: BuildKind.IncrementalDtsChange
156                        },
157                        {
158                            subScenario: "Fix error and emit",
159                            modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
160                            buildKind: BuildKind.IncrementalDtsChange
161                        },
162                        noChangeRunWithEmit,
163                        noChangeRunWithNoEmit,
164                        noChangeRunWithNoEmit,
165                        noChangeRunWithEmit,
166                        {
167                            subScenario: "Introduce error and emit",
168                            modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
169                            buildKind: BuildKind.IncrementalDtsChange
170                        },
171                        noChangeRunWithEmit,
172                        noChangeRunWithNoEmit,
173                        noChangeRunWithNoEmit,
174                        noChangeRunWithEmit,
175                        {
176                            subScenario: "Fix error and no emit",
177                            commandLineArgs: ["--p", "src/project", "--noEmit"],
178                            modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
179                            buildKind: BuildKind.IncrementalDtsChange
180                        },
181                        noChangeRunWithEmit,
182                        noChangeRunWithNoEmit,
183                        noChangeRunWithNoEmit,
184                        noChangeRunWithEmit,
185                    ],
186                });
187
188                verifyTscSerializedIncrementalEdits({
189                    scenario: "incremental",
190                    subScenario: `noEmit changes with initial noEmit${optionsString}`,
191                    commandLineArgs: ["--p", "src/project", "--noEmit"],
192                    fs,
193                    incrementalScenarios: [
194                        noChangeRunWithEmit,
195                        {
196                            subScenario: "Introduce error with emit",
197                            commandLineArgs: ["--p", "src/project"],
198                            modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
199                            buildKind: BuildKind.IncrementalDtsChange
200                        },
201                        {
202                            subScenario: "Fix error and no emit",
203                            modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
204                            buildKind: BuildKind.IncrementalDtsChange
205                        },
206                        noChangeRunWithEmit,
207                    ],
208                });
209
210                function fs() {
211                    return loadProjectFromFiles({
212                        "/src/project/src/class.ts": Utils.dedent`
213                            export class classC {
214                                prop = 1;
215                            }`,
216                        "/src/project/src/indirectClass.ts": Utils.dedent`
217                            import { classC } from './class';
218                            export class indirectClass {
219                                classC = new classC();
220                            }`,
221                        "/src/project/src/directUse.ts": Utils.dedent`
222                            import { indirectClass } from './indirectClass';
223                            new indirectClass().classC.prop;`,
224                        "/src/project/src/indirectUse.ts": Utils.dedent`
225                            import { indirectClass } from './indirectClass';
226                            new indirectClass().classC.prop;`,
227                        "/src/project/src/noChangeFile.ts": Utils.dedent`
228                            export function writeLog(s: string) {
229                            }`,
230                        "/src/project/src/noChangeFileWithEmitSpecificError.ts": Utils.dedent`
231                            function someFunc(arguments: boolean, ...rest: any[]) {
232                            }`,
233                        "/src/project/tsconfig.json": JSON.stringify({ compilerOptions }),
234                    });
235                }
236            }
237        });
238
239        const jsxLibraryContent = `
240export {};
241declare global {
242    namespace JSX {
243        interface Element {}
244        interface IntrinsicElements {
245            div: {
246                propA?: boolean;
247            };
248        }
249    }
250}`;
251
252        verifyTsc({
253            scenario: "react-jsx-emit-mode",
254            subScenario: "with no backing types found doesn't crash",
255            fs: () => loadProjectFromFiles({
256                "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
257                "/src/project/node_modules/@types/react/index.d.ts": jsxLibraryContent, // doesn't contain a jsx-runtime definition
258                "/src/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`,
259                "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } })
260            }),
261            commandLineArgs: ["--p", "src/project"]
262        });
263
264        verifyTsc({
265            scenario: "react-jsx-emit-mode",
266            subScenario: "with no backing types found doesn't crash under --strict",
267            fs: () => loadProjectFromFiles({
268                "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
269                "/src/project/node_modules/@types/react/index.d.ts": jsxLibraryContent, // doesn't contain a jsx-runtime definition
270                "/src/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`,
271                "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } })
272            }),
273            commandLineArgs: ["--p", "src/project", "--strict"]
274        });
275    });
276}
277