/** @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;
}
