fix(storybook): button stories

- role="button" was removed at some point during refactoring which broke how the story was finding buttons
- button no longer has automatic loading state, instead it is now controlled.
This commit is contained in:
Brian McGee
2025-09-30 11:49:59 +01:00
parent feef0a513e
commit 2814c46e68
2 changed files with 7 additions and 45 deletions

View File

@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from "@kachurun/storybook-solid"; import type { Meta, StoryObj } from "@kachurun/storybook-solid";
import { Button, ButtonProps } from "./Button"; import { Button, ButtonProps } from "./Button";
import { Component } from "solid-js"; import { Component } from "solid-js";
import { expect, fn, waitFor } from "storybook/test"; import { expect, fn, waitFor, within } from "storybook/test";
import { StoryContext } from "@kachurun/storybook-solid-vite"; import { StoryContext } from "@kachurun/storybook-solid-vite";
const getCursorStyle = (el: Element) => window.getComputedStyle(el).cursor; const getCursorStyle = (el: Element) => window.getComputedStyle(el).cursor;
@@ -216,17 +216,11 @@ const timeout = process.env.NODE_ENV === "test" ? 500 : 2000;
export const Primary: Story = { export const Primary: Story = {
args: { args: {
hierarchy: "primary", hierarchy: "primary",
onAction: fn(async () => { onClick: fn(),
// wait 500 ms to simulate an action
await new Promise((resolve) => setTimeout(resolve, timeout));
// randomly fail to check that the loading state still returns to normal
if (Math.random() > 0.5) {
throw new Error("Action failure");
}
}),
}, },
play: async ({ canvas, step, userEvent, args }: StoryContext) => { play: async ({ canvasElement, step, userEvent, args }: StoryContext) => {
const canvas = within(canvasElement);
const buttons = await canvas.findAllByRole("button"); const buttons = await canvas.findAllByRole("button");
for (const button of buttons) { for (const button of buttons) {
@@ -238,14 +232,6 @@ export const Primary: Story = {
} }
await step(`Click on ${testID}`, async () => { await step(`Click on ${testID}`, async () => {
// check for the loader
const loaders = button.getElementsByClassName("loader");
await expect(loaders.length).toEqual(1);
// assert its width is 0 before we click
const [loader] = loaders;
await expect(loader.clientWidth).toEqual(0);
// move the mouse over the button // move the mouse over the button
await userEvent.hover(button); await userEvent.hover(button);
@@ -255,33 +241,8 @@ export const Primary: Story = {
// click the button // click the button
await userEvent.click(button); await userEvent.click(button);
// check the button has changed // the click handler should have been called
await waitFor( await expect(args.onClick).toHaveBeenCalled();
async () => {
// the action handler should have been called
await expect(args.onAction).toHaveBeenCalled();
// the button should have a loading class
await expect(button).toHaveClass("loading");
// the loader should be visible
await expect(loader.clientWidth).toBeGreaterThan(0);
// the pointer should have changed to wait
await expect(getCursorStyle(button)).toEqual("wait");
},
{ timeout: timeout + 500 },
);
// wait for the action handler to finish
await waitFor(
async () => {
// the loading class should be removed
await expect(button).not.toHaveClass("loading");
// the loader should be hidden
await expect(loader.clientWidth).toEqual(0);
// the pointer should be normal
await expect(getCursorStyle(button)).toEqual("pointer");
},
{ timeout: timeout + 500 },
);
}); });
} }
}, },

View File

@@ -57,6 +57,7 @@ export const Button = (props: ButtonProps) => {
return ( return (
<KobalteButton <KobalteButton
role="button"
class={cx( class={cx(
styles.button, // default button class styles.button, // default button class
local.size != "default" && styles[local.size], local.size != "default" && styles[local.size],