Skip to content

Commit

Permalink
Merge pull request #25888 from storybookjs/yann/rename-testing-utils-…
Browse files Browse the repository at this point in the history
…to-portable-stories

Maintenance: Rename testing-utils paths to portable-stories
  • Loading branch information
yannbf authored Feb 6, 2024
2 parents ccb3e1a + a307dfa commit 1d8b5ea
Show file tree
Hide file tree
Showing 15 changed files with 211 additions and 331 deletions.
2 changes: 1 addition & 1 deletion code/lib/preview-api/src/modules/store/csf/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ export * from './normalizeProjectAnnotations';
export * from './getValuesFromArgTypes';
export * from './composeConfigs';
export * from './stepRunners';
export * from './testing-utils';
export * from './portable-stories';
146 changes: 146 additions & 0 deletions code/lib/preview-api/src/modules/store/csf/portable-stories.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { describe, expect, vi, it } from 'vitest';
import { composeStory, composeStories } from './portable-stories';

// Most integration tests for this functionality are located under renderers/react
describe('composeStory', () => {
const meta = {
title: 'Button',
parameters: {
firstAddon: true,
},
args: {
label: 'Hello World',
primary: true,
},
};

it('should return story with composed args and parameters', () => {
const Story = () => {};
Story.args = { primary: true };
Story.parameters = {
parameters: {
secondAddon: true,
},
};

const composedStory = composeStory(Story, meta);
expect(composedStory.args).toEqual({ ...Story.args, ...meta.args });
expect(composedStory.parameters).toEqual(
expect.objectContaining({ ...Story.parameters, ...meta.parameters })
);
});

it('should throw an error if Story is undefined', () => {
expect(() => {
// @ts-expect-error (invalid input)
composeStory(undefined, meta);
}).toThrow();
});

describe('Id of the story', () => {
it('is exposed correctly when composeStories is used', () => {
const module = {
default: {
title: 'Example/Button',
},
CSF3Primary: () => {},
};
const Primary = composeStory(module.CSF3Primary, module.default, {});
expect(Primary.id).toBe('example-button--csf-3-primary');
});
it('is exposed correctly when composeStory is used and exportsName is passed', () => {
const module = {
default: {
title: 'Example/Button',
},
CSF3Primary: () => {},
};
const Primary = composeStory(module.CSF3Primary, module.default, {}, {}, 'overwritten');
expect(Primary.id).toBe('example-button--overwritten');
});
it("is not unique when composeStory is used and exportsName isn't passed", () => {
const Primary = composeStory({ render: () => {} }, {});
expect(Primary.id).toContain('unknown');
});
});
});

describe('composeStories', () => {
const composeStoryFn = vi.fn((v) => v);
const defaultAnnotations = { render: () => '' };
it('should call composeStoryFn with stories', () => {
const composeStorySpy = vi.fn((v) => v);
const module = {
default: {
title: 'Button',
},
StoryOne: () => {},
StoryTwo: () => {},
};
const globalConfig = {};
composeStories(module, globalConfig, composeStorySpy);
expect(composeStorySpy).toHaveBeenCalledWith(
module.StoryOne,
module.default,
globalConfig,
'StoryOne'
);
expect(composeStorySpy).toHaveBeenCalledWith(
module.StoryTwo,
module.default,
globalConfig,
'StoryTwo'
);
});

it('should not call composeStoryFn for non-story exports', () => {
const composeStorySpy = vi.fn((v) => v);
const module = {
default: {
title: 'Button',
excludeStories: /Data/,
},
mockData: {},
};
composeStories(module, defaultAnnotations, composeStoryFn);
expect(composeStorySpy).not.toHaveBeenCalled();
});

describe('non-story exports', () => {
it('should filter non-story exports with excludeStories', () => {
const StoryModuleWithNonStoryExports = {
default: {
title: 'Some/Component',
excludeStories: /.*Data/,
},
LegitimateStory: () => 'hello world',
mockData: {},
};

const result = composeStories(
StoryModuleWithNonStoryExports,
defaultAnnotations,
composeStoryFn
);
expect(Object.keys(result)).not.toContain('mockData');
});

it('should filter non-story exports with includeStories', () => {
const StoryModuleWithNonStoryExports = {
default: {
title: 'Some/Component',
includeStories: /.*Story/,
},
LegitimateStory: () => 'hello world',
mockData: {},
};

const result = composeStories(
StoryModuleWithNonStoryExports,
defaultAnnotations,
composeStoryFn
);
expect(Object.keys(result)).not.toContain('mockData');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import type {
} from '@storybook/types';

import { HooksContext } from '../../../addons';
import { composeConfigs } from '../composeConfigs';
import { prepareContext, prepareStory } from '../prepareStory';
import { normalizeStory } from '../normalizeStory';
import { normalizeComponentAnnotations } from '../normalizeComponentAnnotations';
import { getValuesFromArgTypes } from '../getValuesFromArgTypes';
import { normalizeProjectAnnotations } from '../normalizeProjectAnnotations';
import { composeConfigs } from './composeConfigs';
import { prepareContext, prepareStory } from './prepareStory';
import { normalizeStory } from './normalizeStory';
import { normalizeComponentAnnotations } from './normalizeComponentAnnotations';
import { getValuesFromArgTypes } from './getValuesFromArgTypes';
import { normalizeProjectAnnotations } from './normalizeProjectAnnotations';

let GLOBAL_STORYBOOK_PROJECT_ANNOTATIONS = composeConfigs([]);

Expand Down

This file was deleted.

117 changes: 0 additions & 117 deletions code/renderers/react/src/__test__/internals.test.tsx

This file was deleted.

Loading

0 comments on commit 1d8b5ea

Please sign in to comment.