Skip to content

Instantly share code, notes, and snippets.

@hasparus
Last active April 22, 2022 10:26
Show Gist options
  • Save hasparus/a06b1da99e779dc8aac4793caa7a94a7 to your computer and use it in GitHub Desktop.
Save hasparus/a06b1da99e779dc8aac4793caa7a94a7 to your computer and use it in GitHub Desktop.

Revisions

  1. hasparus revised this gist Apr 22, 2022. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions all-stories.test.tsx
    Original file line number Diff line number Diff line change
    @@ -10,6 +10,8 @@ const allStories = import.meta.glob("../src/**/*.stories.tsx");

    for (const [path, module] of Object.entries(allStories)) {
    const segments = path.split("/");

    // This assumes all stories files are named like `{ComponentName}.stories.tsx`
    const componentName = segments[segments.length - 1]!.replace(
    ".stories.tsx",
    ""
  2. hasparus revised this gist Apr 22, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion #All Stories Actually Render the Component.md
    Original file line number Diff line number Diff line change
    @@ -26,4 +26,4 @@ but
    [PreviewJS](https://previewjs.com/) with
    [Component Story Format](https://storybook.js.org/docs/react/api/csf).

    Let's roll it by hand.
    ⬇ source below ⬇
  3. hasparus revised this gist Apr 22, 2022. 1 changed file with 11 additions and 11 deletions.
    22 changes: 11 additions & 11 deletions #All Stories Actually Render the Component.md
    Original file line number Diff line number Diff line change
    @@ -3,11 +3,11 @@ to the component source. If we're not reusing our stories in unit tests and thus
    ensure they still work on CI in every Pull Request, we need to remember to check
    them during code review.

    When you're hotfixing a production bug you have more
    serious concerns than _not breaking the docs_ so every app I worked on that used
    Storybook eventually had some broken stories. Then, fixing them lands at the
    bottom of the backlog. They're just some component examples You're going to do
    it only if you actually need those stories.
    When you're hotfixing a production bug you have more serious concerns than _not
    breaking the docs_. That's understandable. Every app I worked on that used
    Storybook eventually had some broken stories. Fixing them lands at the bottom of
    the backlog; they're just some component examples and those components work on
    production now! You're going to do it only if you actually need those stories.

    **Could we write a simple test to ensure that all our stories render without
    crashing, and more than that, they actually render the component they're meant
    @@ -18,12 +18,12 @@ We could even consider snapshot testing with
    but

    1. I'm not a huge fan of failing the test when CSS gets changed. (unless you're
    building [a CSS-in-JS library](https://github.com/system-ui/theme-ui)). We want
    to write this test to lower the cost of maintenance and know earlier when
    something breaks.
    building [a CSS-in-JS library](https://github.com/system-ui/theme-ui)). We
    want to write this test to lower the cost of maintenance and know earlier
    when something breaks.

    2. I'm actually not using Storybook itself in the app I'm working
    on, just [PreviewJS](https://previewjs.com/) with
    [Component Story Format](https://storybook.js.org/docs/react/api/csf).
    2. I'm actually not using Storybook itself in the app I'm working on, just
    [PreviewJS](https://previewjs.com/) with
    [Component Story Format](https://storybook.js.org/docs/react/api/csf).

    Let's roll it by hand.
  4. hasparus revised this gist Apr 22, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion #All Stories Actually Render the Component.md
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@ to write this test to lower the cost of maintenance and know earlier when
    something breaks.

    2. I'm actually not using Storybook itself in the app I'm working
    on, just PreviewJS with
    on, just [PreviewJS](https://previewjs.com/) with
    [Component Story Format](https://storybook.js.org/docs/react/api/csf).

    Let's roll it by hand.
  5. hasparus revised this gist Apr 22, 2022. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions #All Stories Actually Render the Component.md
    Original file line number Diff line number Diff line change
    @@ -17,10 +17,12 @@ We could even consider snapshot testing with
    [`@storybook/addon-storyshots`](https://storybook.js.org/docs/react/writing-tests/snapshot-testing),
    but

    I'm not a huge fan of failing the test when CSS gets changed. (unless you're
    1. I'm not a huge fan of failing the test when CSS gets changed. (unless you're
    building [a CSS-in-JS library](https://github.com/system-ui/theme-ui)). We want
    to write this test to lower the cost of maintenance and know earlier when
    something breaks. I'm actually not using Storybook itself in the app I'm working
    something breaks.

    2. I'm actually not using Storybook itself in the app I'm working
    on, just PreviewJS with
    [Component Story Format](https://storybook.js.org/docs/react/api/csf).

  6. hasparus revised this gist Apr 22, 2022. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion #All Stories Actually Render the Component.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,9 @@
    It's easy to overlook that your component stories stopped working after changes
    to the component source. If we're not reusing our stories in unit tests and thus
    ensure they still work on CI in every Pull Request, we need to remember to check
    them during code review. When you're hotfixing a production bug you have more
    them during code review.

    When you're hotfixing a production bug you have more
    serious concerns than _not breaking the docs_ so every app I worked on that used
    Storybook eventually had some broken stories. Then, fixing them lands at the
    bottom of the backlog. They're just some component examples You're going to do
  7. hasparus renamed this gist Apr 22, 2022. 1 changed file with 0 additions and 0 deletions.
  8. hasparus revised this gist Apr 22, 2022. 1 changed file with 21 additions and 6 deletions.
    27 changes: 21 additions & 6 deletions #All Stories Actually Render the Component
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,25 @@
    It's easy to overlook that your component stories stopped working after changes to the component source. If we're not reusing our stories in unit tests and thus ensure they still work on CI in every Pull Request, we need to remember to check them during code review. When you're hotfixing a production bug you have more serious concerns than _not breaking the docs_ so every app I worked on that used Storybook eventually had some broken stories. Then, fixing them lands at the bottom of the backlog. They're just some component examples You're going to do it only if you actually need those stories.
    It's easy to overlook that your component stories stopped working after changes
    to the component source. If we're not reusing our stories in unit tests and thus
    ensure they still work on CI in every Pull Request, we need to remember to check
    them during code review. When you're hotfixing a production bug you have more
    serious concerns than _not breaking the docs_ so every app I worked on that used
    Storybook eventually had some broken stories. Then, fixing them lands at the
    bottom of the backlog. They're just some component examples You're going to do
    it only if you actually need those stories.

    **Could we write a simple test to ensure that all our stories render without crashing, and more than that, they actually render the component they're meant to render?**
    **Could we write a simple test to ensure that all our stories render without
    crashing, and more than that, they actually render the component they're meant
    to render?**

    We could even consider snapshot testing with [`@storybook/addon-storyshots`](https://storybook.js.org/docs/react/writing-tests/snapshot-testing), but
    We could even consider snapshot testing with
    [`@storybook/addon-storyshots`](https://storybook.js.org/docs/react/writing-tests/snapshot-testing),
    but

    I'm not a huge fan of failing the test when CSS gets changed. (unless you're building [a CSS-in-JS library](https://github.com/system-ui/theme-ui)). We want to write this test to lower the cost of maintenance and know earlier when something breaks.
    I'm actually not using Storybook itself in the app I'm working on, just PreviewJS with [Component Story Format](https://storybook.js.org/docs/react/api/csf).
    I'm not a huge fan of failing the test when CSS gets changed. (unless you're
    building [a CSS-in-JS library](https://github.com/system-ui/theme-ui)). We want
    to write this test to lower the cost of maintenance and know earlier when
    something breaks. I'm actually not using Storybook itself in the app I'm working
    on, just PreviewJS with
    [Component Story Format](https://storybook.js.org/docs/react/api/csf).

    Let's roll it by hand.
    Let's roll it by hand.
  9. hasparus revised this gist Apr 22, 2022. 1 changed file with 10 additions and 1 deletion.
    11 changes: 10 additions & 1 deletion #All Stories Actually Render the Component
    Original file line number Diff line number Diff line change
    @@ -1 +1,10 @@
    It's easy to overlook that your component stories stopped working after changes to the component source, so we put
    It's easy to overlook that your component stories stopped working after changes to the component source. If we're not reusing our stories in unit tests and thus ensure they still work on CI in every Pull Request, we need to remember to check them during code review. When you're hotfixing a production bug you have more serious concerns than _not breaking the docs_ so every app I worked on that used Storybook eventually had some broken stories. Then, fixing them lands at the bottom of the backlog. They're just some component examples You're going to do it only if you actually need those stories.

    **Could we write a simple test to ensure that all our stories render without crashing, and more than that, they actually render the component they're meant to render?**

    We could even consider snapshot testing with [`@storybook/addon-storyshots`](https://storybook.js.org/docs/react/writing-tests/snapshot-testing), but

    I'm not a huge fan of failing the test when CSS gets changed. (unless you're building [a CSS-in-JS library](https://github.com/system-ui/theme-ui)). We want to write this test to lower the cost of maintenance and know earlier when something breaks.
    I'm actually not using Storybook itself in the app I'm working on, just PreviewJS with [Component Story Format](https://storybook.js.org/docs/react/api/csf).

    Let's roll it by hand.
  10. hasparus revised this gist Apr 22, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion #All Stories Actually Render the Component
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    .
    It's easy to overlook that your component stories stopped working after changes to the component source, so we put
  11. hasparus revised this gist Apr 22, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions #All Stories Actually Render the Component
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    .
  12. hasparus revised this gist Apr 22, 2022. No changes.
  13. hasparus revised this gist Apr 22, 2022. No changes.
  14. hasparus revised this gist Apr 22, 2022. No changes.
  15. hasparus revised this gist Apr 22, 2022. 1 changed file with 12 additions and 0 deletions.
    12 changes: 12 additions & 0 deletions ColorPicker.stories.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    // example stories file

    import { useState } from "react";

    import { hexToHsva } from "./color-conversion";
    import { ColorPicker, HsvaColor } from "./ColorPicker";

    export const Overview = () => {
    const [state, setState] = useState<HsvaColor>(hexToHsva("#00beef"));

    return <ColorPicker color={state} onChange={setState} />;
    };
  16. hasparus revised this gist Apr 22, 2022. 1 changed file with 0 additions and 12 deletions.
    12 changes: 0 additions & 12 deletions ColorPicker.stories.tsx
    Original file line number Diff line number Diff line change
    @@ -1,12 +0,0 @@
    // example stories file

    import { useState } from "react";

    import { hexToHsva } from "./color-conversion";
    import { ColorPicker, HsvaColor } from "./ColorPicker";

    export const Overview = () => {
    const [state, setState] = useState<HsvaColor>(hexToHsva("#00beef"));

    return <ColorPicker color={state} onChange={setState} />;
    };
  17. hasparus revised this gist Apr 22, 2022. No changes.
  18. hasparus created this gist Apr 22, 2022.
    12 changes: 12 additions & 0 deletions ColorPicker.stories.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    // example stories file

    import { useState } from "react";

    import { hexToHsva } from "./color-conversion";
    import { ColorPicker, HsvaColor } from "./ColorPicker";

    export const Overview = () => {
    const [state, setState] = useState<HsvaColor>(hexToHsva("#00beef"));

    return <ColorPicker color={state} onChange={setState} />;
    };
    63 changes: 63 additions & 0 deletions all-stories.test.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    /** @vitest-environment happy-dom */

    import {
    create as createTestRenderer,
    ReactTestRendererTree,
    } from "react-test-renderer";
    import { describe, expect, it } from "vitest";

    const allStories = import.meta.glob("../src/**/*.stories.tsx");

    for (const [path, module] of Object.entries(allStories)) {
    const segments = path.split("/");
    const componentName = segments[segments.length - 1]!.replace(
    ".stories.tsx",
    ""
    );

    const shortPath = segments.slice(-2).join("/");

    describe(shortPath, () => {
    it(`renders ${componentName}`, async () => {
    for (const story of Object.values(await module())) {
    if (typeof story === "function") {
    const Component = story;

    const renderer = createTestRenderer(<Component />);

    const tree = renderer.toTree()!;
    const found = breadthFirstSearch(tree, (node) => {
    const type = node.type as string | React.ComponentType | undefined;

    const name =
    type &&
    (typeof type === "string" ? type : type.displayName || type.name);

    return name === componentName;
    });

    expect(found?.type).toBeInstanceOf(Function);
    }
    }
    });
    });
    }

    function breadthFirstSearch(
    tree: ReactTestRendererTree,
    predicate: (node: ReactTestRendererTree) => boolean
    ) {
    const queue = [tree];
    while (queue.length) {
    const node = queue.shift();
    if (!node) continue;

    if (predicate(node)) return node;

    if (node.rendered)
    queue.push(
    ...(Array.isArray(node.rendered) ? node.rendered : [node.rendered])
    );
    }
    return undefined;
    }