[snap] Refactor fixture utils to separate package
--- Move shared functions to `fixture-test-utils` package.
Mofei Zhang committed
Aug 14, 2023 at 19:26 UTC
5669fc73c0d0ac00d744e22b067bcfc3312b8314
11 files changed
+375
-309
compiler/forget/packages/fixture-test-utils/package.json
new
+25
@@ -0,0 +1,25 @@
1
+{
2
+ "name": "fixture-test-utils",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "license": "MIT",
6
+ "scripts": {
7
+ "build": "rimraf dist && tsc",
8
+ "test": "echo 'no tests'",
9
+ "prettier": "prettier --write src"
10
+ },
11
+ "dependencies": {
12
+ "@parcel/watcher": "^2.1.0",
13
+ "chalk": "4",
14
+ "readline": "^1.3.0",
15
+ "typescript": "^5.1.0",
16
+ "yargs": "^17.7.1"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^18.7.18",
20
+ "@typescript-eslint/eslint-plugin": "^5.51.0",
21
+ "@typescript-eslint/parser": "^5.51.0",
22
+ "prettier": "2.8.8",
23
+ "rimraf": "^3.0.2"
24
+ }
25
+}
compiler/forget/packages/fixture-test-utils/src/compiler-utils.ts
new
+122
@@ -0,0 +1,122 @@
1
+import type { runReactForgetBabelPlugin as RunReactForgetBabelPlugin } from "babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin";
2
+import type { Effect, ValueKind } from "babel-plugin-react-forget/src/HIR";
3
+
4
+const FlowPragmas = [/\/\/\s@flow$/gm, /\*\s@flow$/gm];
5
+
6
+export function parseLanguage(source: string): "flow" | "typescript" {
7
+ let useFlow = false;
8
+ for (const flowPragma of FlowPragmas) {
9
+ useFlow ||= !!source.match(flowPragma);
10
+ }
11
+ return useFlow ? "flow" : "typescript";
12
+}
13
+
14
+export function transformFixtureInput(
15
+ input: string,
16
+ basename: string,
17
+ pluginFn: typeof RunReactForgetBabelPlugin,
18
+ includeAst: boolean = false
19
+) {
20
+ // Extract the first line to quickly check for custom test directives
21
+ const firstLine = input.substring(0, input.indexOf("\n"));
22
+
23
+ let language = parseLanguage(firstLine);
24
+ let enableOnlyOnUseForgetDirective = false;
25
+ let gating = null;
26
+ let instrumentForget = null;
27
+ let panicOnBailout = true;
28
+ let memoizeJsxElements = true;
29
+ let enableAssumeHooksFollowRulesOfReact = false;
30
+ let enableTreatHooksAsFunctions = true;
31
+ let disableAllMemoization = false;
32
+ let validateRefAccessDuringRender = true;
33
+ let validateNoSetStateInRender = true;
34
+ let enableEmitFreeze = null;
35
+ let enableOptimizeFunctionExpressions = true;
36
+ let enableOnlyOnReactScript = false;
37
+
38
+ if (firstLine.indexOf("@forgetDirective") !== -1) {
39
+ enableOnlyOnUseForgetDirective = true;
40
+ }
41
+ if (firstLine.includes("@gating")) {
42
+ gating = {
43
+ source: "ReactForgetFeatureFlag",
44
+ importSpecifierName: "isForgetEnabled_Fixtures",
45
+ };
46
+ }
47
+ if (firstLine.includes("@instrumentForget")) {
48
+ instrumentForget = {
49
+ source: "react-forget-runtime",
50
+ importSpecifierName: "useRenderCounter",
51
+ };
52
+ }
53
+ if (firstLine.includes("@panicOnBailout false")) {
54
+ panicOnBailout = false;
55
+ }
56
+ if (firstLine.includes("@memoizeJsxElements false")) {
57
+ memoizeJsxElements = false;
58
+ }
59
+ if (firstLine.includes("@enableAssumeHooksFollowRulesOfReact true")) {
60
+ enableAssumeHooksFollowRulesOfReact = true;
61
+ }
62
+ if (firstLine.includes("@enableTreatHooksAsFunctions false")) {
63
+ enableTreatHooksAsFunctions = false;
64
+ }
65
+ if (firstLine.includes("@disableAllMemoization true")) {
66
+ disableAllMemoization = true;
67
+ }
68
+ if (firstLine.includes("@validateRefAccessDuringRender false")) {
69
+ validateRefAccessDuringRender = false;
70
+ }
71
+ if (firstLine.includes("@validateNoSetStateInRender false")) {
72
+ validateNoSetStateInRender = false;
73
+ }
74
+ if (firstLine.includes("@enableOptimizeFunctionExpressions false")) {
75
+ enableOptimizeFunctionExpressions = false;
76
+ }
77
+ if (firstLine.includes("@enableEmitFreeze")) {
78
+ enableEmitFreeze = {
79
+ source: "react-forget-runtime",
80
+ importSpecifierName: "makeReadOnly",
81
+ };
82
+ }
83
+ if (firstLine.indexOf("@reactScriptDirective") !== -1) {
84
+ enableOnlyOnReactScript = true;
85
+ language = "flow";
86
+ }
87
+
88
+ return pluginFn(input, basename, language, {
89
+ environment: {
90
+ customHooks: new Map([
91
+ [
92
+ "useFreeze",
93
+ {
94
+ valueKind: "frozen" as ValueKind,
95
+ effectKind: "freeze" as Effect,
96
+ },
97
+ ],
98
+ ]),
99
+ enableAssumeHooksFollowRulesOfReact,
100
+ enableFunctionCallSignatureOptimizations: true,
101
+ disableAllMemoization,
102
+ enableTreatHooksAsFunctions,
103
+ inlineUseMemo: true,
104
+ memoizeJsxElements,
105
+ validateHooksUsage: true,
106
+ validateRefAccessDuringRender,
107
+ validateFrozenLambdas: true,
108
+ validateNoSetStateInRender,
109
+ enableEmitFreeze,
110
+ enableOptimizeFunctionExpressions,
111
+ assertValidMutableRanges: true,
112
+ },
113
+ enableOnlyOnUseForgetDirective,
114
+ enableOnlyOnReactScript,
115
+ logger: null,
116
+ gating,
117
+ instrumentForget,
118
+ panicOnBailout,
119
+ isDev: true,
120
+ noEmit: false,
121
+ });
122
+}
compiler/forget/packages/fixture-test-utils/src/constants.ts
new
+24
@@ -0,0 +1,24 @@
1
+import path from "path";
2
+
3
+// We assume this is run from `babel-plugin-react-forget`
4
+export const COMPILER_PATH = path.join(
5
+ process.cwd(),
6
+ "dist",
7
+ "Babel",
8
+ "RunReactForgetBabelPlugin.js"
9
+);
10
+export const LOGGER_PATH = path.join(
11
+ process.cwd(),
12
+ "dist",
13
+ "Utils",
14
+ "logger.js"
15
+);
16
+export const FIXTURES_PATH = path.join(
17
+ process.cwd(),
18
+ "src",
19
+ "__tests__",
20
+ "fixtures",
21
+ "compiler"
22
+);
23
+export const FILTER_FILENAME = "testfilter.txt";
24
+export const FILTER_PATH = path.join(process.cwd(), FILTER_FILENAME);
compiler/forget/packages/fixture-test-utils/src/fixture-utils.ts
new
+161
@@ -0,0 +1,161 @@
1
+import fs from "fs/promises";
2
+import glob from "glob";
3
+import invariant from "invariant";
4
+import path from "path";
5
+import { FILTER_PATH, FIXTURES_PATH } from "./constants";
6
+
7
+export type TestFilter =
8
+ | {
9
+ kind: "only";
10
+ paths: Array<string>;
11
+ }
12
+ | {
13
+ kind: "skip";
14
+ paths: Array<string>;
15
+ };
16
+
17
+async function exists(file: string): Promise<boolean> {
18
+ try {
19
+ await fs.access(file);
20
+ return true;
21
+ } catch {
22
+ return false;
23
+ }
24
+}
25
+
26
+export async function readTestFilter(): Promise<TestFilter | null> {
27
+ if (!(await exists(FILTER_PATH))) {
28
+ throw new Error(`testfilter file not found at ${FILTER_PATH}`);
29
+ }
30
+
31
+ const input = await fs.readFile(FILTER_PATH, "utf8");
32
+ const lines = input.trim().split("\n");
33
+ if (lines.length < 2) {
34
+ console.warn("Misformed filter file. Expected at least two lines.");
35
+ return null;
36
+ }
37
+
38
+ let filter: "only" | "skip" | null = null;
39
+ if (lines[0]!.indexOf("@only") !== -1) {
40
+ filter = "only";
41
+ }
42
+ if (lines[0]!.indexOf("@skip") !== -1) {
43
+ filter = "skip";
44
+ }
45
+ if (filter === null) {
46
+ console.warn(
47
+ "Misformed filter file. Expected first line to contain @only or @skip"
48
+ );
49
+ return null;
50
+ }
51
+ lines.shift();
52
+ return {
53
+ kind: filter,
54
+ paths: lines,
55
+ };
56
+}
57
+
58
+export type TestFixture = {
59
+ basename: string;
60
+ inputPath: string;
61
+ inputExists: boolean;
62
+ outputPath: string;
63
+ outputExists: boolean;
64
+};
65
+
66
+export function getFixtures(
67
+ filter: TestFilter | null
68
+): Map<string, TestFixture> {
69
+ // search for fixtures within nested directories
70
+ const files = glob.sync(`**/*.{js,md}`, {
71
+ cwd: FIXTURES_PATH,
72
+ });
73
+ const fixtures: Map<string, TestFixture> = new Map();
74
+
75
+ for (const filePath of files) {
76
+ const basename = path.basename(
77
+ path.basename(filePath, ".js"),
78
+ ".expect.md"
79
+ );
80
+ // "partial" paths do not include suffixes
81
+ const partialRelativePath = path.join(path.dirname(filePath), basename);
82
+ // Replicate jest test behavior
83
+ if (basename.startsWith("todo.")) {
84
+ continue;
85
+ }
86
+ if (filter) {
87
+ if (
88
+ filter.kind === "only" &&
89
+ filter.paths.indexOf(partialRelativePath) === -1
90
+ ) {
91
+ continue;
92
+ } else if (
93
+ filter.kind === "skip" &&
94
+ filter.paths.indexOf(partialRelativePath) !== -1
95
+ ) {
96
+ continue;
97
+ }
98
+ }
99
+
100
+ let fixtureInfo = fixtures.get(partialRelativePath);
101
+ if (fixtureInfo === undefined) {
102
+ const partialAbsolutePath = path.join(FIXTURES_PATH, partialRelativePath);
103
+ fixtureInfo = {
104
+ basename,
105
+ inputPath: `${partialAbsolutePath}.js`,
106
+ inputExists: false,
107
+ outputPath: `${partialAbsolutePath}.expect.md`,
108
+ outputExists: false,
109
+ };
110
+ fixtures.set(partialRelativePath, fixtureInfo);
111
+ }
112
+
113
+ if (filePath.endsWith(".js")) {
114
+ fixtureInfo.inputExists = true;
115
+ } else {
116
+ fixtureInfo.outputExists = true;
117
+ }
118
+ }
119
+
120
+ return fixtures;
121
+}
122
+
123
+function wrapWithTripleBackticks(s: string, ext: string | null = null): string {
124
+ return `\`\`\`${ext ?? ""}
125
+${s}
126
+\`\`\``;
127
+}
128
+
129
+export function writeOutputToString(
130
+ input: string,
131
+ output: string | null,
132
+ error: Error | null
133
+) {
134
+ // leading newline intentional
135
+ let result = `
136
+## Input
137
+
138
+${wrapWithTripleBackticks(input, "javascript")}
139
+`; // trailing newline + space internional
140
+
141
+ if (output != null) {
142
+ result += `
143
+## Code
144
+
145
+${output == null ? "[ none ]" : wrapWithTripleBackticks(output, "javascript")}
146
+`;
147
+ } else {
148
+ result += "\n";
149
+ }
150
+
151
+ if (error != null) {
152
+ const errorMessage = error.message.replace(/^\/.*?:\s/, "");
153
+
154
+ result += `
155
+## Error
156
+
157
+${wrapWithTripleBackticks(errorMessage)}
158
+ \n`;
159
+ }
160
+ return result + ` `;
161
+}
compiler/forget/packages/fixture-test-utils/src/index.ts
new
+3
@@ -0,0 +1,3 @@
1
+export * from "./constants";
2
+export * from "./fixture-utils";
3
+export * from "./compiler-utils";
compiler/forget/packages/fixture-test-utils/tsconfig.json
new
+20
@@ -0,0 +1,20 @@
1
+{
2
+ "extends": "@tsconfig/node16-strictest/tsconfig.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "outDir": "dist",
6
+ "jsx": "react-jsxdev",
7
+
8
+ // weaken strictness from preset
9
+ "importsNotUsedAsValues": "remove",
10
+ "noUncheckedIndexedAccess": false,
11
+ "noUnusedParameters": false,
12
+ "useUnknownInCatchVariables": false,
13
+ "target": "ES2015",
14
+ // ideally turn off only during dev, or on a per-file basis
15
+ "noUnusedLocals": false,
16
+ "sourceMap": true
17
+ },
18
+ "exclude": ["node_modules"],
19
+ "include": ["src/**/*.ts"]
20
+}
compiler/forget/packages/snap/package.json
+3
-2
@@ -9,7 +9,7 @@
9
"src"
10
],
11
"scripts": {
12
- "build": "rimraf dist && tsc",
12
+ "build": "yarn workspace fixture-test-utils run build && rimraf dist && tsc",
13
"test": "echo 'no tests'",
14
"lint": "yarn eslint src"
15
},
@@ -22,7 +22,8 @@
22
"chalk": "4",
23
"readline": "^1.3.0",
24
"typescript": "^5.1.0",
25
- "yargs": "^17.7.1"
25
+ "yargs": "^17.7.1",
26
+ "fixture-test-utils": "*"
27
},
28
"devDependencies": {
29
"@types/node": "^18.7.18",
compiler/forget/packages/snap/src/compiler-worker.ts
+13
-185
@@ -6,9 +6,8 @@
6
*/
7
8
import type { runReactForgetBabelPlugin as RunReactForgetBabelPlugin } from 'babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin';
9
-import type { Effect, ValueKind } from 'babel-plugin-react-forget/src/HIR';
9
+import { TestFixture, transformFixtureInput, writeOutputToString } from 'fixture-test-utils';
10
import fs from "fs/promises";
11
-import { exists } from "./utils";
11
12
const originalConsoleError = console.error;
13
@@ -33,12 +32,6 @@ export type TestResult = {
32
unexpectedError: string | null;
33
};
34
36
-export type TestFixture = {
37
- basename: string;
38
- inputPath: string;
39
- outputPath: string;
40
-};
41
-
35
export async function compile(
36
compilerPath: string,
37
loggerPath: string,
@@ -54,11 +47,11 @@ export async function compile(
47
clearRequireCache();
48
}
49
version = compilerVersion;
57
- const { inputPath, outputPath, basename } = fixture;
58
- const input = (await exists(inputPath))
50
+ const { inputPath, inputExists, outputPath, outputExists, basename } = fixture;
51
+ const input = inputExists
52
? await fs.readFile(inputPath, "utf8")
53
: null;
61
- const expected = (await exists(outputPath))
54
+ const expected = outputExists
55
? await fs.readFile(outputPath, "utf8")
56
: null;
57
@@ -86,108 +79,7 @@ export async function compile(
79
// since console log order is non-deterministic
80
const shouldLogPragma = input.split("\n")[0].includes("@debug");
81
toggleLogging(isOnlyFixture && shouldLogPragma);
89
-
90
- // Extract the first line to quickly check for custom test directives
91
- const firstLine = input.substring(0, input.indexOf("\n"));
92
- let language = parseLanguage(firstLine);
93
-
94
- let enableOnlyOnUseForgetDirective = false;
95
- let gating = null;
96
- let instrumentForget = null;
97
- let panicOnBailout = true;
98
- let memoizeJsxElements = true;
99
- let enableAssumeHooksFollowRulesOfReact = false;
100
- let enableTreatHooksAsFunctions = true;
101
- let disableAllMemoization = false;
102
- let validateRefAccessDuringRender = true;
103
- let validateNoSetStateInRender = true;
104
- let enableEmitFreeze = null;
105
- let enableOptimizeFunctionExpressions = true;
106
- let enableOnlyOnReactScript = false;
107
- if (firstLine.indexOf("@forgetDirective") !== -1) {
108
- enableOnlyOnUseForgetDirective = true;
109
- }
110
- if (firstLine.includes("@gating")) {
111
- gating = {
112
- source: "ReactForgetFeatureFlag",
113
- importSpecifierName: "isForgetEnabled_Fixtures",
114
- };
115
- }
116
- if (firstLine.includes("@instrumentForget")) {
117
- instrumentForget = {
118
- source: "react-forget-runtime",
119
- importSpecifierName: "useRenderCounter",
120
- };
121
- }
122
- if (firstLine.includes("@panicOnBailout false")) {
123
- panicOnBailout = false;
124
- }
125
- if (firstLine.includes("@memoizeJsxElements false")) {
126
- memoizeJsxElements = false;
127
- }
128
- if (firstLine.includes("@enableAssumeHooksFollowRulesOfReact true")) {
129
- enableAssumeHooksFollowRulesOfReact = true;
130
- }
131
- if (firstLine.includes("@enableTreatHooksAsFunctions false")) {
132
- enableTreatHooksAsFunctions = false;
133
- }
134
- if (firstLine.includes("@disableAllMemoization true")) {
135
- disableAllMemoization = true;
136
- }
137
- if (firstLine.includes("@validateRefAccessDuringRender false")) {
138
- validateRefAccessDuringRender = false;
139
- }
140
- if (firstLine.includes("@validateNoSetStateInRender false")) {
141
- validateNoSetStateInRender = false;
142
- }
143
- if (firstLine.includes("@enableOptimizeFunctionExpressions false")) {
144
- enableOptimizeFunctionExpressions = false;
145
- }
146
- if (firstLine.includes("@enableEmitFreeze")) {
147
- enableEmitFreeze = {
148
- source: "react-forget-runtime",
149
- importSpecifierName: "makeReadOnly",
150
- };
151
- }
152
- if (firstLine.indexOf("@reactScriptDirective") !== -1) {
153
- enableOnlyOnReactScript = true;
154
- language = "flow";
155
- }
156
-
157
- code = runReactForgetBabelPlugin(input, basename, language, {
158
- environment: {
159
- customHooks: new Map([
160
- [
161
- "useFreeze",
162
- {
163
- valueKind: "frozen" as ValueKind,
164
- effectKind: "freeze" as Effect,
165
- },
166
- ],
167
- ]),
168
- enableAssumeHooksFollowRulesOfReact,
169
- enableFunctionCallSignatureOptimizations: true,
170
- disableAllMemoization,
171
- enableTreatHooksAsFunctions,
172
- inlineUseMemo: true,
173
- memoizeJsxElements,
174
- validateHooksUsage: true,
175
- validateRefAccessDuringRender,
176
- validateFrozenLambdas: true,
177
- validateNoSetStateInRender,
178
- enableEmitFreeze,
179
- enableOptimizeFunctionExpressions,
180
- assertValidMutableRanges: true,
181
- },
182
- enableOnlyOnUseForgetDirective,
183
- enableOnlyOnReactScript,
184
- logger: null,
185
- gating,
186
- instrumentForget,
187
- panicOnBailout,
188
- isDev: true,
189
- noEmit: false,
190
- }).code;
82
+ code = transformFixtureInput(input, basename, runReactForgetBabelPlugin).code;
83
} catch (e) {
84
error = e;
85
}
@@ -202,92 +94,28 @@ export async function compile(
94
}
95
}
96
205
- let output: string;
97
+ const output = writeOutputToString(input, code, error);
98
const expectError = basename.startsWith("error.");
99
+ let unexpectedError: string | null = null;
100
if (expectError) {
101
if (error === null) {
209
- return {
210
- inputPath,
211
- outputPath,
212
- actual: code,
213
- expected,
214
- unexpectedError: `Expected an error to be thrown for fixture: '${basename}', remove the 'error.' prefix if an error is not expected.`,
215
- };
216
- } else if (code != null) {
217
- output = `${formatOutput(code)}\n${formatErrorOutput(error)}`;
218
- } else {
219
- output = formatErrorOutput(error);
102
+ unexpectedError = `Expected an error to be thrown for fixture: '${basename}', remove the 'error.' prefix if an error is not expected.`;
103
}
104
} else {
105
if (error !== null) {
223
- return {
224
- inputPath,
225
- outputPath,
226
- actual: code,
227
- expected,
228
- unexpectedError: `Expected fixture '${basename}' to succeed but it failed with error:\n\n${error.message}`,
229
- };
106
+ unexpectedError = `Expected fixture '${basename}' to succeed but it failed with error:\n\n${error.message}`;
107
+ } else if (code == null || code.length === 0) {
108
+ unexpectedError = `Expected output for fixture '${basename}'.`;
109
}
231
- if (code == null || code.length === 0) {
232
- return {
233
- inputPath,
234
- outputPath,
235
- actual: code,
236
- expected,
237
- unexpectedError: `Expected output for fixture '${basename}'.`,
238
- };
239
- }
240
- output = formatOutput(code);
110
}
111
243
- // leading newline intentional
244
- const actual = `
245
-## Input
246
-
247
-${wrapWithTripleBackticks(input, "javascript")}
248
-
249
-${output}
250
- `; // trailing newline + space internional
251
-
112
console.error = originalConsoleError;
113
114
return {
115
inputPath,
116
outputPath,
257
- actual,
117
+ actual: output,
118
expected,
259
- unexpectedError: null,
119
+ unexpectedError,
120
};
121
}
262
-
263
-function formatErrorOutput(error: Error): string {
264
- error.message = error.message.replace(/^\/.*?:\s/, "");
265
- return `
266
-## Error
267
-
268
-${wrapWithTripleBackticks(error.message)}
269
- `;
270
-}
271
-
272
-function formatOutput(code: string): string {
273
- return `
274
-## Code
275
-
276
-${wrapWithTripleBackticks(code, "javascript")}
277
- `.trim();
278
-}
279
-
280
-function wrapWithTripleBackticks(s: string, ext: string | null = null): string {
281
- return `\`\`\`${ext ?? ""}
282
-${s}
283
-\`\`\``;
284
-}
285
-
286
-const FlowPragmas = [/\/\/\s@flow$/gm, /\*\s@flow$/gm];
287
-function parseLanguage(source: string): "flow" | "typescript" {
288
- let useFlow = false;
289
- for (const flowPragma of FlowPragmas) {
290
- useFlow ||= !!source.match(flowPragma);
291
- }
292
- return useFlow ? "flow" : "typescript";
293
-}
compiler/forget/packages/snap/src/main.ts
+1
-1
@@ -17,7 +17,7 @@ if (process.stdin.isTTY) {
17
process.stdin.setRawMode(true);
18
}
19
20
-process.stdin.on("keypress", function (chunk, key) {
20
+process.stdin.on("keypress", function (_, key) {
21
if (key && key.name === "c" && key.ctrl) {
22
// handle sigint
23
if (childProc) {
compiler/forget/packages/snap/src/runner.ts
+3
-104
@@ -7,8 +7,8 @@
7
8
import watcher from "@parcel/watcher";
9
import chalk from "chalk";
10
+import { COMPILER_PATH, LOGGER_PATH, FIXTURES_PATH, FILTER_FILENAME, FILTER_PATH, readTestFilter, TestFilter } from 'fixture-test-utils';
11
import fs from "fs/promises";
11
-import glob from "glob";
12
import invariant from "invariant";
13
import { diff } from "jest-diff";
14
import { Worker } from "jest-worker";
@@ -19,26 +19,10 @@ import ts from "typescript";
19
import yargs from "yargs";
20
import { hideBin } from "yargs/helpers";
21
import { TestResult } from "./compiler-worker";
22
-import * as compiler from "./compiler-worker.js";
23
-import { exists } from "./utils";
22
+import * as compiler from "./compiler-worker";
23
+import {getFixtures} from 'fixture-test-utils';
24
25
const WORKER_PATH = require.resolve("./compiler-worker.js");
26
-const COMPILER_PATH = path.join(
27
- process.cwd(),
28
- "dist",
29
- "Babel",
30
- "RunReactForgetBabelPlugin.js"
31
-);
32
-const LOGGER_PATH = path.join(process.cwd(), "dist", "Utils", "logger.js");
33
-const FIXTURES_PATH = path.join(
34
- process.cwd(),
35
- "src",
36
- "__tests__",
37
- "fixtures",
38
- "compiler"
39
-);
40
-const FILTER_FILENAME = "testfilter.txt";
41
-const FILTER_PATH = path.join(process.cwd(), FILTER_FILENAME);
26
27
readline.emitKeypressEvents(process.stdin);
28
@@ -109,49 +93,6 @@ function clearConsole() {
93
console.log("\u001Bc");
94
}
95
112
-function getFixtures(
113
- filter: TestFilter | null
114
-): Map<string, compiler.TestFixture> {
115
- // search for fixtures within nested directories
116
- const files = glob.sync(`**/*.{js,md}`, {
117
- cwd: FIXTURES_PATH,
118
- });
119
- const fixtures = new Map();
120
-
121
- for (const filePath of files) {
122
- const basename = path.basename(
123
- path.basename(filePath, ".js"),
124
- ".expect.md"
125
- );
126
- // "partial" paths do not include suffixes
127
- const partialRelativePath = path.join(path.dirname(filePath), basename);
128
- const partialAbsolutePath = path.join(FIXTURES_PATH, partialRelativePath);
129
- // Replicate jest test behavior
130
- if (basename.startsWith("todo.")) {
131
- continue;
132
- }
133
- if (filter) {
134
- if (
135
- filter.kind === "only" &&
136
- filter.paths.indexOf(partialRelativePath) === -1
137
- ) {
138
- continue;
139
- } else if (
140
- filter.kind === "skip" &&
141
- filter.paths.indexOf(partialRelativePath) !== -1
142
- ) {
143
- continue;
144
- }
145
- }
146
- fixtures.set(partialRelativePath, {
147
- basename,
148
- inputPath: `${partialAbsolutePath}.js`,
149
- outputPath: `${partialAbsolutePath}.expect.md`,
150
- });
151
- }
152
- // console.log("fixtures!", JSON.stringify(Array.from(fixtures.keys())));
153
- return fixtures;
154
-}
96
/**
97
* Do a test run and return the test results
98
*/
@@ -395,48 +336,6 @@ enum Mode {
336
Update = "Update",
337
}
338
398
-type TestFilter =
399
- | {
400
- kind: "only";
401
- paths: Array<string>;
402
- }
403
- | {
404
- kind: "skip";
405
- paths: Array<string>;
406
- };
407
-
408
-async function readTestFilter(): Promise<TestFilter | null> {
409
- if (!(await exists(FILTER_PATH))) {
410
- throw new Error(`testfilter file not found at ${FILTER_PATH}`);
411
- }
412
-
413
- const input = await fs.readFile(FILTER_PATH, "utf8");
414
- const lines = input.trim().split("\n");
415
- if (lines.length < 2) {
416
- console.warn("Misformed filter file. Expected at least two lines.");
417
- return null;
418
- }
419
-
420
- let filter: "only" | "skip" | null = null;
421
- if (lines[0]!.indexOf("@only") !== -1) {
422
- filter = "only";
423
- }
424
- if (lines[0]!.indexOf("@skip") !== -1) {
425
- filter = "skip";
426
- }
427
- if (filter === null) {
428
- console.warn(
429
- "Misformed filter file. Expected first line to contain @only or @skip"
430
- );
431
- return null;
432
- }
433
- lines.shift();
434
- return {
435
- kind: filter,
436
- paths: lines,
437
- };
438
-}
439
-
339
/**
340
* Runs the compiler in watch or single-execution mode
341
*/
compiler/forget/packages/snap/src/utils.ts
deleted
-17
@@ -1,17 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
-import fs from "fs/promises";
9
-
10
-export async function exists(file: string): Promise<boolean> {
11
- try {
12
- await fs.access(file);
13
- return true;
14
- } catch {
15
- return false;
16
- }
17
-}