Leosvel Pérez Espinosa 49c5a73cd0
feat(js): generate experimental simplified library with ts solution setup (#27910)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #

---------

Co-authored-by: Jack Hsu <jack.hsu@gmail.com>
2024-09-27 14:14:19 -04:00

1069 lines
32 KiB
TypeScript

import ts = require('typescript');
import {
addBlockToFlatConfigExport,
addFlatCompatToFlatConfig,
addImportToFlatConfig,
generateAst,
generateFlatOverride,
generatePluginExtendsElementWithCompatFixup,
removeCompatExtends,
removeImportFromFlatConfig,
removeOverridesFromLintConfig,
removePlugin,
removePredefinedConfigs,
replaceOverride,
} from './ast-utils';
import { stripIndents } from '@nx/devkit';
describe('ast-utils', () => {
const printer = ts.createPrinter();
function printTsNode(node: ts.Node) {
return printer.printNode(
ts.EmitHint.Unspecified,
node,
ts.createSourceFile('test.ts', '', ts.ScriptTarget.Latest)
);
}
describe('generateFlatOverride', () => {
it('should create appropriate ASTs for a flat config entries based on the provided legacy eslintrc JSON override data', () => {
// It's easier to review the stringified result of the AST than the AST itself
const getOutput = (input: any) => {
const ast = generateFlatOverride(input);
return printTsNode(ast);
};
expect(getOutput({})).toMatchInlineSnapshot(`"{}"`);
// It should apply rules directly
expect(
getOutput({
rules: {
a: 'error',
b: 'off',
c: [
'error',
{
some: {
rich: ['config', 'options'],
},
},
],
},
})
).toMatchInlineSnapshot(`
"{
rules: {
a: "error",
b: "off",
c: [
"error",
{ some: { rich: [
"config",
"options"
] } }
]
}
}"
`);
// It should normalize and apply files as an array
expect(
getOutput({
files: '*.ts', // old single * syntax should be replaced by **/*
})
).toMatchInlineSnapshot(`"{ files: ["**/*.ts"] }"`);
expect(
getOutput({
// It should not only nest the parser in languageOptions, but also wrap it in a require call because parsers are passed by reference in flat config
parser: 'jsonc-eslint-parser',
})
).toMatchInlineSnapshot(`
"{
languageOptions: { parser: require("jsonc-eslint-parser") }
}"
`);
expect(
getOutput({
// It should nest parserOptions in languageOptions
parserOptions: {
foo: 'bar',
},
})
).toMatchInlineSnapshot(`
"{
languageOptions: { parserOptions: { foo: "bar" } }
}"
`);
// It should add the compat tooling for extends, and spread the rules object to allow for easier editing by users
expect(getOutput({ extends: ['plugin:@nx/typescript'] }))
.toMatchInlineSnapshot(`
"...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
...config,
rules: {
...config.rules
}
}))"
`);
// It should add the compat tooling for plugins, and spread the rules object to allow for easier editing by users
expect(getOutput({ plugins: ['@nx/eslint-plugin'] }))
.toMatchInlineSnapshot(`
"...compat.config({ plugins: ["@nx/eslint-plugin"] }).map(config => ({
...config,
rules: {
...config.rules
}
}))"
`);
// It should add the compat tooling for env, and spread the rules object to allow for easier editing by users
expect(getOutput({ env: { jest: true } })).toMatchInlineSnapshot(`
"...compat.config({ env: { jest: true } }).map(config => ({
...config,
rules: {
...config.rules
}
}))"
`);
// Files for the compat tooling should be added appropriately
expect(getOutput({ env: { jest: true }, files: ['*.ts', '*.tsx'] }))
.toMatchInlineSnapshot(`
"...compat.config({ env: { jest: true } }).map(config => ({
...config,
files: [
"**/*.ts",
"**/*.tsx"
],
rules: {
...config.rules
}
}))"
`);
});
});
describe('addBlockToFlatConfigExport', () => {
it('should inject block to the end of the file', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addBlockToFlatConfigExport(
content,
generateAst({
files: ['**/*.svg'],
rules: {
'@nx/do-something-with-svg': 'error',
},
})
);
expect(result).toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
{
files: ["**/*.svg"],
rules: { "@nx/do-something-with-svg": "error" }
},
];"
`);
});
it('should inject spread to the beginning of the file', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addBlockToFlatConfigExport(
content,
ts.factory.createSpreadElement(ts.factory.createIdentifier('config')),
{ insertAtTheEnd: false }
);
expect(result).toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.js");
module.exports = [
...config,
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];"
`);
});
});
describe('addImportToFlatConfig', () => {
it('should inject import if not found', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addImportToFlatConfig(
content,
'varName',
'@myorg/awesome-config'
);
expect(result).toMatchInlineSnapshot(`
"const varName = require("@myorg/awesome-config");
const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];"
`);
});
it('should update import if already found', () => {
const content = `const { varName } = require("@myorg/awesome-config");
const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addImportToFlatConfig(
content,
['otherName', 'someName'],
'@myorg/awesome-config'
);
expect(result).toMatchInlineSnapshot(`
"const { varName, otherName, someName } = require("@myorg/awesome-config");
const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];"
`);
});
it('should not inject import if already exists', () => {
const content = `const { varName, otherName } = require("@myorg/awesome-config");
const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addImportToFlatConfig(
content,
['otherName'],
'@myorg/awesome-config'
);
expect(result).toEqual(content);
});
it('should not update import if already exists', () => {
const content = `const varName = require("@myorg/awesome-config");
const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addImportToFlatConfig(
content,
'varName',
'@myorg/awesome-config'
);
expect(result).toEqual(content);
});
});
describe('removeImportFromFlatConfig', () => {
it('should remove existing import from config if the var name matches', () => {
const content = stripIndents`
const nx = require("@nx/eslint-plugin");
const thisShouldRemain = require("@nx/eslint-plugin");
const playwright = require('eslint-plugin-playwright');
module.exports = [
playwright.configs['flat/recommended'],
];
`;
const result = removeImportFromFlatConfig(
content,
'nx',
'@nx/eslint-plugin'
);
expect(result).toMatchInlineSnapshot(`
"
const thisShouldRemain = require("@nx/eslint-plugin");
const playwright = require('eslint-plugin-playwright');
module.exports = [
playwright.configs['flat/recommended'],
];"
`);
});
});
describe('addCompatToFlatConfig', () => {
it('should add compat to config', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addFlatCompatToFlatConfig(content);
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const js = require("@eslint/js");
const baseConfig = require("../../eslint.config.js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];"
`);
});
it('should add only partially compat to config if parts exist', () => {
const content = `const baseConfig = require("../../eslint.config.js");
const js = require("@eslint/js");
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addFlatCompatToFlatConfig(content);
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const baseConfig = require("../../eslint.config.js");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];"
`);
});
it('should not add compat to config if exist', () => {
const content = `const FlatCompat = require("@eslint/eslintrc");
const baseConfig = require("../../eslint.config.js");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = addFlatCompatToFlatConfig(content);
expect(result).toEqual(content);
});
});
describe('removeOverridesFromLintConfig', () => {
it('should remove all rules from config', () => {
const content = `const FlatCompat = require("@eslint/eslintrc");
const baseConfig = require("../../eslint.config.js");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
...baseConfig,
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
...config,
files: [
"**/*.ts",
"**/*.tsx"
],
rules: {}
})),
...compat.config({ env: { jest: true } }).map(config => ({
...config,
files: [
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.spec.js",
"**/*.spec.jsx"
],
rules: {}
})),
{ ignores: ["my-lib/.cache/**/*"] },
];`;
const result = removeOverridesFromLintConfig(content);
expect(result).toMatchInlineSnapshot(`
"const FlatCompat = require("@eslint/eslintrc");
const baseConfig = require("../../eslint.config.js");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
...baseConfig,
{ ignores: ["my-lib/.cache/**/*"] },
];"
`);
});
it('should remove all rules from starting with first', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {}
},
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
...config,
files: [
"**/*.ts",
"**/*.tsx"
],
rules: {}
})),
...compat.config({ env: { jest: true } }).map(config => ({
...config,
files: [
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.spec.js",
"**/*.spec.jsx"
],
rules: {}
}))
];`;
const result = removeOverridesFromLintConfig(content);
expect(result).toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.js");
module.exports = [
];"
`);
});
});
describe('replaceOverride', () => {
it('should find and replace rules in override', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {
'my-ts-rule': 'error'
}
},
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.js"
],
rules: {}
},
{
files: [
"my-lib/**/*.js",
"my-lib/**/*.jsx"
],
rules: {
'my-js-rule': 'error'
}
},
];`;
const result = replaceOverride(
content,
'my-lib',
(o) => o.files.includes('my-lib/**/*.ts'),
(o) => ({
...o,
rules: {
'my-rule': 'error',
},
})
);
expect(result).toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.js");
module.exports = [
{
"files": [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
"rules": {
"my-rule": "error"
}
},
{
"files": [
"my-lib/**/*.ts",
"my-lib/**/*.js"
],
"rules": {
"my-rule": "error"
}
},
{
files: [
"my-lib/**/*.js",
"my-lib/**/*.jsx"
],
rules: {
'my-js-rule': 'error'
}
},
];"
`);
});
it('should append rules in override', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
{
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {
'my-ts-rule': 'error'
}
},
{
files: [
"my-lib/**/*.js",
"my-lib/**/*.jsx"
],
rules: {
'my-js-rule': 'error'
}
},
];`;
const result = replaceOverride(
content,
'my-lib',
(o) => o.files.includes('my-lib/**/*.ts'),
(o) => ({
...o,
rules: {
...o.rules,
'my-new-rule': 'error',
},
})
);
expect(result).toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.js");
module.exports = [
{
"files": [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
"rules": {
"my-ts-rule": "error",
"my-new-rule": "error"
}
},
{
files: [
"my-lib/**/*.js",
"my-lib/**/*.jsx"
],
rules: {
'my-js-rule': 'error'
}
},
];"
`);
});
it('should work for compat overrides', () => {
const content = `const baseConfig = require("../../eslint.config.js");
module.exports = [
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
...config,
files: [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
rules: {
'my-ts-rule': 'error'
}
}),
];`;
const result = replaceOverride(
content,
'my-lib',
(o) => o.files.includes('my-lib/**/*.ts'),
(o) => ({
...o,
rules: {
...o.rules,
'my-new-rule': 'error',
},
})
);
expect(result).toMatchInlineSnapshot(`
"const baseConfig = require("../../eslint.config.js");
module.exports = [
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
...config,
"files": [
"my-lib/**/*.ts",
"my-lib/**/*.tsx"
],
"rules": {
"my-ts-rule": "error",
"my-new-rule": "error"
}
}),
];"
`);
});
});
describe('removePlugin', () => {
it('should remove plugins from config', () => {
const content = `const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: { "@nx": nxEslintPlugin } },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];`;
const result = removePlugin(content, '@nx', '@nx/eslint-plugin');
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];"
`);
});
it('should remove single plugin from config', () => {
const content = `const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const otherPlugin = require("other/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: { "@nx": nxEslintPlugin, "@other": otherPlugin } },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];`;
const result = removePlugin(content, '@nx', '@nx/eslint-plugin');
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const otherPlugin = require("other/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: { "@other": otherPlugin } },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];"
`);
});
it('should leave other properties in config', () => {
const content = `const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: { "@nx": nxEslintPlugin }, rules: {} },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];`;
const result = removePlugin(content, '@nx', '@nx/eslint-plugin');
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ rules: {} },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];"
`);
});
it('should remove single plugin from config array', () => {
const content = `const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: ["@nx", "something-else"] },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];`;
const result = removePlugin(content, '@nx', '@nx/eslint-plugin');
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins:["something-else"] },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];"
`);
});
it('should leave other fields in the object', () => {
const content = `const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: ["@nx"], rules: { } },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];`;
const result = removePlugin(content, '@nx', '@nx/eslint-plugin');
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ rules: { } },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];"
`);
});
it('should remove entire plugin when array with single element', () => {
const content = `const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: ["@nx"] },
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];`;
const result = removePlugin(content, '@nx', '@nx/eslint-plugin');
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ ignores: ["src/ignore/to/keep.ts"] },
{ ignores: ["something/else"] }
];"
`);
});
});
describe('removeCompatExtends', () => {
it('should remove compat extends from config', () => {
const content = `const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: { "@nx": nxEslintPlugin } },
...compat.config({ extends: ["plugin:@nx/typescript"] }).map(config => ({
...config,
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
rules: {}
})),
{ ignores: ["src/ignore/to/keep.ts"] },
...compat.config({ extends: ["plugin:@nrwl/javascript"] }).map(config => ({
files: ['*.js', '*.jsx'],
...config,
rules: {}
}))
];`;
const result = removeCompatExtends(content, [
'plugin:@nx/typescript',
'plugin:@nx/javascript',
'plugin:@nrwl/typescript',
'plugin:@nrwl/javascript',
]);
expect(result).toMatchInlineSnapshot(`
"const { FlatCompat } = require("@eslint/eslintrc");
const nxEslintPlugin = require("@nx/eslint-plugin");
const js = require("@eslint/js");
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});
module.exports = [
{ plugins: { "@nx": nxEslintPlugin } },
{
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
rules: {}
},
{ ignores: ["src/ignore/to/keep.ts"] },
{
files: ['*.js', '*.jsx'],
rules: {}
}
];"
`);
});
});
describe('removePredefinedConfigs', () => {
it('should remove config objects and import', () => {
const content = stripIndents`
const nx = require("@nx/eslint-plugin");
const playwright = require('eslint-plugin-playwright');
module.exports = [
...nx.config['flat/base'],
...nx.config['flat/typescript'],
...nx.config['flat/javascript'],
playwright.configs['flat/recommended'],
];
`;
const result = removePredefinedConfigs(
content,
'@nx/eslint-plugin',
'nx',
['flat/base', 'flat/typescript', 'flat/javascript']
);
expect(result).toMatchInlineSnapshot(`
"
const playwright = require('eslint-plugin-playwright');
module.exports = [
playwright.configs['flat/recommended'],
];"
`);
});
it('should keep configs that are not in the list', () => {
const content = stripIndents`
const nx = require("@nx/eslint-plugin");
const playwright = require('eslint-plugin-playwright');
module.exports = [
...nx.config['flat/base'],
...nx.config['flat/typescript'],
...nx.config['flat/javascript'],
...nx.config['flat/react'],
playwright.configs['flat/recommended'],
];
`;
const result = removePredefinedConfigs(
content,
'@nx/eslint-plugin',
'nx',
['flat/base', 'flat/typescript', 'flat/javascript']
);
expect(result).toMatchInlineSnapshot(`
"const nx = require("@nx/eslint-plugin");
const playwright = require('eslint-plugin-playwright');
module.exports = [
...nx.config['flat/react'],
playwright.configs['flat/recommended'],
];"
`);
});
});
describe('generatePluginExtendsElementWithCompatFixup', () => {
it('should return spread element with fixupConfigRules call wrapping the extended plugin', () => {
const result = generatePluginExtendsElementWithCompatFixup('my-plugin');
expect(printTsNode(result)).toMatchInlineSnapshot(
`"...fixupConfigRules(compat.extends("my-plugin"))"`
);
});
});
});