Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions code/addons/docs/src/blocks/blocks/Controls.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { PlayFunctionContext } from 'storybook/internal/csf';

import type { Meta, StoryObj } from '@storybook/react-vite';

import { expect, within } from 'storybook/test';
import { expect, userEvent } from 'storybook/test';

import * as ExampleStories from '../examples/ControlsParameters.stories';
import * as SubcomponentsExampleStories from '../examples/ControlsWithSubcomponentsParameters.stories';
Expand Down Expand Up @@ -185,13 +185,14 @@ export const MultipleControlsOnSamePage: Story = {
/**
* When multiple Controls blocks for the SAME story are on the same docs page, each control should
* still have a unique id (and unique name across blocks, so that radio button groups remain
* independent). This verifies the fix for https://github.com/storybookjs/storybook/issues/29295.
* independent). This verifies the fix for https://github.com/storybookjs/storybook/issues/29295
* and https://github.com/storybookjs/storybook/issues/34864.
*/
export const MultipleControlsForSameStoryOnSamePage: Story = {
render: () => (
<>
<Controls of={ExampleStories.NoParameters} />
<Controls of={ExampleStories.NoParameters} />
<Controls of={ExampleStories.WithInlineRadio} />
<Controls of={ExampleStories.WithInlineRadio} />
</>
),
play: async ({ canvasElement }) => {
Expand All @@ -201,5 +202,29 @@ export const MultipleControlsForSameStoryOnSamePage: Story = {
const uniqueIds = new Set(allIds);
await expect(allIds.length).toBeGreaterThan(0);
await expect(uniqueIds.size).toBe(allIds.length);

const radioInputs = Array.from(
canvasElement.querySelectorAll<HTMLInputElement>('input[type="radio"]')
);
const radioNames = radioInputs.map((input) => input.name);
await expect(radioNames.length).toBeGreaterThan(0);
await expect(new Set(radioNames).size).toBe(radioNames.length);
Comment on lines +206 to +211

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix radio name assertion to match radio-group semantics.

This check is currently wrong for radios. Inputs in the same group should share the same name, so Set.size === total inputs will fail for valid markup.

Suggested fix
-    const radioInputs = Array.from(
-      canvasElement.querySelectorAll<HTMLInputElement>('input[type="radio"]')
-    );
-    const radioNames = radioInputs.map((input) => input.name);
-    await expect(radioNames.length).toBeGreaterThan(0);
-    await expect(new Set(radioNames).size).toBe(radioNames.length);
+    const tables = canvasElement.querySelectorAll('.docblock-argstable');
+    await expect(tables.length).toBe(2);
+
+    const firstNames = new Set(
+      Array.from(tables[0].querySelectorAll<HTMLInputElement>('input[type="radio"]')).map(
+        (input) => input.name
+      )
+    );
+    const secondNames = new Set(
+      Array.from(tables[1].querySelectorAll<HTMLInputElement>('input[type="radio"]')).map(
+        (input) => input.name
+      )
+    );
+    await expect(firstNames.size).toBe(1);
+    await expect(secondNames.size).toBe(1);
+    await expect([...firstNames][0]).not.toBe([...secondNames][0]);
 
-    const tables = canvasElement.querySelectorAll('.docblock-argstable');
-    await expect(tables.length).toBe(2);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/addons/docs/src/blocks/blocks/Controls.stories.tsx` around lines 206 -
211, The test currently asserts that all radio input names are unique, which is
incorrect for radio groups; in Controls.stories.tsx where radioInputs and
radioNames are computed, change the second assertion to verify that all radios
share the same name (i.e., new Set(radioNames).size === 1) rather than matching
the total input count, while keeping the check that radioNames.length > 0.


const tables = canvasElement.querySelectorAll('.docblock-argstable');
await expect(tables.length).toBe(2);

const getCheckedValues = (table: Element) =>
Array.from(table.querySelectorAll<HTMLInputElement>('input[type="radio"]:checked')).map(
(input) => input.value
);

const firstBlockRadios = tables[0].querySelectorAll<HTMLInputElement>('input[type="radio"]');
const secondBlockRadios = tables[1].querySelectorAll<HTMLInputElement>('input[type="radio"]');

await userEvent.click(firstBlockRadios[1]);
await userEvent.click(secondBlockRadios[2]);

await expect(getCheckedValues(tables[0])).toEqual(['medium']);
await expect(getCheckedValues(tables[1])).toEqual(['large']);
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ export const NoParameters: Story = {
},
};

export const WithInlineRadio: Story = {
args: { a: 'small' },
argTypes: {
a: {
control: { type: 'inline-radio' },
options: ['small', 'medium', 'large'],
},
},
};

export const Include: Story = {
...NoParameters,
parameters: { docs: { controls: { include: ['a'] } } },
Expand Down