mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[tests][be] Clean up fixture selection logic
--- Refactor selection logic to be easier to read; add support for .jsx test files (feels a bit weird adding a `.jsx` fixture and not seeing it get run)
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
},
|
||||
"include": [
|
||||
"./compiler/**/*.js",
|
||||
"./compiler/**/*.jsx",
|
||||
"./compiler/**/*.ts",
|
||||
"./compiler/**/*.tsx"
|
||||
]
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
import fs from "fs/promises";
|
||||
import glob from "glob";
|
||||
import invariant from "invariant";
|
||||
import path from "path";
|
||||
import { FILTER_PATH, FIXTURES_PATH } from "./constants";
|
||||
|
||||
@@ -32,6 +33,35 @@ async function exists(file: string): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
function stripExtension(filename: string, extensions: Array<string>): string {
|
||||
for (const ext of extensions) {
|
||||
if (filename.endsWith(ext)) {
|
||||
return filename.slice(0, -ext.length);
|
||||
}
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
function shouldSkip(
|
||||
filter: TestFilter | null,
|
||||
filterId: string,
|
||||
filename: string
|
||||
) {
|
||||
if (filter) {
|
||||
if (filter.kind === "only" && filter.paths.indexOf(filterId) === -1) {
|
||||
return true;
|
||||
} else if (
|
||||
filter.kind === "skip" &&
|
||||
filter.paths.indexOf(filterId) !== -1
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
} else if (filename.startsWith("todo.")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function readTestFilter(): Promise<TestFilter | null> {
|
||||
if (!(await exists(FILTER_PATH))) {
|
||||
throw new Error(`testfilter file not found at ${FILTER_PATH}`);
|
||||
@@ -71,71 +101,70 @@ export async function readTestFilter(): Promise<TestFilter | null> {
|
||||
|
||||
export type TestFixture = {
|
||||
basename: string;
|
||||
inputPath: string;
|
||||
inputExists: boolean;
|
||||
inputPath: string | null;
|
||||
outputPath: string;
|
||||
outputExists: boolean;
|
||||
};
|
||||
|
||||
const INPUT_EXTENSIONS = [".js", ".ts", ".jsx", ".tsx"];
|
||||
const OUTPUT_EXTENSION = ".expect.md";
|
||||
export function getFixtures(
|
||||
filter: TestFilter | null
|
||||
): Map<string, TestFixture> {
|
||||
// search for fixtures within nested directories
|
||||
const files = glob.sync(`**/*.{js,ts,tsx,md}`, {
|
||||
const inputFiles = glob.sync(`**/*{${INPUT_EXTENSIONS.join(",")}}`, {
|
||||
cwd: FIXTURES_PATH,
|
||||
});
|
||||
const fixtures: Map<string, TestFixture> = new Map();
|
||||
|
||||
for (const filePath of files) {
|
||||
const basename = path.basename(
|
||||
path.basename(
|
||||
path.basename(path.basename(filePath, ".js"), ".ts"),
|
||||
".tsx"
|
||||
),
|
||||
".expect.md"
|
||||
);
|
||||
// "partial" paths do not include suffixes
|
||||
const partialRelativePath = path.join(path.dirname(filePath), basename);
|
||||
// Replicate jest test behavior
|
||||
if (basename.startsWith("todo.")) {
|
||||
for (const filePath of inputFiles) {
|
||||
const filename = path.basename(filePath);
|
||||
// Do not include extensions in unique identifier for fixture
|
||||
const partialPath = stripExtension(filePath, INPUT_EXTENSIONS);
|
||||
if (shouldSkip(filter, partialPath, filename)) {
|
||||
continue;
|
||||
}
|
||||
if (filter) {
|
||||
if (
|
||||
filter.kind === "only" &&
|
||||
filter.paths.indexOf(partialRelativePath) === -1
|
||||
) {
|
||||
continue;
|
||||
} else if (
|
||||
filter.kind === "skip" &&
|
||||
filter.paths.indexOf(partialRelativePath) !== -1
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let fixtureInfo = fixtures.get(partialRelativePath);
|
||||
const fixtureInfo = fixtures.get(partialPath);
|
||||
if (fixtureInfo === undefined) {
|
||||
const partialAbsolutePath = path.join(FIXTURES_PATH, partialRelativePath);
|
||||
fixtureInfo = {
|
||||
basename,
|
||||
inputPath: `${partialAbsolutePath}.js`,
|
||||
inputExists: false,
|
||||
outputPath: `${partialAbsolutePath}.expect.md`,
|
||||
fixtures.set(partialPath, {
|
||||
basename: path.basename(partialPath),
|
||||
inputPath: path.join(FIXTURES_PATH, filePath),
|
||||
outputPath: path.join(FIXTURES_PATH, partialPath) + OUTPUT_EXTENSION,
|
||||
outputExists: false,
|
||||
};
|
||||
fixtures.set(partialRelativePath, fixtureInfo);
|
||||
});
|
||||
} else {
|
||||
console.warn(
|
||||
"Found duplicate fixture files: ",
|
||||
fixtureInfo.inputPath,
|
||||
filePath
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const outputFiles = glob.sync(`**/*${OUTPUT_EXTENSION}`, {
|
||||
cwd: FIXTURES_PATH,
|
||||
});
|
||||
for (const filePath of outputFiles) {
|
||||
const filename = path.basename(filePath);
|
||||
// Do not include extensions in unique identifier for fixture
|
||||
const partialPath = stripExtension(filePath, [OUTPUT_EXTENSION]);
|
||||
if (shouldSkip(filter, partialPath, filename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
filePath.endsWith(".js") ||
|
||||
filePath.endsWith(".ts") ||
|
||||
filePath.endsWith(".tsx")
|
||||
) {
|
||||
// inputPath may have a different file extension than the .js default
|
||||
fixtureInfo.inputPath = path.join(FIXTURES_PATH, filePath);
|
||||
fixtureInfo.inputExists = true;
|
||||
const fixtureInfo = fixtures.get(partialPath);
|
||||
if (fixtureInfo === undefined) {
|
||||
fixtures.set(partialPath, {
|
||||
basename: path.basename(partialPath),
|
||||
inputPath: null,
|
||||
outputPath: path.join(FIXTURES_PATH, filePath),
|
||||
outputExists: true,
|
||||
});
|
||||
} else {
|
||||
invariant(
|
||||
fixtureInfo.outputPath === path.join(FIXTURES_PATH, filePath),
|
||||
"Unexpected output filepath"
|
||||
);
|
||||
fixtureInfo.outputExists = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ export function clearRequireCache() {
|
||||
}
|
||||
|
||||
export type TestResult = {
|
||||
inputPath: string;
|
||||
outputPath: string;
|
||||
actual: string | null; // null == input did not exist
|
||||
expected: string | null; // null == output did not exist
|
||||
@@ -54,16 +53,15 @@ export async function compile(
|
||||
clearRequireCache();
|
||||
}
|
||||
version = compilerVersion;
|
||||
const { inputPath, inputExists, outputPath, outputExists, basename } =
|
||||
const { inputPath, outputPath, outputExists, basename } =
|
||||
fixture;
|
||||
const input = inputExists ? await fs.readFile(inputPath, "utf8") : null;
|
||||
const input = inputPath != null ? await fs.readFile(inputPath, "utf8") : null;
|
||||
const expected = outputExists ? await fs.readFile(outputPath, "utf8") : null;
|
||||
|
||||
// Input will be null if the input file did not exist, in which case the output file
|
||||
// is stale
|
||||
if (input === null) {
|
||||
return {
|
||||
inputPath,
|
||||
outputPath,
|
||||
actual: null,
|
||||
expected,
|
||||
@@ -128,7 +126,6 @@ export async function compile(
|
||||
console.error = originalConsoleError;
|
||||
|
||||
return {
|
||||
inputPath,
|
||||
outputPath,
|
||||
actual: output,
|
||||
expected,
|
||||
|
||||
@@ -191,12 +191,12 @@ export async function run(fixture: TestFixture): Promise<TestResult> {
|
||||
console.error = (...messages: Array<string>) => {
|
||||
seenConsoleErrors.push(...messages);
|
||||
};
|
||||
const { inputPath, inputExists } = fixture;
|
||||
if (!inputExists) {
|
||||
const { inputPath } = fixture;
|
||||
if (inputPath == null) {
|
||||
return {
|
||||
nonForgetResult: null,
|
||||
forgetResult: null,
|
||||
unexpectedError: "file did not exist!",
|
||||
unexpectedError: "No input for fixture " + fixture.outputPath,
|
||||
};
|
||||
}
|
||||
const inputRaw = await fs.readFile(inputPath, "utf8");
|
||||
|
||||
Reference in New Issue
Block a user