Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,40 @@ describe('attachCSFFile', () => {
});
});

describe('referenceMeta', () => {
it('works with different module namespace object but same default export (Rolldown compatibility)', () => {
// This test simulates what happens with Rolldown bundler:
// The module namespace object from MDX import differs from the one stored in CSFFile,
// but the .default property (meta export) is the same object reference
const { story, csfFile, metaExport, storyExport } = csfFileParts();
const store = {
componentStoriesFromCSFFile: () => [story],
} as unknown as StoryStore<Renderer>;
const context = new DocsContext(channel, store, renderStoryToElement, [csfFile]);

// Create a different namespace object with the same default export
// This simulates Rolldown's behavior where namespace objects are not singletons
const differentModuleExports = { default: metaExport, story: storyExport };

// This should NOT throw, as we can resolve via the .default property
expect(() => context.referenceMeta(differentModuleExports, true)).not.toThrow();
expect(context.storyById()).toEqual(story);
});

it('throws for non-module objects (components)', () => {
const { story, csfFile, component } = csfFileParts();
const store = {
componentStoriesFromCSFFile: () => [story],
} as unknown as StoryStore<Renderer>;
const context = new DocsContext(channel, store, renderStoryToElement, [csfFile]);

// Passing a component directly should throw
expect(() => context.referenceMeta(component, true)).toThrow(
'<Meta of={} /> must reference a CSF file module export or meta export. Did you mistakenly reference your component instead of your CSF file?'
);
});
});

describe('resolveOf', () => {
const { story, csfFile, storyExport, metaExport, moduleExports, component } = csfFileParts();

Expand Down Expand Up @@ -113,6 +147,16 @@ describe('resolveOf', () => {
});
});

it('works for module exports with different object identity but same default (Rolldown compatibility)', () => {
// Simulate what happens in Rolldown: different namespace object but same default export
const differentModuleExports = { default: metaExport, story: storyExport };
expect(context.resolveOf(differentModuleExports)).toEqual({
type: 'meta',
csfFile,
preparedMeta: expect.any(Object),
});
});

it('works for components', () => {
expect(context.resolveOf(component)).toEqual({
type: 'component',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,19 @@ export class DocsContext<TRenderer extends Renderer> implements DocsContextProps
): ResolvedModuleExportFromType<TType, TRenderer> {
type TResolvedExport = ResolvedModuleExportFromType<TType, TRenderer>;

const csfFile = this.exportsToCSFFile.get(moduleExportOrType);
let csfFile = this.exportsToCSFFile.get(moduleExportOrType);

// If direct lookup fails and the object has a .default property,
// try looking up by the default export. This handles bundlers like Rolldown
// that don't preserve module namespace object identity across imports.
if (
!csfFile &&
moduleExportOrType &&
typeof moduleExportOrType === 'object' &&
'default' in moduleExportOrType
) {
csfFile = this.exportsToCSFFile.get((moduleExportOrType as ModuleExports).default);
}

if (csfFile) {
return { type: 'meta', csfFile } as TResolvedExport;
Expand Down
Loading