Skip to content

Commit 5144882

Browse files
authored
moving loading tests code logic into their own file (#1495)
* moving is error test logic into utilities.js * moving get fixtures logic into its own file * updating the fixture logic. returning the new more complete fixture object and using a generator pattern to avoid calling `filter(Boolean)` over the array. * fail early * using the fixture approach, preparing to delegate this section
1 parent a81e55f commit 5144882

4 files changed

Lines changed: 150 additions & 103 deletions

File tree

tests/config/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { normalizeDirectory } from "./utilities.js";
44

55
const { __dirname } = createEsmUtils(import.meta);
66

7+
export const FORMAT_SCRIPT_FILENAME = "format.test.js";
8+
79
export const FORMAT_TEST_DIRECTORY = normalizeDirectory(
810
path.join(__dirname, "../format/"),
911
);

tests/config/get-fixtures.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
import { FORMAT_SCRIPT_FILENAME } from "./constants.js";
4+
import visualizeEndOfLine from "./utils/visualize-end-of-line.js";
5+
6+
function* getFixtures(context) {
7+
yield* getFiles(context);
8+
yield* getSnippets(context);
9+
}
10+
11+
function* getFiles(context) {
12+
const { dirname } = context;
13+
for (const file of fs.readdirSync(dirname, { withFileTypes: true })) {
14+
const filename = file.name;
15+
const filepath = path.join(dirname, filename);
16+
if (
17+
!file.isFile() ||
18+
filename[0] === "." ||
19+
filename === FORMAT_SCRIPT_FILENAME ||
20+
// VSCode creates this file sometime https://github.com/microsoft/vscode/issues/105191
21+
filename === "debug.log" ||
22+
path.extname(filename) === ".snap"
23+
) {
24+
continue;
25+
}
26+
27+
const text = fs.readFileSync(filepath, "utf8");
28+
29+
yield {
30+
context,
31+
name: filename,
32+
filename,
33+
filepath,
34+
code: text,
35+
};
36+
}
37+
}
38+
39+
function* getSnippets(context) {
40+
for (const [index, snippet] of context.snippets.entries()) {
41+
const testCase =
42+
typeof snippet === "string"
43+
? { code: snippet, context }
44+
: { ...snippet, context };
45+
46+
if (typeof testCase.code !== "string") {
47+
throw Object.assign(new Error("Invalid test"), { snippet });
48+
}
49+
50+
if (typeof testCase.output === "string") {
51+
testCase.output = visualizeEndOfLine(testCase.output);
52+
}
53+
54+
testCase.name = `snippet: ${testCase.name || `#${index}`}`;
55+
56+
if (typeof testCase.filename === "string") {
57+
testCase.filepath = path.join(context.dirname, testCase.filename);
58+
}
59+
60+
yield testCase;
61+
}
62+
}
63+
64+
export { getFixtures };

tests/config/run-format-test.js

Lines changed: 79 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,141 +1,119 @@
1-
import fs from "node:fs";
21
import path from "node:path";
32
import url from "node:url";
4-
import createEsmUtils from "esm-utils";
3+
import { FORMAT_SCRIPT_FILENAME } from "./constants.js";
4+
import { getFixtures } from "./get-fixtures.js";
55
import { stringifyOptionsForTitle } from "./utils/stringify-options-for-title.js";
6+
import {
7+
isErrorTest as isErrorTestDirectory,
8+
normalizeDirectory,
9+
} from "./utilities.js";
610
import { format } from "./run-prettier.js";
11+
import { replacePlaceholders } from "./replace-placeholders.js";
712
import { runTest } from "./run-test.js";
813
import { shouldThrowOnFormat } from "./utilities.js";
914

10-
const { __dirname } = createEsmUtils(import.meta);
11-
12-
const isTestDirectory = (dirname, name) =>
13-
(dirname + path.sep).startsWith(
14-
path.join(__dirname, "../format", name) + path.sep,
15-
);
16-
17-
function runFormatTest(fixtures, parsers, options) {
18-
let { importMeta, snippets = [] } = fixtures.importMeta
19-
? fixtures
20-
: { importMeta: fixtures };
15+
function runFormatTest(rawFixtures, explicitParsers, rawOptions) {
16+
const { importMeta, snippets = [] } = rawFixtures.importMeta
17+
? rawFixtures
18+
: { importMeta: rawFixtures };
2119

2220
const filename = path.basename(new URL(importMeta.url).pathname);
23-
if (filename !== "format.test.js") {
24-
throw new Error(`Format test should run in file named 'format.test.js'.`);
21+
if (filename !== FORMAT_SCRIPT_FILENAME) {
22+
throw new Error(
23+
`Format test should run in file named '${FORMAT_SCRIPT_FILENAME}'.`,
24+
);
2525
}
2626

27-
const dirname = path.dirname(url.fileURLToPath(importMeta.url));
28-
29-
// `IS_PARSER_INFERENCE_TESTS` mean to test `inferParser` on `standalone`
30-
const IS_PARSER_INFERENCE_TESTS = isTestDirectory(
31-
dirname,
32-
"misc/parser-inference",
27+
const dirname = normalizeDirectory(
28+
path.dirname(url.fileURLToPath(importMeta.url)),
3329
);
3430

35-
// `IS_ERROR_TESTS` mean to watch errors like:
31+
let options = { ...rawOptions };
32+
33+
// `IS_ERROR_TEST` mean to watch errors like:
3634
// - syntax parser hasn't supported yet
3735
// - syntax errors that should throws
38-
const IS_ERROR_TESTS = isTestDirectory(dirname, "misc/errors");
39-
if (IS_ERROR_TESTS) {
40-
options = { errors: true, ...options };
41-
}
36+
const isErrorTest = isErrorTestDirectory(dirname);
4237

43-
if (IS_PARSER_INFERENCE_TESTS) {
44-
parsers = [undefined];
38+
if (isErrorTest) {
39+
options = { errors: true, ...options };
4540
}
4641

47-
snippets = snippets.map((test, index) => {
48-
test = typeof test === "string" ? { code: test } : test;
49-
50-
if (typeof test.code !== "string") {
51-
throw Object.assign(new Error("Invalid test"), { test });
52-
}
53-
54-
return {
55-
...test,
56-
name: `snippet: ${test.name || `#${index}`}`,
57-
};
58-
});
59-
60-
const files = fs
61-
.readdirSync(dirname, { withFileTypes: true })
62-
.map((file) => {
63-
const basename = file.name;
64-
const filename = path.join(dirname, basename);
65-
if (
66-
path.extname(basename) === ".snap" ||
67-
!file.isFile() ||
68-
basename[0] === "." ||
69-
basename === "format.test.js" ||
70-
// VSCode creates this file sometime https://github.com/microsoft/vscode/issues/105191
71-
basename === "debug.log"
72-
) {
73-
return;
74-
}
75-
76-
const text = fs.readFileSync(filename, "utf8");
77-
78-
return {
79-
name: basename,
80-
filename,
81-
code: text,
82-
};
83-
})
84-
.filter(Boolean);
85-
86-
const [parser] = parsers;
87-
const allParsers = [...parsers];
88-
89-
const stringifiedOptions = stringifyOptionsForTitle(options);
42+
const context = {
43+
dirname,
44+
stringifiedOptions: stringifyOptionsForTitle(rawOptions),
45+
parsers: [...explicitParsers],
46+
options,
47+
explicitParsers,
48+
rawOptions,
49+
snippets,
50+
};
51+
52+
for (const fixture of getFixtures(context)) {
53+
const { name, context, filepath } = fixture;
54+
const { stringifiedOptions, parsers } = context;
9055

91-
for (const { name, filename, code, output } of [...files, ...snippets]) {
9256
const title = `${name}${
9357
stringifiedOptions ? ` - ${stringifiedOptions}` : ""
9458
}`;
9559

9660
describe(title, () => {
97-
const formatOptions = {
98-
printWidth: 80,
99-
...options,
100-
filepath: filename,
101-
parser,
102-
};
103-
const shouldThrowOnMainParserFormat = shouldThrowOnFormat(
104-
name,
105-
formatOptions,
106-
);
107-
108-
let mainParserFormatResult;
109-
if (shouldThrowOnMainParserFormat) {
110-
mainParserFormatResult = { options: formatOptions, error: true };
111-
} else {
112-
beforeAll(async () => {
113-
mainParserFormatResult = await format(code, formatOptions);
114-
});
115-
}
61+
const testCases = parsers.map((parser) => getTestCase(fixture, parser));
11662

117-
for (const currentParser of allParsers) {
63+
for (const testCase of testCases) {
11864
const testTitle =
119-
shouldThrowOnMainParserFormat ||
120-
formatOptions.parser !== currentParser
121-
? `[${currentParser}] format`
65+
testCase.expectFail ||
66+
testCase.formatOptions.parser !== testCase.parser
67+
? `[${testCase.parser}] format`
12268
: "format";
12369

12470
test(testTitle, async () => {
12571
await runTest({
12672
parsers,
12773
name,
128-
filename,
129-
code,
130-
output,
131-
parser: currentParser,
132-
mainParserFormatResult,
133-
mainParserFormatOptions: formatOptions,
74+
filename: filepath,
75+
code: testCase.code,
76+
output: testCase.expectedOutput,
77+
parser: testCase.parser,
78+
mainParserFormatResult: await testCase.runFormat(),
79+
mainParserFormatOptions: testCase.formatOptions,
13480
});
13581
});
13682
}
13783
});
13884
}
13985
}
14086

87+
function getTestCase(fixture, parser) {
88+
const { code: originalText, context, filepath } = fixture;
89+
90+
const { text: code, options: formatOptions } = replacePlaceholders(
91+
originalText,
92+
{
93+
printWidth: 80,
94+
...context.options,
95+
filepath,
96+
parser,
97+
},
98+
);
99+
100+
const expectFail = shouldThrowOnFormat(fixture, formatOptions);
101+
102+
let promise;
103+
104+
return {
105+
context,
106+
parser,
107+
filepath,
108+
originalText,
109+
code,
110+
formatOptions,
111+
expectFail,
112+
expectedOutput: fixture.output,
113+
isEmpty: code.trim() === "",
114+
runFormat: () =>
115+
promise === undefined ? (promise = format(code, formatOptions)) : promise,
116+
};
117+
}
118+
141119
export default runFormatTest;

tests/config/utilities.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import path from "node:path";
22

33
const normalizeDirectory = (directory) => path.normalize(directory + path.sep);
44

5-
const shouldThrowOnFormat = (filename, options) => {
5+
const isErrorTest = (dirname) =>
6+
normalizeDirectory(dirname).includes(`${path.sep}_errors_${path.sep}`);
7+
8+
const shouldThrowOnFormat = ({ filename }, options) => {
69
const { errors = {}, parser } = options;
710
if (errors === true) {
811
return true;
@@ -17,4 +20,4 @@ const shouldThrowOnFormat = (filename, options) => {
1720
return false;
1821
};
1922

20-
export { normalizeDirectory, shouldThrowOnFormat };
23+
export { normalizeDirectory, isErrorTest, shouldThrowOnFormat };

0 commit comments

Comments
 (0)