diff --git a/.changeset/pre.json b/.changeset/pre.json index 3bebf785..5d562422 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,13 +1,10 @@ { - "mode": "pre", - "tag": "next", - "initialVersions": { - "@storybook/mcp-internal-storybook": "0.0.0", - "@storybook/addon-mcp": "0.1.3", - "@storybook/mcp": "0.0.6" - }, - "changesets": [ - "dull-impalas-vanish", - "strict-boxes-sort" - ] + "mode": "pre", + "tag": "next", + "initialVersions": { + "@storybook/mcp-internal-storybook": "0.0.0", + "@storybook/addon-mcp": "0.1.3", + "@storybook/mcp": "0.0.6" + }, + "changesets": ["dull-impalas-vanish", "strict-boxes-sort"] } diff --git a/packages/mcp/src/utils/error-to-mcp-content.test.ts b/packages/mcp/src/utils/error-to-mcp-content.test.ts index 4e190df5..9d8bf7d5 100644 --- a/packages/mcp/src/utils/error-to-mcp-content.test.ts +++ b/packages/mcp/src/utils/error-to-mcp-content.test.ts @@ -3,10 +3,7 @@ import { errorToMCPContent, ManifestGetError } from './get-manifest.ts'; describe('errorToMCPContent', () => { it('should convert ManifestGetError to MCP error content', () => { - const error = new ManifestGetError( - 'Failed to get', - 'https://example.com', - ); + const error = new ManifestGetError('Failed to get', 'https://example.com'); const result = errorToMCPContent(error); diff --git a/packages/mcp/src/utils/format-manifest.test.ts b/packages/mcp/src/utils/format-manifest.test.ts index 448d6368..9a685bba 100644 --- a/packages/mcp/src/utils/format-manifest.test.ts +++ b/packages/mcp/src/utils/format-manifest.test.ts @@ -351,6 +351,48 @@ describe('formatComponentManifest', () => { " `); }); + + it('should skip examples without snippets (e.g., when there are errors)', () => { + const manifest: ComponentManifest = { + id: 'button', + name: 'Button', + path: 'src/components/Button.tsx', + import: 'import { Button } from "@/components";', + examples: [ + { + name: 'BrokenExample', + description: 'This example has an error and no snippet', + // No snippet property - should be skipped + }, + { + name: 'WorkingExample', + description: 'This example works fine', + snippet: '', + }, + ], + }; + + const result = formatComponentManifest(manifest); + + // Should only include the working example, not the broken one + expect(result).toMatchInlineSnapshot(` + " + button + Button + + Working Example + + This example works fine + + + import { Button } from "@/components"; + + + + + " + `); + }); }); describe('complete component', () => { diff --git a/packages/mcp/src/utils/get-manifest.test.ts b/packages/mcp/src/utils/get-manifest.test.ts index 348367bb..bd4619c5 100644 --- a/packages/mcp/src/utils/get-manifest.test.ts +++ b/packages/mcp/src/utils/get-manifest.test.ts @@ -187,6 +187,49 @@ describe('getManifest', () => { 'https://example.com/manifest.json', ); }); + + it('should accept examples with missing snippets', async () => { + const manifestWithMissingSnippets: ComponentManifestMap = { + v: 1, + components: { + button: { + id: 'button', + path: 'src/components/Button.tsx', + name: 'Button', + description: 'A button component', + examples: [ + { + name: 'Default', + description: 'Default button', + // snippet is optional and missing here (e.g., when there's an error) + }, + { + name: 'Primary', + description: 'Primary button', + snippet: '', + }, + ], + }, + }, + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + headers: { + get: vi.fn().mockReturnValue('application/json'), + }, + text: vi + .fn() + .mockResolvedValue(JSON.stringify(manifestWithMissingSnippets)), + }); + + const result = await getManifest('https://example.com/manifest.json'); + + expect(result).toEqual(manifestWithMissingSnippets); + expect(global.fetch).toHaveBeenCalledExactlyOnceWith( + 'https://example.com/manifest.json', + ); + }); }); describe('manifestProvider', () => {