From b7f75722c106366e39a4d88c5fb6d841e515bf4c Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 12 Mar 2026 19:17:10 -0300 Subject: [PATCH 1/3] delegating test description completely to run test. --- tests/config/run-format-test.js | 69 +------------ tests/config/run-test.js | 176 ++++++++++++++++++++------------ 2 files changed, 114 insertions(+), 131 deletions(-) diff --git a/tests/config/run-format-test.js b/tests/config/run-format-test.js index 1804ab2e1..7871e0501 100644 --- a/tests/config/run-format-test.js +++ b/tests/config/run-format-test.js @@ -2,15 +2,12 @@ import path from "node:path"; import url from "node:url"; import { FORMAT_SCRIPT_FILENAME } from "./constants.js"; import { getFixtures } from "./get-fixtures.js"; +import { testFixture } from "./run-test.js"; import { stringifyOptionsForTitle } from "./utils/stringify-options-for-title.js"; import { isErrorTest as isErrorTestDirectory, normalizeDirectory, } from "./utilities.js"; -import { format } from "./run-prettier.js"; -import { replacePlaceholders } from "./replace-placeholders.js"; -import { runTest } from "./run-test.js"; -import { shouldThrowOnFormat } from "./utilities.js"; function runFormatTest(rawFixtures, explicitParsers, rawOptions) { const { importMeta, snippets = [] } = rawFixtures.importMeta @@ -50,70 +47,8 @@ function runFormatTest(rawFixtures, explicitParsers, rawOptions) { }; for (const fixture of getFixtures(context)) { - const { name, context, filepath } = fixture; - const { stringifiedOptions, parsers } = context; - - const title = `${name}${ - stringifiedOptions ? ` - ${stringifiedOptions}` : "" - }`; - - describe(title, () => { - const testCases = parsers.map((parser) => getTestCase(fixture, parser)); - - for (const testCase of testCases) { - const testTitle = - testCase.expectFail || - testCase.formatOptions.parser !== testCase.parser - ? `[${testCase.parser}] format` - : "format"; - - test(testTitle, async () => { - await runTest({ - parsers, - name, - filename: filepath, - code: testCase.code, - output: testCase.expectedOutput, - parser: testCase.parser, - mainParserFormatResult: await testCase.runFormat(), - mainParserFormatOptions: testCase.formatOptions, - }); - }); - } - }); + testFixture(fixture); } } -function getTestCase(fixture, parser) { - const { code: originalText, context, filepath } = fixture; - - const { text: code, options: formatOptions } = replacePlaceholders( - originalText, - { - printWidth: 80, - ...context.options, - filepath, - parser, - }, - ); - - const expectFail = shouldThrowOnFormat(fixture, formatOptions); - - let promise; - - return { - context, - parser, - filepath, - originalText, - code, - formatOptions, - expectFail, - expectedOutput: fixture.output, - isEmpty: code.trim() === "", - runFormat: () => - promise === undefined ? (promise = format(code, formatOptions)) : promise, - }; -} - export default runFormatTest; diff --git a/tests/config/run-test.js b/tests/config/run-test.js index 4186f1403..bf8464c1d 100644 --- a/tests/config/run-test.js +++ b/tests/config/run-test.js @@ -1,4 +1,5 @@ import { FULL_TEST } from "./constants.js"; +import { replacePlaceholders } from "./replace-placeholders.js"; import { format } from "./run-prettier.js"; import consistentEndOfLine from "./utils/consistent-end-of-line.js"; import createSnapshot from "./utils/create-snapshot.js"; @@ -12,74 +13,121 @@ import * as testAntlrFormat from "./test-antlr-format.js"; import * as testVariantCoverage from "./test-variant-coverage.js"; import { shouldThrowOnFormat } from "./utilities.js"; -async function runTest({ - parsers, - name, - filename, - code, - output, - parser, - mainParserFormatResult, - mainParserFormatOptions, -}) { - let formatOptions = mainParserFormatOptions; - let formatResult = mainParserFormatResult; - - // Verify parsers or error tests - if ( - mainParserFormatResult.error || - mainParserFormatOptions.parser !== parser - ) { - formatOptions = { ...mainParserFormatResult.options, parser }; - const runFormat = () => format(code, formatOptions); - - if (shouldThrowOnFormat(name, formatOptions)) { - await expect(runFormat()).rejects.toThrowErrorMatchingSnapshot(); - return; +async function testFixture(fixture) { + const { name, context, filepath } = fixture; + const { stringifiedOptions, parsers } = context; + + const title = `${name}${ + stringifiedOptions ? ` - ${stringifiedOptions}` : "" + }`; + + describe(title, () => { + const testCases = parsers.map((parser) => getTestCase(fixture, parser)); + + for (const testCase of testCases) { + const testTitle = + testCase.expectFail || testCase.formatOptions.parser !== testCase.parser + ? `[${testCase.parser}] format` + : "format"; + + test(testTitle, async () => { + let { code, expectedOutput, parser, formatOptions } = testCase; + let formatResult = await testCase.runFormat(); + + // Verify parsers or error tests + if (formatOptions.parser !== parser) { + const runFormat = () => format(code, formatOptions); + + if (shouldThrowOnFormat(name, formatOptions)) { + await expect(runFormat()).rejects.toThrowErrorMatchingSnapshot(); + return; + } + + // Verify parsers format result should be the same as main parser + output = formatResult.outputWithCursor; + formatResult = await runFormat(); + } + + // Make sure output has consistent EOL + expect(formatResult.eolVisualizedOutput).toEqual( + visualizeEndOfLine( + consistentEndOfLine(formatResult.outputWithCursor), + ), + ); + + // The result is assert to equals to `expectedOutput` + if (typeof expectedOutput === "string") { + expect(formatResult.eolVisualizedOutput).toEqual( + visualizeEndOfLine(expectedOutput), + ); + return; + } + + // All parsers have the same result, only snapshot the result from main parser + expect( + createSnapshot(formatResult, { parsers, formatOptions }), + ).toMatchSnapshot(); + + if (!FULL_TEST) { + return; + } + await Promise.all( + [ + testAntlrFormat.run, + testVariantCoverage.run, + testSecondFormat.run, + testAstCompare.run, + testBom.run, + testBytecodeCompare.run, + ] + .map((test) => test(code, formatResult, filepath, formatOptions)) + .join( + ["\r\n", "\r"].map((eol) => + testEndOfLine.run( + code, + formatResult, + filepath, + formatOptions, + eol, + ), + ), + ), + ); + }); } + }); +} - // Verify parsers format result should be the same as main parser - output = mainParserFormatResult.outputWithCursor; - formatResult = await runFormat(); - } +function getTestCase(fixture, parser) { + const { code: originalText, context, filepath } = fixture; - // Make sure output has consistent EOL - expect(formatResult.eolVisualizedOutput).toEqual( - visualizeEndOfLine(consistentEndOfLine(formatResult.outputWithCursor)), + const { text: code, options: formatOptions } = replacePlaceholders( + originalText, + { + printWidth: 80, + ...context.options, + filepath, + parser, + }, ); - // The result is assert to equals to `output` - if (typeof output === "string") { - expect(formatResult.eolVisualizedOutput).toEqual( - visualizeEndOfLine(output), - ); - return; - } - - // All parsers have the same result, only snapshot the result from main parser - expect( - createSnapshot(formatResult, { parsers, formatOptions }), - ).toMatchSnapshot(); - - if (!FULL_TEST) { - return; - } - await Promise.all( - [ - testAntlrFormat.run, - testVariantCoverage.run, - testSecondFormat.run, - testAstCompare.run, - testBom.run, - testBytecodeCompare.run, - ] - .map((run) => run(code, formatResult, filename, formatOptions)) - .join( - ["\r\n", "\r"].map((eol) => - testEndOfLine.run(code, formatResult, filename, formatOptions, eol), - ), - ), - ); + const expectFail = shouldThrowOnFormat(fixture, formatOptions); + + let promise; + + return { + context, + parser, + filepath, + originalText, + code, + formatOptions, + expectFail, + expectedOutput: fixture.output, + isEmpty: code.trim() === "", + runFormat: () => + promise === undefined ? (promise = format(code, formatOptions)) : promise, + }; } -export { runTest }; +export { testFixture }; From 7d174176272ba44e37247dc340c13b77cc1d344b Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 12 Mar 2026 22:25:20 -0300 Subject: [PATCH 2/3] moving test format into it's own file --- tests/config/run-test.js | 43 +++++++--------------------------- tests/config/test-format.js | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 35 deletions(-) create mode 100644 tests/config/test-format.js diff --git a/tests/config/run-test.js b/tests/config/run-test.js index bf8464c1d..14eeea02d 100644 --- a/tests/config/run-test.js +++ b/tests/config/run-test.js @@ -1,12 +1,10 @@ import { FULL_TEST } from "./constants.js"; import { replacePlaceholders } from "./replace-placeholders.js"; import { format } from "./run-prettier.js"; -import consistentEndOfLine from "./utils/consistent-end-of-line.js"; -import createSnapshot from "./utils/create-snapshot.js"; -import visualizeEndOfLine from "./utils/visualize-end-of-line.js"; import * as testAstCompare from "./test-ast-compare.js"; import * as testBom from "./test-bom.js"; import * as testEndOfLine from "./test-end-of-line.js"; +import * as testFormat from "./test-format.js"; import * as testSecondFormat from "./test-second-format.js"; import * as testBytecodeCompare from "./test-bytecode-compare.js"; import * as testAntlrFormat from "./test-antlr-format.js"; @@ -34,40 +32,15 @@ async function testFixture(fixture) { let { code, expectedOutput, parser, formatOptions } = testCase; let formatResult = await testCase.runFormat(); - // Verify parsers or error tests - if (formatOptions.parser !== parser) { - const runFormat = () => format(code, formatOptions); - - if (shouldThrowOnFormat(name, formatOptions)) { - await expect(runFormat()).rejects.toThrowErrorMatchingSnapshot(); - return; - } - - // Verify parsers format result should be the same as main parser - output = formatResult.outputWithCursor; - formatResult = await runFormat(); - } - - // Make sure output has consistent EOL - expect(formatResult.eolVisualizedOutput).toEqual( - visualizeEndOfLine( - consistentEndOfLine(formatResult.outputWithCursor), - ), + await testFormat.run( + code, + formatResult, + parser, + parsers, + expectedOutput, + formatOptions, ); - // The result is assert to equals to `expectedOutput` - if (typeof expectedOutput === "string") { - expect(formatResult.eolVisualizedOutput).toEqual( - visualizeEndOfLine(expectedOutput), - ); - return; - } - - // All parsers have the same result, only snapshot the result from main parser - expect( - createSnapshot(formatResult, { parsers, formatOptions }), - ).toMatchSnapshot(); - if (!FULL_TEST) { return; } diff --git a/tests/config/test-format.js b/tests/config/test-format.js new file mode 100644 index 000000000..0a07f1d41 --- /dev/null +++ b/tests/config/test-format.js @@ -0,0 +1,46 @@ +import consistentEndOfLine from "./utils/consistent-end-of-line.js"; +import createSnapshot from "./utils/create-snapshot.js"; +import visualizeEndOfLine from "./utils/visualize-end-of-line.js"; + +async function testFormat( + code, + formatResult, + parser, + parsers, + expectedOutput, + formatOptions, +) { + // Verify parsers or error tests + if (formatOptions.parser !== parser) { + const runFormat = () => format(code, formatOptions); + + if (shouldThrowOnFormat(name, formatOptions)) { + await expect(runFormat()).rejects.toThrowErrorMatchingSnapshot(); + return; + } + + // Verify parsers format result should be the same as main parser + output = formatResult.outputWithCursor; + formatResult = await runFormat(); + } + + // Make sure output has consistent EOL + expect(formatResult.eolVisualizedOutput).toEqual( + visualizeEndOfLine(consistentEndOfLine(formatResult.outputWithCursor)), + ); + + // The result is assert to equals to `expectedOutput` + if (typeof expectedOutput === "string") { + expect(formatResult.eolVisualizedOutput).toEqual( + visualizeEndOfLine(expectedOutput), + ); + return; + } + + // All parsers have the same result, only snapshot the result from main parser + expect( + createSnapshot(formatResult, { parsers, formatOptions }), + ).toMatchSnapshot(); +} + +export { testFormat as run }; From a2ed0f16592fe451853d790cd30a0f2bcea7be28 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 13 Mar 2026 00:54:28 -0300 Subject: [PATCH 3/3] passing the testCase to each test, standardising the functions signature --- tests/config/run-test.js | 26 ++++---------------------- tests/config/test-antlr-format.js | 11 +++++++---- tests/config/test-ast-compare.js | 9 ++++++--- tests/config/test-bom.js | 9 ++++++--- tests/config/test-bytecode-compare.js | 20 +++++++++----------- tests/config/test-end-of-line.js | 15 ++++++--------- tests/config/test-format.js | 17 ++++++++--------- tests/config/test-second-format.js | 9 ++++++--- tests/config/test-variant-coverage.js | 11 ++++------- 9 files changed, 56 insertions(+), 71 deletions(-) diff --git a/tests/config/run-test.js b/tests/config/run-test.js index 14eeea02d..163cfca92 100644 --- a/tests/config/run-test.js +++ b/tests/config/run-test.js @@ -12,7 +12,7 @@ import * as testVariantCoverage from "./test-variant-coverage.js"; import { shouldThrowOnFormat } from "./utilities.js"; async function testFixture(fixture) { - const { name, context, filepath } = fixture; + const { name, context } = fixture; const { stringifiedOptions, parsers } = context; const title = `${name}${ @@ -29,17 +29,7 @@ async function testFixture(fixture) { : "format"; test(testTitle, async () => { - let { code, expectedOutput, parser, formatOptions } = testCase; - let formatResult = await testCase.runFormat(); - - await testFormat.run( - code, - formatResult, - parser, - parsers, - expectedOutput, - formatOptions, - ); + await testFormat.run(testCase); if (!FULL_TEST) { return; @@ -53,17 +43,9 @@ async function testFixture(fixture) { testBom.run, testBytecodeCompare.run, ] - .map((test) => test(code, formatResult, filepath, formatOptions)) + .map((test) => test(testCase)) .join( - ["\r\n", "\r"].map((eol) => - testEndOfLine.run( - code, - formatResult, - filepath, - formatOptions, - eol, - ), - ), + ["\r\n", "\r"].map((eol) => testEndOfLine.run(testCase, eol)), ), ); }); diff --git a/tests/config/test-antlr-format.js b/tests/config/test-antlr-format.js index 2d76066d2..75227a464 100644 --- a/tests/config/test-antlr-format.js +++ b/tests/config/test-antlr-format.js @@ -3,16 +3,19 @@ import getPrettier from "./get-prettier.js"; import getCreateParser from "./get-create-parser.js"; import getPlugins from "./get-plugins.js"; -async function testAntlrFormat(source, formatResult, filename, formatOptions) { +async function testAntlrFormat(testCase) { + const { code, filepath, formatOptions } = testCase; + const formatResult = await testCase.runFormat(); + if ( formatOptions.parser === "slang" && - !failedTests.isAntlrMismatch(filename, formatOptions) + !failedTests.isAntlrMismatch(filepath, formatOptions) ) { // Compare with ANTLR's format const createParser = await getCreateParser(); - const { parser } = createParser(source, formatOptions); + const { parser } = createParser(code, formatOptions); const prettier = await getPrettier(); - const { formatted: antlrOutput } = await prettier.formatWithCursor(source, { + const { formatted: antlrOutput } = await prettier.formatWithCursor(code, { ...formatOptions, // Since Slang forces us to decide on a compiler version, we need to do the // same for ANTLR unless it was already given as an option. diff --git a/tests/config/test-ast-compare.js b/tests/config/test-ast-compare.js index c82d27b13..80d78f0a9 100644 --- a/tests/config/test-ast-compare.js +++ b/tests/config/test-ast-compare.js @@ -1,10 +1,13 @@ import * as failedTests from "./failed-format-tests.js"; import { parse } from "./run-prettier.js"; -async function testAstCompare(source, formatResult, filename, formatOptions) { - const isAstUnstableTest = failedTests.isAstUnstable(filename, formatOptions); +async function testAstCompare(testCase) { + const { code, filepath, formatOptions } = testCase; + const formatResult = await testCase.runFormat(); + + const isAstUnstableTest = failedTests.isAstUnstable(filepath, formatOptions); // Some parsers skip parsing empty files - if (formatResult.changed && source.trim()) { + if (formatResult.changed && code.trim()) { const [originalAst, formattedAst] = await Promise.all( [formatResult.input, formatResult.output].map((code) => parse(code, formatResult.options), diff --git a/tests/config/test-bom.js b/tests/config/test-bom.js index 7c8f1ec2a..585457c87 100644 --- a/tests/config/test-bom.js +++ b/tests/config/test-bom.js @@ -1,10 +1,13 @@ import { BOM } from "./constants.js"; import { format } from "./run-prettier.js"; -async function testBom(source, formatResult, _filename, formatOptions) { - if (source.charAt(0) !== BOM) { +async function testBom(testCase) { + const { code, formatOptions } = testCase; + const formatResult = await testCase.runFormat(); + + if (code.charAt(0) !== BOM) { const { eolVisualizedOutput: output } = await format( - BOM + source, + BOM + code, formatOptions, ); const expected = BOM + formatResult.eolVisualizedOutput; diff --git a/tests/config/test-bytecode-compare.js b/tests/config/test-bytecode-compare.js index cdf0b0c65..e41f82e49 100644 --- a/tests/config/test-bytecode-compare.js +++ b/tests/config/test-bytecode-compare.js @@ -2,15 +2,13 @@ import path from "node:path"; import createEsmUtils from "esm-utils"; import compileContract from "./utils/compile-contract.js"; -async function testBytecodeCompare( - _source, - formatResult, - filename, - formatOptions, -) { - if (shouldCompareBytecode(filename, formatOptions)) { - const output = compileContract(filename, formatResult.output); - const expected = compileContract(filename, formatResult.input); +async function testBytecodeCompare(testCase) { + const { filepath, formatOptions } = testCase; + const formatResult = await testCase.runFormat(); + + if (shouldCompareBytecode(filepath, formatOptions)) { + const output = compileContract(filepath, formatResult.output); + const expected = compileContract(filepath, formatResult.input); expect(output).toEqual(expected); } } @@ -41,8 +39,8 @@ const testsWithAstChanges = new Map( }), ); -const shouldCompareBytecode = (filename, options) => { - const testFunction = testsWithAstChanges.get(filename); +const shouldCompareBytecode = (filepath, options) => { + const testFunction = testsWithAstChanges.get(filepath); if (!testFunction) { return false; diff --git a/tests/config/test-end-of-line.js b/tests/config/test-end-of-line.js index ae3cb165a..6128ea078 100644 --- a/tests/config/test-end-of-line.js +++ b/tests/config/test-end-of-line.js @@ -1,16 +1,13 @@ import { format } from "./run-prettier.js"; import visualizeEndOfLine from "./utils/visualize-end-of-line.js"; -async function testEndOfLine( - source, - formatResult, - _filename, - formatOptions, - eol, -) { - if (!shouldSkipEolTest(source, formatResult.options)) { +async function testEndOfLine(testCase, eol) { + const { code, formatOptions } = testCase; + const formatResult = await testCase.runFormat(); + + if (!shouldSkipEolTest(code, formatResult.options)) { const { eolVisualizedOutput: output } = await format( - source.replace(/\n/gu, eol), + code.replace(/\n/gu, eol), formatOptions, ); // Only if `endOfLine: "auto"` the result will be different diff --git a/tests/config/test-format.js b/tests/config/test-format.js index 0a07f1d41..75eadef3e 100644 --- a/tests/config/test-format.js +++ b/tests/config/test-format.js @@ -2,14 +2,10 @@ import consistentEndOfLine from "./utils/consistent-end-of-line.js"; import createSnapshot from "./utils/create-snapshot.js"; import visualizeEndOfLine from "./utils/visualize-end-of-line.js"; -async function testFormat( - code, - formatResult, - parser, - parsers, - expectedOutput, - formatOptions, -) { +async function testFormat(testCase) { + const { code, parser, expectedOutput, formatOptions } = testCase; + const formatResult = await testCase.runFormat(); + // Verify parsers or error tests if (formatOptions.parser !== parser) { const runFormat = () => format(code, formatOptions); @@ -39,7 +35,10 @@ async function testFormat( // All parsers have the same result, only snapshot the result from main parser expect( - createSnapshot(formatResult, { parsers, formatOptions }), + createSnapshot(formatResult, { + parsers: testCase.context.parsers, + formatOptions, + }), ).toMatchSnapshot(); } diff --git a/tests/config/test-second-format.js b/tests/config/test-second-format.js index fd6e0df9b..ee4c9b9d3 100644 --- a/tests/config/test-second-format.js +++ b/tests/config/test-second-format.js @@ -1,12 +1,15 @@ import * as failedTests from "./failed-format-tests.js"; import { format } from "./run-prettier.js"; -async function testSecondFormat(source, formatResult, filename, formatOptions) { - const isUnstableTest = failedTests.isUnstable(filename, formatOptions); +async function testSecondFormat(testCase) { + const { code, filepath, formatOptions } = testCase; + const formatResult = await testCase.runFormat(); + + const isUnstableTest = failedTests.isUnstable(filepath, formatOptions); if ( (formatResult.changed || isUnstableTest) && // No range and cursor - formatResult.input === source + formatResult.input === code ) { const { eolVisualizedOutput: firstOutput, output } = formatResult; const { eolVisualizedOutput: secondOutput } = await format( diff --git a/tests/config/test-variant-coverage.js b/tests/config/test-variant-coverage.js index 477626421..28b8888b8 100644 --- a/tests/config/test-variant-coverage.js +++ b/tests/config/test-variant-coverage.js @@ -1,16 +1,13 @@ import getCreateParser from "./get-create-parser.js"; import getVariantCoverage from "./get-variant-coverage.js"; -async function testVariantCoverage( - source, - _formatResult, - _filename, - formatOptions, -) { +async function testVariantCoverage(testCase) { + const { code, formatOptions } = testCase; + if (formatOptions.parser === "slang") { const createParser = await getCreateParser(); const variantCoverage = await getVariantCoverage(); - const { parseOutput } = createParser(source, formatOptions); + const { parseOutput } = createParser(code, formatOptions); // Check coverage variantCoverage(parseOutput.tree.asNonterminalNode());