fix(storybook): linting react storybook files with eslint (#5146)
ISSUES CLOSED: #3867
This commit is contained in:
parent
ed94c4e1ec
commit
ec2ebca40a
@ -27,6 +27,20 @@ describe('Storybook schematics', () => {
|
|||||||
).toContain(`<title>Storybook</title>`);
|
).toContain(`<title>Storybook</title>`);
|
||||||
}, 1000000);
|
}, 1000000);
|
||||||
|
|
||||||
|
it('should lint a React based storybook without errors', () => {
|
||||||
|
newProject();
|
||||||
|
|
||||||
|
const reactStorybookLib = uniq('test-ui-lib-react');
|
||||||
|
runCLI(`generate @nrwl/react:lib ${reactStorybookLib} --no-interactive`);
|
||||||
|
runCLI(
|
||||||
|
`generate @nrwl/react:storybook-configuration ${reactStorybookLib} --generateStories --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
// build React lib
|
||||||
|
const output = runCLI(`run ${reactStorybookLib}:lint`);
|
||||||
|
expect(output).toContain('All files pass linting.');
|
||||||
|
}, 1000000);
|
||||||
|
|
||||||
it('should build a React based storybook that references another lib', () => {
|
it('should build a React based storybook that references another lib', () => {
|
||||||
const proj = newProject();
|
const proj = newProject();
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,11 @@
|
|||||||
"version": "11.0.12",
|
"version": "11.0.12",
|
||||||
"description": "Update storybook if installed and above 6",
|
"description": "Update storybook if installed and above 6",
|
||||||
"factory": "./src/migrations/update-11-0-12/update-storybook"
|
"factory": "./src/migrations/update-11-0-12/update-storybook"
|
||||||
|
},
|
||||||
|
"update-11-5-3": {
|
||||||
|
"version": "11.5.3-beta.1",
|
||||||
|
"description": "Update react storybook lint config",
|
||||||
|
"factory": "./src/migrations/update-11-5-3/update-lint-ignores"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packageJsonUpdates": {
|
"packageJsonUpdates": {
|
||||||
|
|||||||
@ -4,5 +4,5 @@
|
|||||||
"emitDecoratorMetadata": true
|
"emitDecoratorMetadata": true
|
||||||
},
|
},
|
||||||
"exclude": ["../**/*.spec.ts" <% if(uiFramework === '@storybook/react') { %>, "../**/*.spec.js", "../**/*.spec.tsx", "../**/*.spec.jsx"<% } %>],
|
"exclude": ["../**/*.spec.ts" <% if(uiFramework === '@storybook/react') { %>, "../**/*.spec.js", "../**/*.spec.tsx", "../**/*.spec.jsx"<% } %>],
|
||||||
"include": ["../src/**/*"]
|
"include": ["../src/**/*", "*.js"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
import { Tree } from '@angular-devkit/schematics';
|
||||||
|
import { getFileContent } from '@nrwl/workspace/testing';
|
||||||
|
import { runMigration } from '../../utils/testing';
|
||||||
|
|
||||||
|
describe('Update 11-5-3', () => {
|
||||||
|
let tree: Tree;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tree = Tree.empty();
|
||||||
|
|
||||||
|
// create workspace
|
||||||
|
tree.create(
|
||||||
|
'workspace.json',
|
||||||
|
JSON.stringify({
|
||||||
|
projects: {
|
||||||
|
['home-ui-react']: {
|
||||||
|
projectType: 'library',
|
||||||
|
root: 'libs/home/ui-react',
|
||||||
|
sourceRoot: 'libs/home/ui-react/src',
|
||||||
|
architect: {
|
||||||
|
storybook: {
|
||||||
|
builder: '@nrwl/storybook:storybook',
|
||||||
|
options: {
|
||||||
|
uiFramework: '@storybook/react',
|
||||||
|
port: 4400,
|
||||||
|
config: {
|
||||||
|
configFolder: 'libs/home/ui-react/.storybook',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
tree.create(
|
||||||
|
'libs/home/ui-react/.storybook/tsconfig.json',
|
||||||
|
JSON.stringify({
|
||||||
|
extends: '../tsconfig.json',
|
||||||
|
include: ['../src/**/*'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should add storybook tsconfig to lint target and update tsconfigs in project for React project`, async () => {
|
||||||
|
tree = await runMigration('update-11-5-3', {}, tree);
|
||||||
|
|
||||||
|
expect(getFileContent(tree, 'libs/home/ui-react/.storybook/tsconfig.json'))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
"{
|
||||||
|
\\"extends\\": \\"../tsconfig.json\\",
|
||||||
|
\\"include\\": [\\"../src/**/*\\", \\"./*.js\\"]
|
||||||
|
}
|
||||||
|
"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import {
|
||||||
|
chain,
|
||||||
|
Tree,
|
||||||
|
SchematicContext,
|
||||||
|
Rule,
|
||||||
|
} from '@angular-devkit/schematics';
|
||||||
|
|
||||||
|
import {
|
||||||
|
formatFiles,
|
||||||
|
readJsonInTree,
|
||||||
|
updateWorkspaceInTree,
|
||||||
|
serializeJson,
|
||||||
|
} from '@nrwl/workspace';
|
||||||
|
|
||||||
|
import { isFramework, TsConfig } from '../../utils/utilities';
|
||||||
|
import { normalize } from '@angular-devkit/core';
|
||||||
|
|
||||||
|
interface ProjectDefinition {
|
||||||
|
root: string;
|
||||||
|
sourceRoot: string;
|
||||||
|
projectType: 'library' | 'application';
|
||||||
|
|
||||||
|
schematic?: Record<string, any>;
|
||||||
|
architect: Record<
|
||||||
|
string,
|
||||||
|
import('@angular-devkit/core').workspaces.TargetDefinition
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function (tree: Tree, context: SchematicContext) {
|
||||||
|
return chain([update, formatFiles()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(tree: Tree, context: SchematicContext): Rule {
|
||||||
|
return updateWorkspaceInTree((config, context, tree) => {
|
||||||
|
Object.entries<ProjectDefinition>(config.projects).forEach(
|
||||||
|
([projectName, projectConfig]) => {
|
||||||
|
updateTsconfigInclude(tree, context, { projectName, projectConfig });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTsconfigInclude(
|
||||||
|
tree: Tree,
|
||||||
|
context: SchematicContext,
|
||||||
|
options: {
|
||||||
|
projectName: string;
|
||||||
|
projectConfig: ProjectDefinition;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const architect = options.projectConfig.architect;
|
||||||
|
|
||||||
|
const paths = {
|
||||||
|
tsConfigStorybook: normalize(
|
||||||
|
path.join(options.projectConfig.root, '.storybook/tsconfig.json')
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasStorybookConfig =
|
||||||
|
architect.storybook && tree.exists(paths.tsConfigStorybook);
|
||||||
|
|
||||||
|
if (!hasStorybookConfig) {
|
||||||
|
context.logger.info(
|
||||||
|
`${options.projectName}: no storybook configured. skipping migration...`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isReactProject = isFramework('react', {
|
||||||
|
uiFramework: architect.storybook.options?.uiFramework as Parameters<
|
||||||
|
typeof isFramework
|
||||||
|
>[1]['uiFramework'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const tsConfig = {
|
||||||
|
storybook: readJsonInTree<TsConfig>(tree, paths.tsConfigStorybook),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isReactProject && Array.isArray(tsConfig.storybook.include)) {
|
||||||
|
tsConfig.storybook.include = uniqueArray([
|
||||||
|
...tsConfig.storybook.include,
|
||||||
|
'./*.js',
|
||||||
|
]);
|
||||||
|
tree.overwrite(paths.tsConfigStorybook, serializeJson(tsConfig.storybook));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function uniqueArray<T extends Array<any>>(value: T) {
|
||||||
|
return [...new Set(value)] as T;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user