@@ -575,6 +575,89 @@ test('should create component manifest when only attached-mdx docs have manifest
575575 ` ) ;
576576} ) ;
577577
578+ test ( 'stories are populated when meta has no explicit title' , async ( ) => {
579+ vol . fromJSON (
580+ {
581+ [ './package.json' ] : JSON . stringify ( { name : 'some-package' } ) ,
582+ [ './src/stories/Card.stories.ts' ] : dedent `
583+ import type { Meta, StoryObj } from '@storybook/react';
584+ import { Card } from './Card';
585+
586+ const meta: Meta<typeof Card> = {
587+ component: Card,
588+ };
589+ export default meta;
590+ type Story = StoryObj<typeof meta>;
591+
592+ export const Default: Story = { args: { label: 'Click me' } };
593+ export const Large: Story = { args: { label: 'Big button', size: 'large' } };
594+ ` ,
595+ [ './src/stories/Card.tsx' ] : dedent `
596+ import React from 'react';
597+ export interface CardProps {
598+ label: string;
599+ size?: 'small' | 'large';
600+ }
601+
602+ /** A simple card component */
603+ export const Card = ({ label, size }: CardProps) => {
604+ return <div className={size}>{label}</div>;
605+ };
606+ ` ,
607+ } ,
608+ '/app'
609+ ) ;
610+
611+ const manifestEntries = [
612+ {
613+ type : 'story' ,
614+ subtype : 'story' ,
615+ id : 'card--default' ,
616+ name : 'Default' ,
617+ title : 'Card' ,
618+ importPath : './src/stories/Card.stories.ts' ,
619+ componentPath : './src/stories/Card.tsx' ,
620+ tags : [ Tag . DEV , Tag . TEST , Tag . MANIFEST ] ,
621+ exportName : 'Default' ,
622+ } ,
623+ {
624+ type : 'story' ,
625+ subtype : 'story' ,
626+ id : 'card--large' ,
627+ name : 'Large' ,
628+ title : 'Card' ,
629+ importPath : './src/stories/Card.stories.ts' ,
630+ componentPath : './src/stories/Card.tsx' ,
631+ tags : [ Tag . DEV , Tag . TEST , Tag . MANIFEST ] ,
632+ exportName : 'Large' ,
633+ } ,
634+ ] ;
635+
636+ const result = await manifests ( undefined , { manifestEntries } as any ) ;
637+ const component = result ?. components ?. components ?. [ 'card' ] ;
638+
639+ // When no explicit title is in the meta, stories should still be populated
640+ // because the generator should use the index entry's title as fallback
641+ expect ( component ?. stories ) . toMatchInlineSnapshot ( `
642+ [
643+ {
644+ "description": undefined,
645+ "id": "card--default",
646+ "name": "Default",
647+ "snippet": "const Default = () => <Card label="Click me" />;",
648+ "summary": undefined,
649+ },
650+ {
651+ "description": undefined,
652+ "id": "card--large",
653+ "name": "Large",
654+ "snippet": "const Large = () => <Card label="Big button" size="large" />;",
655+ "summary": undefined,
656+ },
657+ ]
658+ ` ) ;
659+ } ) ;
660+
578661test ( 'should extract story description and summary from JSDoc comments' , async ( ) => {
579662 const code = withCSF3 ( dedent `
580663 /**
0 commit comments