malcolm-kee / react-showroom

Document React components by declaring props definition and writing markdown.
https://react-showroom.js.org/
43 stars 1 forks source link

RFC: Interactions #112

Open malcolm-kee opened 2 years ago

malcolm-kee commented 2 years ago

Inspired by the upcoming StorybookJS Interaction Testing, I am thinking of introducing something similar to React Showroom.

Goals

Must-have

Nice-to-have

  1. Allowing reusing code for the interaction demo and tests, following our philosophy of reusing existing dev workflow instead of reinvent one.
  2. Undo/redo the interaction steps
  3. Ability to run the interaction step-by-step

Challenges

malcolm-kee commented 2 years ago

Note: Storybook instruments (monkey-patch) @testing-library methods so they can intercept it.

malcolm-kee commented 2 years ago

Intention of trying to reuse code for interaction with tests feel clunky as we need to define the interactions outside of the markdown file, but the interactions is dependent on the rendered content.

Reference: https://github.com/malcolm-kee/react-showroom/tree/feature/run-fn

Preview: https://61d092d22bc6cbe65a4e48a7--react-showroom-subpath.netlify.app/some-subpath/button/#usestate-example

malcolm-kee commented 2 years ago

Thinking out loud: maybe parse jest tests and then run it in browser???

malcolm-kee commented 2 years ago

After playing around with esbuild, now I have better idea how to do this:

  1. combining acorn and esbuild, create a file from component test file that will export each test with a function name generated deterministically from the test name. The dependencies of the file will be prebundled (except few libraries, e.g. react and @testing-library and those listed in imports.) (Possible improvement: if it's import the components, maybe just resolve to the component instead).
  2. component metadata will include a key-value object of { [testName]: fnName } that allows us to generate a path pointing to a specific fnName associated with a test.
  3. an InteractionBlock component will be exported from react-showroom/client which will accepts a testName props. The component will use the props in combination of the key-value object above to generates a path, e.g. /_interactions/:componentId/:fnName that will be used as url of iframe.
  4. we will create another sub app - interaction app (in addition of current showroom app and preview app) that will parse the path and use it to import specific test file and run. This app will be run in iframe rendered by InteractionBlock. The reason we want to run this as iframe is to isolate as much as possible (although we can't do it fully).
  5. For build, we also need to prerender the interaction app so the html will be generated for static site hosting.
  6. [To explore] Inject @testing-library/* usage with custom code, that will allows us to send details about the interactions from interaction app to showroom app, thus enabling play/pause feature like storybookjs.