make depth configurable

This commit is contained in:
Rob Halff 2018-04-15 20:56:05 +01:00
parent d26ea97a2f
commit dd6e12e18f
9 changed files with 127 additions and 8 deletions

View File

@ -3,4 +3,4 @@ export const ADDON_ID = 'storybook/actions';
export const PANEL_ID = `${ADDON_ID}/actions-panel`;
export const EVENT_ID = `${ADDON_ID}/action-event`;
export { action, decorateAction } from './preview';
export * from './preview';

View File

@ -2,7 +2,6 @@ import reviver from './reviver';
import { muteProperty } from './util';
import { CYCLIC_KEY } from './';
// eslint-disable-next-line no-control-regex
const pathReg = /^\$(?:\[(?:\d+|"(?:[^\\"\u0000-\u001f]|\\([\\"/bfnrt]|u[0-9a-zA-Z]{4}))*")])*$/;
export default function retrocycle(json) {

View File

@ -1,8 +1,8 @@
import { decycle } from '../index';
export default function prepareArguments(arg) {
export default function prepareArguments(arg, depth) {
try {
return JSON.stringify(decycle(arg));
return JSON.stringify(decycle(arg, depth));
} catch (error) {
return error.toString(); // IE still cyclic.
}

View File

@ -0,0 +1,90 @@
import addons from '@storybook/addons';
import { action, configureActions } from '../../';
jest.mock('@storybook/addons');
const getChannelData = channel =>
channel.emit.mock.calls[channel.emit.mock.calls.length - 1][1].data;
describe('Action', () => {
const channel = { emit: jest.fn() };
addons.getChannel.mockReturnValue(channel);
it('with one argument', () => {
action('test-action')('one');
expect(getChannelData(channel).args[0]).toEqual('"one"');
});
it('with multiple arguments', () => {
action('test-action')('one', 'two', 'three');
expect(getChannelData(channel).args).toEqual(['"one"', '"two"', '"three"']);
});
it('with global depth configuration', () => {
const depth = 1;
configureActions({
depth,
});
action('test-action')({
root: {
one: {
two: 'foo',
},
},
});
expect(getChannelData(channel).args[0]).toEqual(
JSON.stringify({
'$___storybook.objectName': 'Object',
root: {
'$___storybook.objectName': 'Object',
one: {
'$___storybook.objectName': 'Object',
},
},
})
);
});
it('per action depth option overrides global config', () => {
configureActions({
depth: 1,
});
action('test-action', { depth: 3 })({
root: {
one: {
two: {
three: {
four: {
five: 'foo',
},
},
},
},
},
});
expect(getChannelData(channel).args[0]).toEqual(
JSON.stringify({
'$___storybook.objectName': 'Object',
root: {
'$___storybook.objectName': 'Object',
one: {
'$___storybook.objectName': 'Object',
two: {
'$___storybook.objectName': 'Object',
three: {
'$___storybook.objectName': 'Object',
},
},
},
},
})
);
});
});

View File

@ -0,0 +1,16 @@
import { config } from '../configureActions';
import { configureActions } from '../../';
describe('Configure Actions', () => {
it('can configure actions', () => {
const depth = 100;
configureActions({
depth,
});
expect(config).toEqual({
depth,
});
});
});

View File

@ -2,11 +2,17 @@ import uuid from 'uuid/v1';
import addons from '@storybook/addons';
import { EVENT_ID } from '../';
import { canConfigureName, prepareArguments } from '../lib/util';
import { config } from './configureActions';
export default function action(name, options = {}) {
const actionOptions = {
...config,
...options,
};
export default function action(name) {
// eslint-disable-next-line no-shadow
const handler = function action(..._args) {
const args = _args.map(prepareArguments);
const args = _args.map(arg => prepareArguments(arg, actionOptions.depth));
const channel = addons.getChannel();
const id = uuid();
channel.emit(EVENT_ID, {

View File

@ -0,0 +1,7 @@
export const config = {
depth: 10,
};
export function configureActions(options = {}) {
Object.assign(config, options);
}

View File

@ -1,8 +1,8 @@
import { action } from '../preview';
export default function decorateAction(decorators) {
return name => {
const callAction = action(name);
return (name, options) => {
const callAction = action(name, options);
return (..._args) => {
const decorated = decorators.reduce((args, fn) => fn(args), _args);
callAction(...decorated);

View File

@ -1,2 +1,3 @@
export { default as action } from './action';
export { configureActions } from './configureActions';
export { default as decorateAction } from './decorateAction';