Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/slang-utils/create-hug-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ export function createHugFunction(
{
kind: NonterminalKind.TupleExpression,
loc: { ...loc },
comments: [],
comments: undefined,
items: Object.assign(
Object.create(TupleValues.prototype) as TupleValues,
{
kind: NonterminalKind.TupleValues,
loc: { ...loc },
comments: [],
comments: undefined,
items: [
Object.assign(
Object.create(TupleValue.prototype) as TupleValue,
{
kind: NonterminalKind.TupleValue,
loc: { ...loc },
comments: [],
comments: undefined,
expression: node
}
)
Expand Down
2 changes: 1 addition & 1 deletion tests/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const FORMAT_TEST_DIRECTORY = normalizeDirectory(
path.join(__dirname, "../format/"),
);

export const { FULL_TEST } = process.env;
export const { FULL_TEST, TEST_STANDALONE } = process.env;
export const BOM = "\uFEFF";

export const CURSOR_PLACEHOLDER = "<|>";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { wrap as raw } from "jest-snapshot-serializer-raw";
import { CURSOR_PLACEHOLDER } from "../constants.js";
import { CURSOR_PLACEHOLDER } from "./constants.js";
import visualizeEndOfLine from "./visualize-end-of-line.js";
import visualizeRange from "./visualize-range.js";

Expand Down
2 changes: 1 addition & 1 deletion tests/config/format-test-setup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import runFormatTest from "./run-format-test.js";
import { runFormatTest } from "./run-format-test.js";

globalThis.runFormatTest = runFormatTest;
4 changes: 3 additions & 1 deletion tests/config/get-create-parser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TEST_STANDALONE } from "./constants.js";

function getCreateParserInternal() {
const entry = process.env.TEST_STANDALONE
const entry = TEST_STANDALONE
? "../../dist/create-parser.js"
: "../../src/slang-utils/create-parser.js";

Expand Down
16 changes: 15 additions & 1 deletion tests/config/get-fixtures.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import fs from "node:fs";
import path from "node:path";
import { FORMAT_SCRIPT_FILENAME } from "./constants.js";
import visualizeEndOfLine from "./utils/visualize-end-of-line.js";
import visualizeEndOfLine from "./visualize-end-of-line.js";

/**
@import {Context} from "./run-format-test.js"
@typedef {Exclude<ReturnType<ReturnType<getFixtures>["next"]>["value"], void>} Fixture
*/

/**
@param {Context} context
*/
function* getFixtures(context) {
yield* getFiles(context);
yield* getSnippets(context);
}

/**
@param {Context} context
*/
function* getFiles(context) {
const { dirname } = context;
for (const file of fs.readdirSync(dirname, { withFileTypes: true })) {
Expand Down Expand Up @@ -36,6 +47,9 @@ function* getFiles(context) {
}
}

/**
@param {Context} context
*/
function* getSnippets(context) {
for (const [index, snippet] of context.snippets.entries()) {
const testCase =
Expand Down
5 changes: 3 additions & 2 deletions tests/config/get-plugins.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import path from "node:path";
import createEsmUtils from "esm-utils";
import getPrettier from "./get-prettier.js";
import { TEST_STANDALONE } from "./constants.js";

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

// populate the root object for the standalone in node
if (process.env.TEST_STANDALONE) {
if (TEST_STANDALONE) {
const root =
typeof globalThis !== "undefined"
? globalThis
Expand All @@ -19,7 +20,7 @@ if (process.env.TEST_STANDALONE) {

function getPluginsInternal() {
return Promise.all(
process.env.TEST_STANDALONE
TEST_STANDALONE
? [
import("prettier/plugins/babel"),
import("prettier/plugins/estree"),
Expand Down
6 changes: 3 additions & 3 deletions tests/config/get-prettier.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TEST_STANDALONE } from "./constants.js";

function getPrettierInternal() {
const entry = process.env.TEST_STANDALONE
? "prettier/standalone"
: "prettier";
const entry = TEST_STANDALONE ? "prettier/standalone" : "prettier";

return import(entry).then((module) => module.default);
}
Expand Down
4 changes: 3 additions & 1 deletion tests/config/get-variant-coverage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TEST_STANDALONE } from "./constants.js";

function getVariantCoverageInternal() {
const entry = process.env.TEST_STANDALONE
const entry = TEST_STANDALONE
? "../../dist/variant-coverage.js"
: "../../variant-coverage/index.js";

Expand Down
4 changes: 4 additions & 0 deletions tests/config/replace-placeholders.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const indexProperties = [
},
];

/**
@param {string} originalText
@param {any} originalOptions
*/
function replacePlaceholders(originalText, originalOptions) {
const indexes = indexProperties
.map(({ property, placeholder }) => {
Expand Down
30 changes: 28 additions & 2 deletions tests/config/run-format-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,36 @@ 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 { stringifyOptionsForTitle } from "./stringify-options-for-title.js";
import {
isErrorTest as isErrorTestDirectory,
normalizeDirectory,
} from "./utilities.js";

/**
@typedef {
| string
| { code: string; name?: string; filename?: string; output?: string }
} Snippet
@typedef {{
dirname: string,
stringifiedOptions: string,
parsers: string[],
options: any,
explicitParsers: string[],
rawOptions: any,
snippets: Snippet[],
}} Context
*/

/**
@param {
| ImportMeta
| { importMeta: ImportMeta, snippets?: Snippet[] }
} rawFixtures
@param {string[]} explicitParsers
@param {any} rawOptions
*/
function runFormatTest(rawFixtures, explicitParsers, rawOptions) {
const { importMeta, snippets = [] } = rawFixtures.importMeta
? rawFixtures
Expand Down Expand Up @@ -36,6 +60,8 @@ function runFormatTest(rawFixtures, explicitParsers, rawOptions) {
options = { errors: true, ...options };
}

// Make sure tests are in correct location

const context = {
dirname,
stringifiedOptions: stringifyOptionsForTitle(rawOptions),
Expand All @@ -51,4 +77,4 @@ function runFormatTest(rawFixtures, explicitParsers, rawOptions) {
}
}

export default runFormatTest;
export { runFormatTest };
10 changes: 2 additions & 8 deletions tests/config/run-prettier.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import getPrettier from "./get-prettier.js";
import getPlugins from "./get-plugins.js";
import { CURSOR_PLACEHOLDER } from "./constants.js";
import visualizeEndOfLine from "./utils/visualize-end-of-line.js";
import { replacePlaceholders } from "./replace-placeholders.js";
import visualizeEndOfLine from "./visualize-end-of-line.js";

async function parse(input, options) {
const prettier = await getPrettier();

const { ast } = await prettier.__debug.parse(
input,
await loadPlugins(options),
Expand All @@ -15,11 +13,7 @@ async function parse(input, options) {
return ast;
}

async function format(originalText, originalOptions) {
const { text: input, options } = replacePlaceholders(
originalText,
originalOptions,
);
async function format(input, options) {
const inputWithCursor = insertCursor(input, options.cursorOffset);
const prettier = await getPrettier();

Expand Down
136 changes: 109 additions & 27 deletions tests/config/run-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ import * as testAntlrFormat from "./test-antlr-format.js";
import * as testVariantCoverage from "./test-variant-coverage.js";
import { shouldThrowOnFormat } from "./utilities.js";

async function testFixture(fixture) {
/**
@import {Fixture} from "./get-fixtures.js"
@typedef {ReturnType<getTestCase>} TestCase
*/

/**
@param {Fixture} fixture
*/
function testFixture(fixture) {
const { name, context } = fixture;
const { stringifiedOptions, parsers } = context;

Expand All @@ -22,52 +30,126 @@ async function testFixture(fixture) {
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";
const testCaseForSnapshot = testCases.find(
(testCase) =>
!testCase.expectFail && typeof testCase.expectedOutput !== "string",
);

const hasMultipleParsers = testCases.length > 1;

test(testTitle, async () => {
await testFormat.run(testCase);
for (const functionality of [
{
name(testCase) {
let name = "format";
// Avoid parser display in snapshot
if (testCaseForSnapshot !== testCase && hasMultipleParsers) {
name += `[${testCase.parser}]`;
}
return name;
},
test: {
run: (testCase, name) =>
testFormat.run(testCase, name, testCaseForSnapshot),
},
},
{
name: "ast compare",
test: { run: testAstCompare.run, skip: testAstCompare.skip },
skip: () => !FULL_TEST,
},
// The following cases only need run on main parser
{
name: "second format",
test: { run: testSecondFormat.run, skip: testSecondFormat.skip },
skip: (testCase) => !FULL_TEST || testCase !== testCaseForSnapshot,
},
{
name: "end of line (CRLF)",
test: {
run: (testCase, name) => testEndOfLine.run(testCase, name, "\r\n"),
skip: testEndOfLine.skip,
},
skip: (testCase) => !FULL_TEST || testCase !== testCaseForSnapshot,
},
{
name: "end of line (CR)",
test: {
run: (testCase, name) => testEndOfLine.run(testCase, name, "\r"),
skip: testEndOfLine.skip,
},
skip: (testCase) => !FULL_TEST || testCase !== testCaseForSnapshot,
},
{
name: "BOM",
test: { run: testBom.run, skip: testBom.skip },
skip: (testCase) => !FULL_TEST || testCase !== testCaseForSnapshot,
},
// The following cases only need run if the parser is Slang
{
name: "ANTLR format",
test: { run: testAntlrFormat.run, skip: testAntlrFormat.skip },
skip: (testCase) =>
!FULL_TEST ||
testCase !== testCaseForSnapshot ||
testCase.parser !== "slang",
},
{
name: "bytecode comparison",
test: { run: testBytecodeCompare.run, skip: testBytecodeCompare.skip },
skip: (testCase) =>
!FULL_TEST ||
testCase !== testCaseForSnapshot ||
testCase.parser !== "slang",
},
{
name: "variant coverage",
test: { run: testVariantCoverage.run, skip: testVariantCoverage.skip },
skip: (testCase) =>
!FULL_TEST ||
testCase !== testCaseForSnapshot ||
testCase.parser !== "slang",
},
]) {
for (const testCase of testCases) {
if (
functionality.skip?.(testCase) ||
functionality.test.skip?.(testCase)
) {
continue;
}

if (!FULL_TEST) {
return;
let { name } = functionality;
if (typeof name === "function") {
name = name(testCase);
} else if (hasMultipleParsers) {
name += ` [${testCase.parser}]`;
}
await Promise.all(
[
testAntlrFormat.run,
testVariantCoverage.run,
testSecondFormat.run,
testAstCompare.run,
testBom.run,
testBytecodeCompare.run,
]
.map((test) => test(testCase))
.join(
["\r\n", "\r"].map((eol) => testEndOfLine.run(testCase, eol)),
),
);
});

functionality.test.run(testCase, name);
}
}
});
}

/**
@param {Fixture} fixture
@param {string} parser
*/
function getTestCase(fixture, parser) {
const { code: originalText, context, filepath } = fixture;

const { text: code, options: formatOptions } = replacePlaceholders(
originalText,
{
printWidth: 80,
...context.options,
filepath,
...context.options,
parser,
},
);

const expectFail = shouldThrowOnFormat(fixture, formatOptions);

/** @type {ReturnType<format> | undefined} */
let promise;

return {
Expand Down
Loading