Skip to content

Commit

Permalink
Merge pull request storybookjs#3747 from storybooks/storyshots-advanc…
Browse files Browse the repository at this point in the history
…ed-config

Storyshots advanced config options
  • Loading branch information
igor-dv authored Jun 12, 2018
2 parents 5180de5 + 1a9a227 commit 86f37eb
Show file tree
Hide file tree
Showing 21 changed files with 358 additions and 59 deletions.
11 changes: 11 additions & 0 deletions addons/storyshots/storyshots-core/.storybook/configTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { configure } from '@storybook/react';

const req = require.context('../stories/required_with_context', true, /.stories.js$/);

function loadStories() {
req.keys().forEach(filename => req(filename));
// eslint-disable-next-line global-require
require('../stories/directly_required');
}

configure(loadStories, module);
33 changes: 32 additions & 1 deletion addons/storyshots/storyshots-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,22 @@ initStoryshots({

## Options

### `config`

The `config` parameter must be a function that helps to configure storybook like the `config.js` does.
If it's not specified, storyshots will try to use [configPath](#configPath) parameter.

```js
import initStoryshots from '@storybook/addon-storyshots';

initStoryshots({
config: ({ configure }) =>
configure(() => {
require('../stories/Button.story.js');
}, module),
});
```

### `configPath`

By default, Storyshots assumes the config directory path for your project as below:
Expand All @@ -165,6 +181,21 @@ initStoryshots({
});
```

`configPath` can also specify path to the `config.js` itself. In this case, config directory will be
a base directory of the `configPath`. It may be useful when the `config.js` for test should differ from the
original one. It also may be useful for separating tests to different test configs:

```js
initStoryshots({
configPath: '.my-storybook-config-dir/testConfig1.js'
});

initStoryshots({
configPath: '.my-storybook-config-dir/testConfig2.js'
});
```


### `suite`

By default, Storyshots groups stories inside a Jest test suite called "Storyshots". You could change it like this:
Expand Down Expand Up @@ -326,7 +357,7 @@ The value is just a [settings](https://github.com/isaacs/node-glob#options) to a
```js
initStoryshots({
integrityOptions: { cwd: __dirname }, // it will start searching from the current directory
test: multiSnapshotWithOptions({}),
test: multiSnapshotWithOptions(),
});
```

Expand Down
16 changes: 6 additions & 10 deletions addons/storyshots/storyshots-core/src/frameworks/angular/loader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import runWithRequireContext from '../require_context';
import hasDependency from '../hasDependency';
import loadConfig from '../config-loader';
import configure from '../configure';

function setupAngularJestPreset() {
// Angular + Jest + Storyshots = Crazy Shit:
Expand All @@ -20,22 +19,19 @@ function test(options) {
function load(options) {
setupAngularJestPreset();

const appOptions = require.requireActual('@storybook/angular/options').default;
const { configPath, config } = options;
const frameworkOptions = '@storybook/angular/options';
const storybook = require.requireActual('@storybook/angular');

const { content, contextOpts } = loadConfig({
configDirPath: options.configPath,
appOptions,
});

runWithRequireContext(content, contextOpts);
configure({ configPath, config, frameworkOptions, storybook });

return {
framework: 'angular',
renderTree: require.requireActual('./renderTree').default,
renderShallowTree: () => {
throw new Error('Shallow renderer is not supported for angular');
},
storybook: require.requireActual('@storybook/angular'),
storybook,
};
}

Expand Down
30 changes: 23 additions & 7 deletions addons/storyshots/storyshots-core/src/frameworks/config-loader.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
import fs from 'fs';
import path from 'path';
import { getBabelConfig } from '@storybook/core/server';

const babel = require('babel-core');

function getConfigContent({ resolvedConfigDirPath, configPath, appOptions }) {
function getConfigContent({ resolvedConfigDirPath, resolvedConfigPath, appOptions }) {
const babelConfig = getBabelConfig({
...appOptions,
configDir: resolvedConfigDirPath,
});
return babel.transformFileSync(configPath, babelConfig).code;
return babel.transformFileSync(resolvedConfigPath, babelConfig).code;
}

function load({ configDirPath, appOptions }) {
const resolvedConfigDirPath = path.resolve(configDirPath || '.storybook');
const configPath = path.join(resolvedConfigDirPath, 'config.js');
function getConfigPathParts(configPath) {
const resolvedConfigPath = path.resolve(configPath);

const content = getConfigContent({ resolvedConfigDirPath, configPath, appOptions });
const contextOpts = { filename: configPath, dirname: resolvedConfigDirPath };
if (fs.lstatSync(resolvedConfigPath).isDirectory()) {
return {
resolvedConfigDirPath: resolvedConfigPath,
resolvedConfigPath: path.join(resolvedConfigPath, 'config.js'),
};
}

return {
resolvedConfigDirPath: path.dirname(resolvedConfigPath),
resolvedConfigPath,
};
}

function load({ configPath, appOptions }) {
const { resolvedConfigPath, resolvedConfigDirPath } = getConfigPathParts(configPath);

const content = getConfigContent({ resolvedConfigDirPath, resolvedConfigPath, appOptions });
const contextOpts = { filename: resolvedConfigPath, dirname: resolvedConfigDirPath };

return {
content,
Expand Down
22 changes: 22 additions & 0 deletions addons/storyshots/storyshots-core/src/frameworks/configure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import loadConfig from './config-loader';
import runWithRequireContext from './require_context';

function configure(options) {
const { configPath = '.storybook', config, frameworkOptions, storybook } = options;

if (config && typeof config === 'function') {
config(storybook);
return;
}

const appOptions = require.requireActual(frameworkOptions).default;

const { content, contextOpts } = loadConfig({
configPath,
appOptions,
});

runWithRequireContext(content, contextOpts);
}

export default configure;
16 changes: 6 additions & 10 deletions addons/storyshots/storyshots-core/src/frameworks/html/loader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import global from 'global';
import runWithRequireContext from '../require_context';
import loadConfig from '../config-loader';
import configure from '../configure';

function test(options) {
return options.framework === 'html';
Expand All @@ -9,22 +8,19 @@ function test(options) {
function load(options) {
global.STORYBOOK_ENV = 'html';

const appOptions = require.requireActual('@storybook/html/options').default;
const { configPath, config } = options;
const frameworkOptions = '@storybook/html/options';
const storybook = require.requireActual('@storybook/html');

const { content, contextOpts } = loadConfig({
configDirPath: options.configPath,
appOptions,
});

runWithRequireContext(content, contextOpts);
configure({ configPath, config, frameworkOptions, storybook });

return {
framework: 'html',
renderTree: require.requireActual('./renderTree').default,
renderShallowTree: () => {
throw new Error('Shallow renderer is not supported for HTML');
},
storybook: require.requireActual('@storybook/html'),
storybook,
};
}

Expand Down
16 changes: 6 additions & 10 deletions addons/storyshots/storyshots-core/src/frameworks/react/loader.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import runWithRequireContext from '../require_context';
import configure from '../configure';
import hasDependency from '../hasDependency';
import loadConfig from '../config-loader';

function test(options) {
return options.framework === 'react' || (!options.framework && hasDependency('@storybook/react'));
}

function load(options) {
const appOptions = require.requireActual('@storybook/react/options').default;
const { configPath, config } = options;
const frameworkOptions = '@storybook/react/options';
const storybook = require.requireActual('@storybook/react');

const { content, contextOpts } = loadConfig({
configDirPath: options.configPath,
appOptions,
});

runWithRequireContext(content, contextOpts);
configure({ configPath, config, frameworkOptions, storybook });

return {
framework: 'react',
renderTree: require.requireActual('./renderTree').default,
renderShallowTree: require.requireActual('./renderShallowTree').default,
storybook: require.requireActual('@storybook/react'),
storybook,
};
}

Expand Down
15 changes: 13 additions & 2 deletions addons/storyshots/storyshots-core/src/frameworks/rn/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,22 @@ function test(options) {
);
}

function configure(options, storybook) {
const { configPath = 'storybook', config } = options;

if (config && typeof config === 'function') {
config(storybook);
return;
}

const resolvedConfigPath = path.resolve(configPath);
require.requireActual(resolvedConfigPath);
}

function load(options) {
const storybook = require.requireActual('@storybook/react-native');

const configPath = path.resolve(options.configPath || 'storybook');
require.requireActual(configPath);
configure(options, storybook);

return {
renderTree: require('../react/renderTree').default,
Expand Down
16 changes: 6 additions & 10 deletions addons/storyshots/storyshots-core/src/frameworks/vue/loader.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import global from 'global';
import runWithRequireContext from '../require_context';
import hasDependency from '../hasDependency';
import loadConfig from '../config-loader';
import configure from '../configure';

function mockVueToIncludeCompiler() {
jest.mock('vue', () => require.requireActual('vue/dist/vue.common.js'));
Expand All @@ -15,22 +14,19 @@ function load(options) {
global.STORYBOOK_ENV = 'vue';
mockVueToIncludeCompiler();

const appOptions = require.requireActual('@storybook/vue/options').default;
const { configPath, config } = options;
const frameworkOptions = '@storybook/vue/options';
const storybook = require.requireActual('@storybook/vue');

const { content, contextOpts } = loadConfig({
configDirPath: options.configPath,
appOptions,
});

runWithRequireContext(content, contextOpts);
configure({ configPath, config, frameworkOptions, storybook });

return {
framework: 'vue',
renderTree: require.requireActual('./renderTree').default,
renderShallowTree: () => {
throw new Error('Shallow renderer is not supported for vue');
},
storybook: require.requireActual('@storybook/vue'),
storybook,
};
}

Expand Down
10 changes: 5 additions & 5 deletions addons/storyshots/storyshots-core/src/test-bodies.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'jest-specific-snapshot';

export const snapshotWithOptions = options => ({
export const snapshotWithOptions = (options = {}) => ({
story,
context,
renderTree,
Expand All @@ -27,7 +27,7 @@ export const snapshotWithOptions = options => ({
return match(result);
};

export const multiSnapshotWithOptions = options => ({
export const multiSnapshotWithOptions = (options = {}) => ({
story,
context,
renderTree,
Expand All @@ -45,7 +45,7 @@ export function shallowSnapshot({ story, context, renderShallowTree, options = {
expect(result).toMatchSnapshot();
}

export const renderWithOptions = options => ({ story, context, renderTree }) => {
export const renderWithOptions = (options = {}) => ({ story, context, renderTree }) => {
const result = renderTree(story, context, options);

if (typeof result.then === 'function') {
Expand All @@ -55,6 +55,6 @@ export const renderWithOptions = options => ({ story, context, renderTree }) =>
return undefined;
};

export const renderOnly = renderWithOptions({});
export const renderOnly = renderWithOptions();

export const snapshot = snapshotWithOptions({});
export const snapshot = snapshotWithOptions();
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Storyshots Another Button with some emoji 1`] = `
<button
className="css-1qwzad5"
onClick={[Function]}
>
<span
aria-label="so cool"
role="img"
>
😀 😎 👍 💯
</span>
</button>
`;

exports[`Storyshots Another Button with text 1`] = `
<button
className="css-1qwzad5"
onClick={[Function]}
>
Hello Button
</button>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Storyshots Another Button with some emoji 1`] = `
<button
className="css-1qwzad5"
onClick={[Function]}
>
<span
aria-label="so cool"
role="img"
>
😀 😎 👍 💯
</span>
</button>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Storyshots Another Button with text 1`] = `
<button
className="css-1qwzad5"
onClick={[Function]}
>
Hello Button
</button>
`;
Loading

0 comments on commit 86f37eb

Please sign in to comment.