Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compatibility with storybook-addon-manual-mocks #53

Open
abenhamdine opened this issue Jul 25, 2024 · 9 comments
Open

compatibility with storybook-addon-manual-mocks #53

abenhamdine opened this issue Jul 25, 2024 · 9 comments
Labels
bug Something isn't working

Comments

@abenhamdine
Copy link

abenhamdine commented Jul 25, 2024

We are migrating from vite, and we are blocked by an incompatibility with https://github.com/gebeto/storybook-addon-manual-mocks
which was working perfectly with vite.

You can see the issue we ran into here : gebeto/storybook-addon-manual-mocks#19

There's also a version of this preset for webpack so we tried to use webpack addon but the error was the same.

Finally we tried to mimic the code of the addon here : https://github.com/gebeto/storybook-addon-manual-mocks/blob/main/webpack/preset.js
by overriding the rsbuild config in storybook/main.ts like that :

import { StorybookConfig } from 'storybook-react-rsbuild'
import { mergeRsbuildConfig, rspack } from '@rsbuild/core'
import path from 'path'
import fs from 'fs'

const EXTENSIONS = [".ts", ".js"]
const MOCKS_DIRECTORY = "mocks"

const config: StorybookConfig = {
  stories: [
    "../src/**/*.stories.@(ts|tsx)"
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-onboarding",
    "@storybook/addon-interactions",
    'storybook-addon-remix-react-router',
  ],
  framework: {
    name: 'storybook-react-rsbuild',
    options: {}
  },
  rsbuildFinal: (config) => {
    return mergeRsbuildConfig(config, {
      dev: {
        client: {
          overlay: false
        }
      },
      tools: {
        rspack: (config) => {
          const mocksReplacementPlugins = [
            new rspack.NormalModuleReplacementPlugin(/^\.\//, async (resource) => {
              const mockedPath = path.resolve(
                resource.context,
                MOCKS_DIRECTORY,
                resource.request
              )
              for (let ext of EXTENSIONS) {
                const isReplacementPathExists = fs.existsSync(mockedPath + ext)
                if (isReplacementPathExists) {
                  const newImportPath =
                    "./" + path.join(MOCKS_DIRECTORY, resource.request)
                  resource.request = newImportPath
                  break
                }
              }
            }),
            new rspack.NormalModuleReplacementPlugin(/^\.\.\//, async (resource) => {
              const mockedPath = path.resolve(
                resource.context,
                MOCKS_DIRECTORY,
                resource.request
              )
              for (let ext of EXTENSIONS) {
                const isReplacementPathExists = fs.existsSync(mockedPath + ext)
                if (isReplacementPathExists) {
                  const newImportPath =
                    "./" + path.join(MOCKS_DIRECTORY, resource.request)
                  resource.request = newImportPath
                  break
                }
              }
            })
          ]
          config.plugins = (config.plugins ?? []).concat(mocksReplacementPlugins)
          return config
        }
      },
      source: {
        include: [
          /node_modules[\\/]storybook-addon-remix-react-router[\\/]dist[\\/]index.js/
        ]
      }
    })
  },
  staticDirs: ['../public'],
  docs: {
    defaultName: "Docs",
    docsMode: false,
    autodocs: false,
  },
}

but still no luck : same error.

Looks like the NormalReplacement plugin has no effect, though the code is the exact copy of the webpack addon.
I really don't understand where the problem is.

Thx by advance for any kind of help.

@fi3ework
Copy link
Member

fi3ework commented Jul 25, 2024

Try adding a plugin like this. The config merging is quite complex inside, this is the way I know it should work. The way you provided should also work but not for now.

import { mergeRsbuildConfig } from '@rsbuild/core'

// --- snip ---
async rsbuildFinal(config) {
	return mergeRsbuildConfig(config, {
	  tools: {
	    rspack: (config, { addRules, appendPlugins, rspack, mergeConfig }) => {
	      return mergeConfig(config, {
	        plugins: [
	          // YOUR PLUGIN HERE
	        ],
	      })
	    },
	  },
	})
}

@fi3ework
Copy link
Member

fi3ework commented Aug 1, 2024

Hi, does this configuration help out?

@abenhamdine
Copy link
Author

no it doesn't work either

here's my storybook/main.ts file :

import { StorybookConfig } from 'storybook-react-rsbuild'
import { mergeRsbuildConfig, rspack } from '@rsbuild/core'
import path from 'path'
import fs from 'fs'

const EXTENSIONS = [".ts", ".js"]
const MOCKS_DIRECTORY = "mocks"

const config: StorybookConfig = {
  stories: [
    "../src/**/*.stories.@(ts|tsx)"
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-onboarding",
    "@storybook/addon-interactions",
    'storybook-addon-remix-react-router',
  ],
  framework: {
    name: 'storybook-react-rsbuild',
    options: {}
  },
  rsbuildFinal: (config) => {
    return mergeRsbuildConfig(config, {
      dev: {
        client: {
          overlay: false
        }
      },
      tools: {
        rspack: (config, { mergeConfig }) => {
          return mergeConfig(config, {
            plugins: [
              new rspack.NormalModuleReplacementPlugin(/^\.\//, async (resource) => {
                const mockedPath = path.resolve(
                  resource.context,
                  MOCKS_DIRECTORY,
                  resource.request
                )
                for (let ext of EXTENSIONS) {
                  const isReplacementPathExists = fs.existsSync(mockedPath + ext)
                  if (isReplacementPathExists) {
                    const newImportPath =
                      "./" + path.join(MOCKS_DIRECTORY, resource.request)
                    resource.request = newImportPath
                    break
                  }
                }
              }),
              new rspack.NormalModuleReplacementPlugin(/^\.\.\//, async (resource) => {
                const mockedPath = path.resolve(
                  resource.context,
                  MOCKS_DIRECTORY,
                  resource.request
                )
                for (let ext of EXTENSIONS) {
                  const isReplacementPathExists = fs.existsSync(mockedPath + ext)
                  if (isReplacementPathExists) {
                    const newImportPath =
                      "./" + path.join(MOCKS_DIRECTORY, resource.request)
                    resource.request = newImportPath
                    break
                  }
                }
              })
            ]
          })
        }
      },
      source: {
        define: {
          'import.meta.env.PUBLIC_GRAPHQL_SERVER_URL': JSON.stringify(process.env.PUBLIC_GRAPHQL_SERVER_URL),
          'import.meta.env.PUBLIC_MODE': JSON.stringify(process.env.PUBLIC_MODE),
          'import.meta.env.PUBLIC_DEBUG': JSON.stringify(process.env.PUBLIC_DEBUG),
          'import.meta.env.PUBLIC_GLEAP_API_KEY': JSON.stringify(process.env.PUBLIC_GLEAP_API_KEY),
          'import.meta.env.PUBLIC_SENTRY_DSN': JSON.stringify(process.env.PUBLIC_SENTRY_DSN),
          'import.meta.env.PUBLIC_CLARITY_PROJECT_ID': JSON.stringify(process.env.PUBLIC_CLARITY_PROJECT_ID)
        },
        include: [
          /node_modules[\\/]storybook-addon-remix-react-router[\\/]dist[\\/]index.js/
        ]
      }
    })
  },
  staticDirs: ['../public'],
  docs: {
    defaultName: "Docs",
    docsMode: false,
    autodocs: false,
  },
}

export default config

and still the same error : the import is not mocked.

@fi3ework
Copy link
Member

fi3ework commented Aug 1, 2024

Could you add a console.log under new rspack.NormalModuleReplacementPlugin(/^\.\//, async (resource) => { to test is the plugin being invoked indeed?

@abenhamdine
Copy link
Author

abenhamdine commented Aug 1, 2024

yes, the plugin is being invoked

$ cross-env NODE_OPTIONS=--max-old-space-size=8192 storybook dev -p 6006
storybook v8.2.7

info => Serving static files from ./.\public at /
info => Starting manager..
info => Starting preview..
info Addon-docs: using MDX3
start   Compiling...
info Using tsconfig paths for react-docgen
 // below the console.logs calls
1st plugin : resource.context :  D:\GitHub\payroll-app-next\client\src\state
1st plugin : resource.request :  ./state
1st plugin remplacement exists :  D:\GitHub\payroll-app-next\client\src\state\mocks\state.ts
1st plugin : new import path :  ./mocks\state
//
ready   Compiled in 5.79 s (web)

the replacement path is correct, however the import is not mocked
Is it allowed to mutate resource.request ?
I would say yes because if i set a new path 'fooBar/state', there's an error, thus the request path is actually being changed

@fi3ework
Copy link
Member

fi3ework commented Aug 2, 2024

The new import path ./mocks\state looks weird (I'm not familiar with Windows tbh), is that correct?

@abenhamdine
Copy link
Author

abenhamdine commented Aug 2, 2024

Yes it looks weird, but If change the path like this :

    console.log('1st plugin : remplacement exists : ', mockedPath + ext)  
    
    // old method
    //const newImportPath = "./" + path.join(MOCKS_DIRECTORY, resource.request)
    
    // new method : 
    const fileRequested = resource.request.split('/').pop()
    const newImportPath = "./" + MOCKS_DIRECTORY + "/" + fileRequested
    
    resource.request = newImportPath

logs :

start   Compiling...
info Using tsconfig paths for react-docgen
1st plugin : resource.context :  D:\GitHub\payroll-app-next\client\src\state
1st plugin : resource.request :  ./state
1st plugin remplacement exists :  D:\GitHub\payroll-app-next\client\src\state\mocks\state.ts
1st plugin : new import path :  ./mocks/state
ready   Compiled in 11.4 s (web)

see, the path looks right, but the issue is the same, the module is not mocked

I don't understand why this doesn't work, the replacement seems being processed but the mock is not active.

@fi3ework
Copy link
Member

fi3ework commented Aug 2, 2024

The NormalModuleReplacementPlugin is supprted by Rspack in web-infra-dev/rspack#6028. I suspect this has something to do with Storybook's internal configuration. It would be very nice if you could provide a minimal reproduction to help me easy to debug.

@fi3ework fi3ework added the bug Something isn't working label Aug 2, 2024
@abenhamdine
Copy link
Author

Thx for investigating, I will prepare a minimal reproduction as soon as possible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants