Skip to content

Commit

Permalink
feat(cli): add prop codemods (#600)
Browse files Browse the repository at this point in the history
* feat(cli): add codemod for List props

* refactor(cli): extract function to find local component names

* feat(cli): add codemod to rename onChange props

* feat(cli): add codemod to rename as prop

* feat(cli): add codemod to rename Selector props

* feat(cli): add codemod to remove exit animations

* feat(cli): add codemod to rename ref Input prop
  • Loading branch information
connor-baer authored Jun 4, 2020
1 parent b63d385 commit f9cbb24
Show file tree
Hide file tree
Showing 22 changed files with 588 additions and 12 deletions.
11 changes: 10 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ module.exports = require('@sumup/foundry/eslint')(
rules: {
'import/no-unresolved': 'off',
'notice/notice': 'off',
'@typescript-eslint/no-unused-vars': 'off'
'@typescript-eslint/no-unused-vars': 'off',
'prettier/prettier': 'off'
}
},
{
files: ['src/cli/migrate/*.ts'],
rules: {
// jscodeshift expect no return value for files
// that should not be transformed.
'consistent-return': 'off'
}
}
]
Expand Down
35 changes: 35 additions & 0 deletions src/cli/migrate/__testfixtures__/as-prop.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import styled from '@emotion/styled';
import { Heading, SubHeading, Text, Input } from '@sumup/circuit-ui';

const BaseHeading = () => <Heading element="h1" />;

const RedHeading = styled(Heading)`
color: red;
`;

const StyledHeading = () => <RedHeading element="h1" />;

const BaseSubHeading = () => <SubHeading element="h1" />;

const RedSubHeading = styled(SubHeading)`
color: red;
`;

const StyledSubHeading = () => <RedSubHeading element="h1" />;

const BaseText = () => <Text element="h1" />;

const RedText = styled(Text)`
color: red;
`;

const StyledText = () => <RedText element="h1" />;

const BaseInput = () => <Input element="h1" />;

const RedInput = styled(Input)`
color: red;
`;

const StyledInput = () => <RedInput element="h1" />;
35 changes: 35 additions & 0 deletions src/cli/migrate/__testfixtures__/as-prop.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import styled from '@emotion/styled';
import { Heading, SubHeading, Text, Input } from '@sumup/circuit-ui';

const BaseHeading = () => <Heading as="h1" />;

const RedHeading = styled(Heading)`
color: red;
`;

const StyledHeading = () => <RedHeading as="h1" />;

const BaseSubHeading = () => <SubHeading as="h1" />;

const RedSubHeading = styled(SubHeading)`
color: red;
`;

const StyledSubHeading = () => <RedSubHeading as="h1" />;

const BaseText = () => <Text as="h1" />;

const RedText = styled(Text)`
color: red;
`;

const StyledText = () => <RedText as="h1" />;

const BaseInput = () => <Input as="h1" />;

const RedInput = styled(Input)`
color: red;
`;

const StyledInput = () => <RedInput as="h1" />;
23 changes: 23 additions & 0 deletions src/cli/migrate/__testfixtures__/exit-animations.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import styled from '@emotion/styled';
import { LoadingButton } from '@sumup/circuit-ui';

const BaseLoadingButton = () => (
<LoadingButton
exitAnimation={LoadingButton.ERROR}
onAnimationComplete={console.log}
exitAnimationDuration={300}
/>
);

const RedLoadingButton = styled(LoadingButton)`
color: red;
`;

const StyledLoadingButton = () => (
<RedLoadingButton
exitAnimation={LoadingButton.ERROR}
onAnimationComplete={console.log}
exitAnimationDuration={300}
/>
);
15 changes: 15 additions & 0 deletions src/cli/migrate/__testfixtures__/exit-animations.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import styled from '@emotion/styled';
import { LoadingButton } from '@sumup/circuit-ui';

const BaseLoadingButton = () => (
<LoadingButton />
);

const RedLoadingButton = styled(LoadingButton)`
color: red;
`;

const StyledLoadingButton = () => (
<RedLoadingButton />
);
17 changes: 17 additions & 0 deletions src/cli/migrate/__testfixtures__/input-deepref-prop.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { useRef } from 'react';
import styled from '@emotion/styled';
import { Input } from '@sumup/circuit-ui';

const Form = () => {
const ref = useRef(null);
return <Input deepRef={ref} />;
};

const RedInput = styled(Input)`
color: red;
`;

const RedForm = () => {
const ref = useRef(null);
return <RedInput deepRef={ref} />;
};
17 changes: 17 additions & 0 deletions src/cli/migrate/__testfixtures__/input-deepref-prop.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { useRef } from 'react';
import styled from '@emotion/styled';
import { Input } from '@sumup/circuit-ui';

const Form = () => {
const ref = useRef(null);
return <Input ref={ref} />;
};

const RedInput = styled(Input)`
color: red;
`;

const RedForm = () => {
const ref = useRef(null);
return <RedInput ref={ref} />;
};
28 changes: 28 additions & 0 deletions src/cli/migrate/__testfixtures__/list-variant-enum.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import styled from '@emotion/styled';
import { List, Text } from '@sumup/circuit-ui';

const Ordered = () => <List ordered>primary</List>;

const Unordered = () => <List unordered>Secondary</List>;

const RedList = styled(List)`
color: red;
`;

const BlueList = styled(List)`
color: blue;
`;

const BlueText = styled(Text)`
color: blue;
`;

const Styled = () => (
<>
<RedList ordered>Ordered red</RedList>
<BlueList unordered>Unordered blue</BlueList>
<Text ordered>Text</Text>
<BlueText unordered>Text blue</BlueText>
</>
);
28 changes: 28 additions & 0 deletions src/cli/migrate/__testfixtures__/list-variant-enum.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import styled from '@emotion/styled';
import { List, Text } from '@sumup/circuit-ui';

const Ordered = () => <List variant="ordered">primary</List>;

const Unordered = () => <List variant="unordered">Secondary</List>;

const RedList = styled(List)`
color: red;
`;

const BlueList = styled(List)`
color: blue;
`;

const BlueText = styled(Text)`
color: blue;
`;

const Styled = () => (
<>
<RedList variant="ordered">Ordered red</RedList>
<BlueList variant="unordered">Unordered blue</BlueList>
<Text ordered>Text</Text>
<BlueText unordered>Text blue</BlueText>
</>
);
21 changes: 21 additions & 0 deletions src/cli/migrate/__testfixtures__/onchange-prop.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import styled from '@emotion/styled';
import { RadioButton, Switch } from '@sumup/circuit-ui';

const BaseRadioButton = () => <RadioButton onToggle={console.log} checked />;

const RedRadioButton = styled(RadioButton)`
color: red;
`;

const StyledRadioButton = () => (
<RedRadioButton onToggle={console.log} checked />
);

const BaseSwitch = () => <Switch onToggle={console.log} checked />;

const RedSwitch = styled(Switch)`
color: red;
`;

const StyledSwitch = () => <RedSwitch onToggle={console.log} checked />;
21 changes: 21 additions & 0 deletions src/cli/migrate/__testfixtures__/onchange-prop.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import styled from '@emotion/styled';
import { RadioButton, Switch } from '@sumup/circuit-ui';

const BaseRadioButton = () => <RadioButton onChange={console.log} checked />;

const RedRadioButton = styled(RadioButton)`
color: red;
`;

const StyledRadioButton = () => (
<RedRadioButton onChange={console.log} checked />
);

const BaseSwitch = () => <Switch onChange={console.log} checked />;

const RedSwitch = styled(Switch)`
color: red;
`;

const StyledSwitch = () => <RedSwitch onChange={console.log} checked />;
11 changes: 11 additions & 0 deletions src/cli/migrate/__testfixtures__/selector-props.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import styled from '@emotion/styled';
import { Selector } from '@sumup/circuit-ui';

const BaseSelector = () => <Selector onClick={console.log} selected />;

const RedSelector = styled(Selector)`
color: red;
`;

const StyledSelector = () => <RedSelector onClick={console.log} selected />;
11 changes: 11 additions & 0 deletions src/cli/migrate/__testfixtures__/selector-props.output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import styled from '@emotion/styled';
import { Selector } from '@sumup/circuit-ui';

const BaseSelector = () => <Selector onChange={console.log} checked />;

const RedSelector = styled(Selector)`
color: red;
`;

const StyledSelector = () => <RedSelector onChange={console.log} checked />;
6 changes: 6 additions & 0 deletions src/cli/migrate/__tests__/transforms.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ import { defineTest } from 'jscodeshift/dist/testUtils';
jest.autoMockOff();

defineTest(__dirname, 'button-variant-enum');
defineTest(__dirname, 'list-variant-enum');
defineTest(__dirname, 'onchange-prop');
defineTest(__dirname, 'as-prop');
defineTest(__dirname, 'selector-props');
defineTest(__dirname, 'exit-animations');
defineTest(__dirname, 'input-deepref-prop');
47 changes: 47 additions & 0 deletions src/cli/migrate/as-prop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright 2020, SumUp Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { Transform, JSCodeshift, Collection } from 'jscodeshift';

import { renameJSXAttribute, findLocalNames } from './utils';

function transformFactory(
j: JSCodeshift,
root: Collection,
componentName: string
): void {
const components = findLocalNames(j, root, componentName);

if (!components) {
return;
}

components.forEach(component => {
renameJSXAttribute(j, root, component, 'element', 'as');
});
}

const transform: Transform = (file, api) => {
const j = api.jscodeshift;
const root = j(file.source);

['Heading', 'SubHeading', 'Text', 'Input'].forEach(componentName => {
transformFactory(j, root, componentName);
});

return root.toSource();
};

export default transform;
14 changes: 3 additions & 11 deletions src/cli/migrate/button-variant-enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,19 @@

import { Transform, JSCodeshift, Collection } from 'jscodeshift';

import { findImportsByPath, findStyledComponentNames } from './utils';
import { findLocalNames } from './utils';

function transformFactory(
j: JSCodeshift,
root: Collection,
buttonName: string
): void {
const imports = findImportsByPath(j, root, '@sumup/circuit-ui');
const components = findLocalNames(j, root, buttonName);

const buttonImport = imports.find(i => i.name === buttonName);

if (!buttonImport) {
if (!components) {
return;
}

const localName = buttonImport.local;

const styledButtons = findStyledComponentNames(j, root, localName);

const components = [localName, ...styledButtons];

components.forEach(component => {
// Change variants from boolean to enum prop
['primary', 'secondary'].forEach(variant => {
Expand Down
Loading

0 comments on commit f9cbb24

Please sign in to comment.