Skip to content

Commit

Permalink
CLI: Fix variable collisions in storiesof-to-csf (#8106)
Browse files Browse the repository at this point in the history
CLI: Fix variable collisions in storiesof-to-csf
  • Loading branch information
shilman committed Oct 7, 2019
1 parent 9bf9150 commit d7ec320
Show file tree
Hide file tree
Showing 14 changed files with 114 additions and 30 deletions.
10 changes: 10 additions & 0 deletions lib/cli/story.js
@@ -0,0 +1,10 @@
export default {
title: 'Story',
};

export const startCase = () => 'foo';
export const camelCase = () => 'foo';

camelCase.story = {
name: 'camelCase',
};
1 change: 1 addition & 0 deletions lib/codemod/package.json
Expand Up @@ -23,6 +23,7 @@
"dependencies": {
"@mdx-js/mdx": "^1.0.0",
"@storybook/node-logger": "5.2.1",
"@storybook/router": "5.2.1",
"core-js": "^3.0.1",
"cross-spawn": "^6.0.5",
"globby": "^10.0.1",
Expand Down
4 changes: 4 additions & 0 deletions lib/codemod/src/lib/utils.js
Expand Up @@ -9,5 +9,9 @@ export const sanitizeName = name => {
if (isReserved(key)) {
key = `${key}Story`;
}
// prepend _ if name starts with a digit
if (/^\d/.test(key)) {
key = `_${key}`;
}
return key;
};
Expand Up @@ -14,4 +14,5 @@ storiesOf('Button', module)
<br />
</div>
))
.add('w/punctuation', () => <Button label="Story 2" onClick={action('click')} />);
.add('w/punctuation', () => <Button label="Story 2" onClick={action('click')} />)
.add('Start Case', () => <Button label="Story 2" onClick={action('click')} />);
Expand Up @@ -10,6 +10,11 @@ export default {
};

export const story1 = () => <Button label="Story 1" />;

story1.story = {
name: 'story1',
};

export const secondStory = () => <Button label="Story 2" onClick={action('click')} />;

secondStory.story = {
Expand All @@ -32,3 +37,5 @@ export const wPunctuation = () => <Button label="Story 2" onClick={action('click
wPunctuation.story = {
name: 'w/punctuation',
};

export const startCase = () => <Button label="Story 2" onClick={action('click')} />;
@@ -1,2 +1,11 @@
export const foo = 1;
storiesOf('bar', module).add('foo', () => <button />);
const bar = 1;
const barStory = 1;
const baz = 1;
const bazStory1 = 1;

storiesOf('foo', module)
.add('foo', () => <button />)
.add('bar', () => <button />)
.add('bazStory', () => <button />)
.add('baz', () => <button />);
@@ -1,12 +1,34 @@
export const foo = 1;
const bar = 1;
const barStory = 1;
const baz = 1;
const bazStory1 = 1;

export default {
title: 'bar',
title: 'foo',
excludeStories: ['foo'],
};

export const story0 = () => <button />;
export const fooStory = () => <button />;

story0.story = {
fooStory.story = {
name: 'foo',
};

export const barStory1 = () => <button />;

barStory1.story = {
name: 'bar',
};

export const bazStory = () => <button />;

bazStory.story = {
name: 'bazStory',
};

export const bazStory2 = () => <button />;

bazStory2.story = {
name: 'baz',
};
@@ -0,0 +1 @@
storiesOf('bar', module).add('1', () => <button />);
@@ -0,0 +1,5 @@
export default {
title: 'bar',
};

export const _1 = () => <button />;
Expand Up @@ -6,3 +6,7 @@ export default {
};

export const baz = () => <button />;

baz.story = {
name: 'baz',
};
Expand Up @@ -7,11 +7,29 @@ export default {
};

export const story1 = () => <Button label="Button1.1" />;

story1.story = {
name: 'story1',
};

export const story2 = () => <Button label="Button1.2" />;

story2.story = {
name: 'story2',
};

export default {
title: 'Button2',
};

export const story1 = () => <Button label="Button2.1" />;
export const story2 = () => <Button label="Button2.2" />;
export const story1Story = () => <Button label="Button2.1" />;

story1Story.story = {
name: 'story1',
};

export const story2Story = () => <Button label="Button2.2" />;

story2Story.story = {
name: 'story2',
};
Expand Up @@ -20,6 +20,8 @@ withStoryParameters.story = {
export const foo = () => <Button label="Foo" />;

foo.story = {
name: 'foo',

parameters: {
bar: 1,
},
Expand Down
27 changes: 10 additions & 17 deletions lib/codemod/src/transforms/__tests__/storiesof-to-csf.test.js
@@ -1,21 +1,14 @@
import fs from 'fs';
import path from 'path';

import { defineTest } from 'jscodeshift/dist/testUtils';

jest.mock('@storybook/node-logger');

const testNames = [
'basic',
'decorators',
'parameters',
'story-parameters',
'module',
'multi',
'default',
'exports',
'collision',
'const',
'story-decorators',
];

testNames.forEach(testName => {
defineTest(__dirname, `storiesof-to-csf`, null, `storiesof-to-csf/${testName}`);
});
fs.readdirSync(path.resolve(__dirname, '../__testfixtures__/storiesof-to-csf'))
.map(filename => filename.match(/^(.*)\.input\.js$/))
.filter(Boolean)
.map(match => match[1])
.forEach(testName => {
defineTest(__dirname, `storiesof-to-csf`, null, `storiesof-to-csf/${testName}`);
});
19 changes: 13 additions & 6 deletions lib/codemod/src/transforms/storiesof-to-csf.js
@@ -1,5 +1,6 @@
import prettier from 'prettier';
import { logger } from '@storybook/node-logger';
import { storyNameFromExport } from '@storybook/router';
import { sanitizeName } from '../lib/utils';

/**
Expand Down Expand Up @@ -44,7 +45,7 @@ export default function transformer(file, api, options) {
return { storyParams, storyDecorators };
}

function convertToModuleExports(path, originalExports, counter) {
function convertToModuleExports(path, originalExports) {
const base = j(path);

const statements = [];
Expand Down Expand Up @@ -127,13 +128,19 @@ export default function transformer(file, api, options) {
adds.reverse();
adds.push(path);

const identifiers = new Set();
root.find(j.Identifier).forEach(({ value }) => identifiers.add(value.name));
adds.forEach(add => {
let name = add.node.arguments[0].value;
let key = sanitizeName(name);
if (originalExports.includes(key)) {
key = `story${counter}`;
const sanitized = sanitizeName(name);
let key = sanitized;
let counter = 0;
while (identifiers.has(key)) {
key = `${sanitized}Story${counter || ''}`;
counter += 1;
}
if (key === name) {
identifiers.add(key);
if (storyNameFromExport(key) === name) {
name = null;
}

Expand Down Expand Up @@ -209,7 +216,7 @@ export default function transformer(file, api, options) {
.filter(add => add.node.callee.property && add.node.callee.property.name === 'add')
.filter(add => add.node.arguments.length >= 2 && add.node.arguments[0].type === 'Literal')
.filter(add => add.parentPath.node.type === 'ExpressionStatement')
.forEach((path, i) => convertToModuleExports(path, originalExports, i));
.forEach(path => convertToModuleExports(path, originalExports));

// remove storiesOf import
root
Expand Down

0 comments on commit d7ec320

Please sign in to comment.