fix(node): fix standalone linter setup (#15681)
This commit is contained in:
parent
e744f0429f
commit
4bf652d2e7
@ -443,68 +443,81 @@ describe('Linter', () => {
|
|||||||
beforeEach(() => newProject());
|
beforeEach(() => newProject());
|
||||||
afterEach(() => cleanupProject());
|
afterEach(() => cleanupProject());
|
||||||
|
|
||||||
|
function verifySuccessfulStandaloneSetup(myapp: string) {
|
||||||
|
expect(runCLI(`lint ${myapp}`, { silenceError: true })).toContain(
|
||||||
|
'All files pass linting'
|
||||||
|
);
|
||||||
|
expect(runCLI(`lint e2e`, { silenceError: true })).toContain(
|
||||||
|
'All files pass linting'
|
||||||
|
);
|
||||||
|
expect(() => checkFilesExist(`.eslintrc.base.json`)).toThrow();
|
||||||
|
|
||||||
|
const rootEslint = readJson('.eslintrc.json');
|
||||||
|
const e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
|
|
||||||
|
// should directly refer to nx plugin
|
||||||
|
expect(rootEslint.plugins).toEqual(['@nrwl/nx']);
|
||||||
|
expect(e2eEslint.plugins).toEqual(['@nrwl/nx']);
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifySuccessfulMigratedSetup(myapp: string, mylib: string) {
|
||||||
|
expect(runCLI(`lint ${myapp}`, { silenceError: true })).toContain(
|
||||||
|
'All files pass linting'
|
||||||
|
);
|
||||||
|
expect(runCLI(`lint e2e`, { silenceError: true })).toContain(
|
||||||
|
'All files pass linting'
|
||||||
|
);
|
||||||
|
expect(runCLI(`lint ${mylib}`, { silenceError: true })).toContain(
|
||||||
|
'All files pass linting'
|
||||||
|
);
|
||||||
|
expect(() => checkFilesExist(`.eslintrc.base.json`)).not.toThrow();
|
||||||
|
|
||||||
|
const rootEslint = readJson('.eslintrc.base.json');
|
||||||
|
const appEslint = readJson('.eslintrc.json');
|
||||||
|
const e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
|
const libEslint = readJson(`libs/${mylib}/.eslintrc.json`);
|
||||||
|
|
||||||
|
// should directly refer to nx plugin
|
||||||
|
expect(rootEslint.plugins).toEqual(['@nrwl/nx']);
|
||||||
|
expect(appEslint.plugins).toBeUndefined();
|
||||||
|
expect(e2eEslint.plugins).toBeUndefined();
|
||||||
|
expect(libEslint.plugins).toBeUndefined();
|
||||||
|
|
||||||
|
// should extend base
|
||||||
|
expect(appEslint.extends.slice(-1)).toEqual(['./.eslintrc.base.json']);
|
||||||
|
expect(e2eEslint.extends.slice(-1)).toEqual(['../.eslintrc.base.json']);
|
||||||
|
expect(libEslint.extends.slice(-1)).toEqual([
|
||||||
|
'../../.eslintrc.base.json',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
it('(React standalone) should set root project config to app and e2e app and migrate when another lib is added', () => {
|
it('(React standalone) should set root project config to app and e2e app and migrate when another lib is added', () => {
|
||||||
const myapp = uniq('myapp');
|
const myapp = uniq('myapp');
|
||||||
const mylib = uniq('mylib');
|
const mylib = uniq('mylib');
|
||||||
|
|
||||||
runCLI(`generate @nrwl/react:app ${myapp} --rootProject=true`);
|
runCLI(`generate @nrwl/react:app ${myapp} --rootProject=true`);
|
||||||
|
verifySuccessfulStandaloneSetup(myapp);
|
||||||
|
|
||||||
let rootEslint = readJson('.eslintrc.json');
|
let appEslint = readJson('.eslintrc.json');
|
||||||
let e2eEslint = readJson('e2e/.eslintrc.json');
|
let e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
expect(() => checkFilesExist(`.eslintrc.base.json`)).toThrow();
|
|
||||||
|
|
||||||
// should directly refer to nx plugin
|
|
||||||
expect(rootEslint.plugins).toEqual(['@nrwl/nx']);
|
|
||||||
expect(e2eEslint.plugins).toEqual(['@nrwl/nx']);
|
|
||||||
// should only extend framework plugin
|
|
||||||
expect(rootEslint.extends).toEqual(['plugin:@nrwl/nx/react']);
|
|
||||||
expect(e2eEslint.extends).toEqual(['plugin:cypress/recommended']);
|
|
||||||
// should have plugin extends
|
// should have plugin extends
|
||||||
expect(rootEslint.overrides[0].extends).toEqual([
|
expect(appEslint.overrides[0].extends).toBeDefined();
|
||||||
'plugin:@nrwl/nx/typescript',
|
expect(appEslint.overrides[1].extends).toBeDefined();
|
||||||
]);
|
expect(e2eEslint.overrides[0].extends).toBeDefined();
|
||||||
expect(rootEslint.overrides[1].extends).toEqual([
|
expect(e2eEslint.overrides[1].extends).toBeDefined();
|
||||||
'plugin:@nrwl/nx/javascript',
|
|
||||||
]);
|
|
||||||
expect(e2eEslint.overrides[0].extends).toEqual([
|
|
||||||
'plugin:@nrwl/nx/typescript',
|
|
||||||
]);
|
|
||||||
expect(e2eEslint.overrides[1].extends).toEqual([
|
|
||||||
'plugin:@nrwl/nx/javascript',
|
|
||||||
]);
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/react:lib ${mylib} --unitTestRunner=jest`);
|
runCLI(`generate @nrwl/workspace:lib ${mylib} --unitTestRunner=jest`);
|
||||||
// should add new tslint
|
verifySuccessfulMigratedSetup(myapp, mylib);
|
||||||
expect(() => checkFilesExist(`.eslintrc.base.json`)).not.toThrow();
|
|
||||||
const appEslint = readJson(`.eslintrc.json`);
|
appEslint = readJson(`.eslintrc.json`);
|
||||||
rootEslint = readJson('.eslintrc.base.json');
|
|
||||||
e2eEslint = readJson('e2e/.eslintrc.json');
|
e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
const libEslint = readJson(`libs/${mylib}/.eslintrc.json`);
|
|
||||||
|
|
||||||
// should directly refer to nx plugin only in the root
|
|
||||||
expect(rootEslint.plugins).toEqual(['@nrwl/nx']);
|
|
||||||
expect(appEslint.plugins).toBeUndefined();
|
|
||||||
expect(e2eEslint.plugins).toBeUndefined();
|
|
||||||
// should extend framework plugin and root config
|
|
||||||
expect(appEslint.extends).toEqual([
|
|
||||||
'plugin:@nrwl/nx/react',
|
|
||||||
'./.eslintrc.base.json',
|
|
||||||
]);
|
|
||||||
expect(e2eEslint.extends).toEqual([
|
|
||||||
'plugin:cypress/recommended',
|
|
||||||
'../.eslintrc.base.json',
|
|
||||||
]);
|
|
||||||
expect(libEslint.extends).toEqual([
|
|
||||||
'plugin:@nrwl/nx/react',
|
|
||||||
'../../.eslintrc.base.json',
|
|
||||||
]);
|
|
||||||
// should have no plugin extends
|
// should have no plugin extends
|
||||||
expect(appEslint.overrides[0].extends).toBeUndefined();
|
expect(appEslint.overrides[0].extends).toBeUndefined();
|
||||||
expect(appEslint.overrides[1].extends).toBeUndefined();
|
expect(appEslint.overrides[1].extends).toBeUndefined();
|
||||||
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
||||||
expect(e2eEslint.overrides[1].extends).toBeUndefined();
|
expect(e2eEslint.overrides[1].extends).toBeUndefined();
|
||||||
expect(libEslint.overrides[1].extends).toBeUndefined();
|
|
||||||
expect(libEslint.overrides[1].extends).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('(Angular standalone) should set root project config to app and e2e app and migrate when another lib is added', () => {
|
it('(Angular standalone) should set root project config to app and e2e app and migrate when another lib is added', () => {
|
||||||
@ -514,57 +527,23 @@ describe('Linter', () => {
|
|||||||
runCLI(
|
runCLI(
|
||||||
`generate @nrwl/angular:app ${myapp} --rootProject=true --no-interactive`
|
`generate @nrwl/angular:app ${myapp} --rootProject=true --no-interactive`
|
||||||
);
|
);
|
||||||
|
verifySuccessfulStandaloneSetup(myapp);
|
||||||
|
|
||||||
let rootEslint = readJson('.eslintrc.json');
|
let appEslint = readJson('.eslintrc.json');
|
||||||
let e2eEslint = readJson('e2e/.eslintrc.json');
|
let e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
expect(() => checkFilesExist(`.eslintrc.base.json`)).toThrow();
|
|
||||||
|
|
||||||
// should directly refer to nx plugin
|
|
||||||
expect(rootEslint.plugins).toEqual(['@nrwl/nx']);
|
|
||||||
expect(e2eEslint.plugins).toEqual(['@nrwl/nx']);
|
|
||||||
// should only extend framework plugin
|
|
||||||
expect(e2eEslint.extends).toEqual(['plugin:cypress/recommended']);
|
|
||||||
// should have plugin extends
|
// should have plugin extends
|
||||||
expect(rootEslint.overrides[0].files).toEqual(['*.ts']);
|
expect(appEslint.overrides[0].extends).toBeDefined();
|
||||||
expect(rootEslint.overrides[0].extends).toEqual([
|
expect(appEslint.overrides[1].extends).toBeDefined();
|
||||||
'plugin:@nrwl/nx/typescript',
|
expect(e2eEslint.overrides[0].extends).toBeDefined();
|
||||||
'plugin:@nrwl/nx/angular',
|
expect(e2eEslint.overrides[1].extends).toBeDefined();
|
||||||
'plugin:@angular-eslint/template/process-inline-templates',
|
|
||||||
]);
|
|
||||||
expect(Object.keys(rootEslint.overrides[0].rules)).toEqual([
|
|
||||||
'@angular-eslint/directive-selector',
|
|
||||||
'@angular-eslint/component-selector',
|
|
||||||
]);
|
|
||||||
expect(rootEslint.overrides[1].files).toEqual(['*.html']);
|
|
||||||
expect(rootEslint.overrides[1].extends).toEqual([
|
|
||||||
'plugin:@nrwl/nx/angular-template',
|
|
||||||
]);
|
|
||||||
expect(e2eEslint.overrides[0].extends).toEqual([
|
|
||||||
'plugin:@nrwl/nx/typescript',
|
|
||||||
]);
|
|
||||||
expect(e2eEslint.overrides[1].extends).toEqual([
|
|
||||||
'plugin:@nrwl/nx/javascript',
|
|
||||||
]);
|
|
||||||
|
|
||||||
runCLI(`generate @nrwl/angular:lib ${mylib} --no-interactive`);
|
runCLI(`generate @nrwl/workspace:lib ${mylib} --no-interactive`);
|
||||||
// should add new tslint
|
verifySuccessfulMigratedSetup(myapp, mylib);
|
||||||
expect(() => checkFilesExist(`.eslintrc.base.json`)).not.toThrow();
|
|
||||||
const appEslint = readJson(`.eslintrc.json`);
|
appEslint = readJson(`.eslintrc.json`);
|
||||||
rootEslint = readJson('.eslintrc.base.json');
|
|
||||||
e2eEslint = readJson('e2e/.eslintrc.json');
|
e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
const libEslint = readJson(`libs/${mylib}/.eslintrc.json`);
|
|
||||||
|
|
||||||
// should directly refer to nx plugin only in the root
|
|
||||||
expect(rootEslint.plugins).toEqual(['@nrwl/nx']);
|
|
||||||
expect(appEslint.plugins).toBeUndefined();
|
|
||||||
expect(e2eEslint.plugins).toBeUndefined();
|
|
||||||
// should extend framework plugin and root config
|
|
||||||
expect(appEslint.extends).toEqual(['./.eslintrc.base.json']);
|
|
||||||
expect(e2eEslint.extends).toEqual([
|
|
||||||
'plugin:cypress/recommended',
|
|
||||||
'../.eslintrc.base.json',
|
|
||||||
]);
|
|
||||||
expect(libEslint.extends).toEqual(['../../.eslintrc.base.json']);
|
|
||||||
// should have no plugin extends
|
// should have no plugin extends
|
||||||
expect(appEslint.overrides[0].extends).toEqual([
|
expect(appEslint.overrides[0].extends).toEqual([
|
||||||
'plugin:@nrwl/nx/angular',
|
'plugin:@nrwl/nx/angular',
|
||||||
@ -572,10 +551,37 @@ describe('Linter', () => {
|
|||||||
]);
|
]);
|
||||||
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
||||||
expect(e2eEslint.overrides[1].extends).toBeUndefined();
|
expect(e2eEslint.overrides[1].extends).toBeUndefined();
|
||||||
expect(libEslint.overrides[0].extends).toEqual([
|
});
|
||||||
'plugin:@nrwl/nx/angular',
|
|
||||||
'plugin:@angular-eslint/template/process-inline-templates',
|
it('(Node standalone) should set root project config to app and e2e app and migrate when another lib is added', () => {
|
||||||
]);
|
const myapp = uniq('myapp');
|
||||||
|
const mylib = uniq('mylib');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nrwl/node:app ${myapp} --rootProject=true --no-interactive`
|
||||||
|
);
|
||||||
|
verifySuccessfulStandaloneSetup(myapp);
|
||||||
|
|
||||||
|
let appEslint = readJson('.eslintrc.json');
|
||||||
|
let e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
|
|
||||||
|
// should have plugin extends
|
||||||
|
expect(appEslint.overrides[0].extends).toBeDefined();
|
||||||
|
expect(appEslint.overrides[1].extends).toBeDefined();
|
||||||
|
expect(e2eEslint.overrides[0].extends).toBeDefined();
|
||||||
|
expect(e2eEslint.overrides[1].extends).toBeDefined();
|
||||||
|
|
||||||
|
runCLI(`generate @nrwl/workspace:lib ${mylib} --no-interactive`);
|
||||||
|
verifySuccessfulMigratedSetup(myapp, mylib);
|
||||||
|
|
||||||
|
appEslint = readJson(`.eslintrc.json`);
|
||||||
|
e2eEslint = readJson('e2e/.eslintrc.json');
|
||||||
|
|
||||||
|
// should have no plugin extends
|
||||||
|
expect(appEslint.overrides[0].extends).toBeUndefined();
|
||||||
|
expect(appEslint.overrides[1].extends).toBeUndefined();
|
||||||
|
expect(e2eEslint.overrides[0].extends).toBeUndefined();
|
||||||
|
expect(e2eEslint.overrides[1].extends).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -45,6 +45,7 @@ import { e2eProjectGenerator } from '../e2e-project/e2e-project';
|
|||||||
import { setupDockerGenerator } from '../setup-docker/setup-docker';
|
import { setupDockerGenerator } from '../setup-docker/setup-docker';
|
||||||
|
|
||||||
import { Schema } from './schema';
|
import { Schema } from './schema';
|
||||||
|
import { mapLintPattern } from '@nrwl/linter/src/generators/lint-project/lint-project';
|
||||||
|
|
||||||
export interface NormalizedSchema extends Schema {
|
export interface NormalizedSchema extends Schema {
|
||||||
appProjectRoot: string;
|
appProjectRoot: string;
|
||||||
@ -273,7 +274,11 @@ export async function addLintingToApplication(
|
|||||||
joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
joinPathFragments(options.appProjectRoot, 'tsconfig.app.json'),
|
||||||
],
|
],
|
||||||
eslintFilePatterns: [
|
eslintFilePatterns: [
|
||||||
`${options.appProjectRoot}/**/*.${options.js ? 'js' : 'ts'}`,
|
mapLintPattern(
|
||||||
|
options.appProjectRoot,
|
||||||
|
options.js ? 'js' : 'ts',
|
||||||
|
options.rootProject
|
||||||
|
),
|
||||||
],
|
],
|
||||||
unitTestRunner: options.unitTestRunner,
|
unitTestRunner: options.unitTestRunner,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
@ -382,11 +387,8 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
|
|||||||
|
|
||||||
updateTsConfigOptions(tree, options);
|
updateTsConfigOptions(tree, options);
|
||||||
|
|
||||||
if (options.linter !== Linter.None) {
|
if (options.linter === Linter.EsLint) {
|
||||||
const lintTask = await addLintingToApplication(tree, {
|
const lintTask = await addLintingToApplication(tree, options);
|
||||||
...options,
|
|
||||||
skipFormat: true,
|
|
||||||
});
|
|
||||||
tasks.push(lintTask);
|
tasks.push(lintTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,11 +14,17 @@ import {
|
|||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
|
updateJson,
|
||||||
} from '@nrwl/devkit';
|
} from '@nrwl/devkit';
|
||||||
import { Linter, lintProjectGenerator } from '@nrwl/linter';
|
import { Linter, lintProjectGenerator } from '@nrwl/linter';
|
||||||
|
|
||||||
import { Schema } from './schema';
|
import { Schema } from './schema';
|
||||||
import { axiosVersion } from '../../utils/versions';
|
import { axiosVersion } from '../../utils/versions';
|
||||||
|
import { join } from 'path';
|
||||||
|
import {
|
||||||
|
globalJavaScriptOverrides,
|
||||||
|
globalTypeScriptOverrides,
|
||||||
|
} from '@nrwl/linter/src/generators/init/global-eslint-config';
|
||||||
|
|
||||||
export async function e2eProjectGenerator(host: Tree, _options: Schema) {
|
export async function e2eProjectGenerator(host: Tree, _options: Schema) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
@ -90,7 +96,7 @@ export async function e2eProjectGenerator(host: Tree, _options: Schema) {
|
|||||||
);
|
);
|
||||||
tasks.push(installTask);
|
tasks.push(installTask);
|
||||||
|
|
||||||
if (options.linter === 'eslint') {
|
if (options.linter === Linter.EsLint) {
|
||||||
const linterTask = await lintProjectGenerator(host, {
|
const linterTask = await lintProjectGenerator(host, {
|
||||||
project: options.e2eProjectName,
|
project: options.e2eProjectName,
|
||||||
linter: Linter.EsLint,
|
linter: Linter.EsLint,
|
||||||
@ -104,6 +110,33 @@ export async function e2eProjectGenerator(host: Tree, _options: Schema) {
|
|||||||
rootProject: options.rootProject,
|
rootProject: options.rootProject,
|
||||||
});
|
});
|
||||||
tasks.push(linterTask);
|
tasks.push(linterTask);
|
||||||
|
|
||||||
|
updateJson(host, join(options.e2eProjectRoot, '.eslintrc.json'), (json) => {
|
||||||
|
if (options.rootProject) {
|
||||||
|
json.plugins = ['@nrwl/nx'];
|
||||||
|
json.extends = [];
|
||||||
|
}
|
||||||
|
json.overrides = [
|
||||||
|
...(options.rootProject
|
||||||
|
? [globalTypeScriptOverrides, globalJavaScriptOverrides]
|
||||||
|
: []),
|
||||||
|
/**
|
||||||
|
* In order to ensure maximum efficiency when typescript-eslint generates TypeScript Programs
|
||||||
|
* behind the scenes during lint runs, we need to make sure the project is configured to use its
|
||||||
|
* own specific tsconfigs, and not fall back to the ones in the root of the workspace.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
||||||
|
/**
|
||||||
|
* Having an empty rules object present makes it more obvious to the user where they would
|
||||||
|
* extend things from if they needed to
|
||||||
|
*/
|
||||||
|
rules: {},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return json;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.formatFile) {
|
if (options.formatFile) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user