From 2565265d9000847ba6341912c28d50dd5610fc80 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Wed, 3 May 2023 17:32:58 +0300 Subject: [PATCH] fix(storybook): ignore nx storybook plugin from sb eslint --- package.json | 2 +- packages/storybook/migrations.json | 9 ++ .../eslint-ignore-react-plugin.spec.ts | 90 +++++++++++++++++++ .../eslint-ignore-react-plugin.ts | 49 ++++++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.spec.ts create mode 100644 packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.ts diff --git a/package.json b/package.json index 8301ef1d60bc23..0177473ff1207a 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "eslint-plugin-jsx-a11y": "6.6.1", "eslint-plugin-react": "7.31.11", "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-storybook": "^0.6.11", + "eslint-plugin-storybook": "^0.6.12", "express": "^4.18.1", "fast-xml-parser": "^4.0.9", "figures": "3.2.0", diff --git a/packages/storybook/migrations.json b/packages/storybook/migrations.json index 2217a2364e4f64..94f01aca079ac2 100644 --- a/packages/storybook/migrations.json +++ b/packages/storybook/migrations.json @@ -56,6 +56,15 @@ } }, "packageJsonUpdates": { + "16.1.0": { + "version": "16.1.0-beta.0", + "packages": { + "eslint-plugin-storybook": { + "version": "^0.6.12", + "alwaysAddToPackageJson": false + } + } + }, "16.0.0": { "version": "16.0.0-beta.1", "packages": { diff --git a/packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.spec.ts b/packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.spec.ts new file mode 100644 index 00000000000000..58c9ed5a4e514e --- /dev/null +++ b/packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.spec.ts @@ -0,0 +1,90 @@ +import { + addProjectConfiguration, + ProjectConfiguration, + readJson, + Tree, + updateJson, +} from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import * as variousProjects from '../update-15-7-0/test-configs/various-configs.json'; +import eslintIgnoreReactPlugin from './eslint-ignore-react-plugin'; + +describe('Ignore @nx/react/plugins/storybook in Storybook eslint plugin', () => { + let tree: Tree; + + beforeEach(async () => { + tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + addProjectConfiguration( + tree, + variousProjects['main-vite'].name, + variousProjects['main-vite'] as ProjectConfiguration + ); + tree.write('apps/main-vite/tsconfig.json', `{}`); + tree.write( + `apps/main-vite/.storybook/main.js`, + ` + module.exports = { + stories: ['../src/lib/**/*.stories.@(mdx|js|jsx|ts|tsx)'], + addons: ['@storybook/addon-essentials'], + framework: { + name: '@storybook/react-vite', + options: {}, + }, + }; + ` + ); + addProjectConfiguration( + tree, + variousProjects['main-webpack'].name, + variousProjects['main-webpack'] as ProjectConfiguration + ); + + if (!tree.exists('.eslintrc.json')) { + tree.write('.eslintrc.json', '{}'); + } + updateJson(tree, '.eslintrc.json', (json) => { + json.extends ??= []; + json.extends.push('plugin:storybook/recommended'); + return json; + }); + }); + + it('should not ignore the plugin if it is not used', async () => { + await eslintIgnoreReactPlugin(tree); + const eslintConfig = readJson(tree, '.eslintrc.json'); + expect(eslintConfig.rules).toBeUndefined(); + }); + + it(`should add ignore @nx/react/plugins/storybook to eslint config`, async () => { + tree.write('apps/main-webpack/tsconfig.json', `{}`); + tree.write( + `apps/main-webpack/.storybook/main.js`, + ` + module.exports = { + stories: ['../src/lib/**/*.stories.@(mdx|js|jsx|ts|tsx)'], + addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + framework: { + name: '@storybook/react-webpack5', + options: {}, + }, + }; + ` + ); + + await eslintIgnoreReactPlugin(tree); + + const eslintConfig = readJson(tree, '.eslintrc.json'); + expect(eslintConfig.rules).toHaveProperty( + 'storybook/no-uninstalled-addons' + ); + + expect(eslintConfig.rules['storybook/no-uninstalled-addons']).toMatchObject( + [ + 'error', + { + ignore: ['@nx/react/plugins/storybook'], + }, + ] + ); + }); +}); diff --git a/packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.ts b/packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.ts new file mode 100644 index 00000000000000..24f028092e1b90 --- /dev/null +++ b/packages/storybook/src/migrations/update-16-1-0/eslint-ignore-react-plugin.ts @@ -0,0 +1,49 @@ +import { + getProjects, + joinPathFragments, + Tree, + formatFiles, + updateJson, +} from '@nx/devkit'; + +export default async function (tree: Tree) { + const projects = getProjects(tree); + const reactPlugin = '@nx/react/plugins/storybook'; + let shouldIgnoreReactPlugin = false; + + for (const [, config] of projects) { + let sbConfigPath = joinPathFragments(config.root, '.storybook/main.ts'); + + if (!tree.exists(sbConfigPath)) { + sbConfigPath = joinPathFragments(config.root, '.storybook/main.js'); + } + + if (!tree.exists(sbConfigPath)) { + continue; + } + + const sbConfig = tree.read(sbConfigPath, 'utf-8'); + console.log('sbConfig', sbConfig); + if (sbConfig.includes(reactPlugin)) { + shouldIgnoreReactPlugin = true; + break; + } + } + + if (shouldIgnoreReactPlugin && tree.exists('.eslintrc.json')) { + updateJson(tree, '.eslintrc.json', (json) => { + if (json.extends?.includes('plugin:storybook/recommended')) { + json.rules ??= {}; + json.rules['storybook/no-uninstalled-addons'] = [ + 'error', + { + ignore: ['@nx/react/plugins/storybook'], + }, + ]; + return json; + } + }); + } + + await formatFiles(tree); +}