import { Button, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
import ConfirmButton from 'sonar-ui-common/components/controls/ConfirmButton';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import ProjectKeyInput from '../../components/common/ProjectKeyInput';
+import { validateProjectKey } from '../../helpers/projects';
+import { ProjectKeyValidationResult } from '../../types/component';
-interface Props {
+export interface UpdateFormProps {
component: Pick<T.Component, 'key' | 'name'>;
onKeyChange: (newKey: string) => Promise<void>;
}
-interface State {
- newKey?: string;
-}
-
-export default class UpdateForm extends React.PureComponent<Props, State> {
- state: State = {};
-
- handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
- const newKey = event.currentTarget.value;
- this.setState({ newKey });
- };
-
- handleReset = () => {
- this.setState({ newKey: undefined });
- };
+export default function UpdateForm(props: UpdateFormProps) {
+ const { component } = props;
+ const [newKey, setNewKey] = React.useState<string | undefined>(undefined);
+ const value = newKey !== undefined ? newKey : component.key;
+ const hasChanged = value !== component.key;
- render() {
- const { component } = this.props;
- const { newKey } = this.state;
- const value = newKey != null ? newKey : component.key;
- const hasChanged = value !== component.key;
+ const validationResult = validateProjectKey(value);
+ const error =
+ validationResult === ProjectKeyValidationResult.Valid
+ ? undefined
+ : translate('onboarding.create_project.project_key.error', validationResult);
- return (
- <ConfirmButton
- confirmButtonText={translate('update_verb')}
- confirmData={newKey}
- modalBody={
- <>
- {translateWithParameters('update_key.are_you_sure_to_change_key', component.name)}
- <div className="spacer-top">
- {translate('update_key.old_key')}
- {': '}
- <strong>{component.key}</strong>
- </div>
- <div className="spacer-top">
- {translate('update_key.new_key')}
- {': '}
- <strong>{newKey}</strong>
- </div>
- </>
- }
- modalHeader={translate('update_key.page')}
- onConfirm={this.props.onKeyChange}>
- {({ onFormSubmit }) => (
- <form onSubmit={onFormSubmit}>
- <input
- className="input-super-large"
- id="update-key-new-key"
- onChange={this.handleChange}
- placeholder={translate('update_key.new_key')}
- required={true}
- type="text"
- value={value}
- />
+ return (
+ <ConfirmButton
+ confirmButtonText={translate('update_verb')}
+ confirmData={newKey}
+ modalBody={
+ <>
+ {translateWithParameters('update_key.are_you_sure_to_change_key', component.name)}
+ <div className="spacer-top">
+ {translate('update_key.old_key')}
+ {': '}
+ <strong>{component.key}</strong>
+ </div>
+ <div className="spacer-top">
+ {translate('update_key.new_key')}
+ {': '}
+ <strong>{newKey}</strong>
+ </div>
+ </>
+ }
+ modalHeader={translate('update_key.page')}
+ onConfirm={props.onKeyChange}>
+ {({ onFormSubmit }) => (
+ <form onSubmit={onFormSubmit}>
+ <ProjectKeyInput
+ error={error}
+ label={translate('update_key.new_key')}
+ onProjectKeyChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+ setNewKey(e.currentTarget.value);
+ }}
+ touched={hasChanged}
+ placeholder={translate('update_key.new_key')}
+ projectKey={value}
+ />
- <div className="spacer-top">
- <SubmitButton disabled={!hasChanged} id="update-key-submit">
- {translate('update_verb')}
- </SubmitButton>
+ <div className="spacer-top">
+ <SubmitButton disabled={!hasChanged || error !== undefined} id="update-key-submit">
+ {translate('update_verb')}
+ </SubmitButton>
- <Button
- className="spacer-left"
- disabled={!hasChanged}
- id="update-key-reset"
- onClick={this.handleReset}
- type="reset">
- {translate('reset_verb')}
- </Button>
- </div>
- </form>
- )}
- </ConfirmButton>
- );
- }
+ <Button
+ className="spacer-left"
+ disabled={!hasChanged}
+ id="update-key-reset"
+ onClick={() => {
+ setNewKey(undefined);
+ }}
+ type="reset">
+ {translate('reset_verb')}
+ </Button>
+ </div>
+ </form>
+ )}
+ </ConfirmButton>
+ );
}
*/
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
-import { change, click } from 'sonar-ui-common/helpers/testUtils';
-import UpdateForm from '../UpdateForm';
+import { Button, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
+import { click } from 'sonar-ui-common/helpers/testUtils';
+import ProjectKeyInput from '../../../components/common/ProjectKeyInput';
+import { mockComponent, mockEvent } from '../../../helpers/testMocks';
+import UpdateForm, { UpdateFormProps } from '../UpdateForm';
it('should render', () => {
- const wrapper = shallow(
- <UpdateForm component={{ key: 'foo', name: 'Foo' }} onKeyChange={jest.fn()} />
- );
- expect(getInner(wrapper)).toMatchSnapshot();
+ expect(shallowRender()).toMatchSnapshot('default');
+ expect(getForm(shallowRender())).toMatchSnapshot('form');
+});
+
+it('should correctly update the form', () => {
+ const component = mockComponent();
+ const wrapper = shallowRender({ component });
+ expectButtonDisabled(wrapper, Button).toBe(true);
+ expectButtonDisabled(wrapper, SubmitButton).toBe(true);
+
+ // Changing the key should unlock the form.
+ changeInput(wrapper, 'bar');
+ expectProjectKeyInputValue(wrapper).toBe('bar');
+ expectButtonDisabled(wrapper, Button).toBe(false);
+ expectButtonDisabled(wrapper, SubmitButton).toBe(false);
- change(getInner(wrapper).find('input'), 'bar');
- expect(getInner(wrapper)).toMatchSnapshot();
+ // Changing it back again should lock the form.
+ changeInput(wrapper, component.key);
+ expectProjectKeyInputValue(wrapper).toBe(component.key);
+ expectButtonDisabled(wrapper, Button).toBe(true);
+ expectButtonDisabled(wrapper, SubmitButton).toBe(true);
+});
- click(getInner(wrapper).find('Button'));
- expect(getInner(wrapper)).toMatchSnapshot();
+it('should correctly reset the form', () => {
+ const component = mockComponent();
+ const wrapper = shallowRender({ component });
+ changeInput(wrapper, 'bar');
+ click(getForm(wrapper).find(Button));
+ expectProjectKeyInputValue(wrapper).toBe(component.key);
});
-function getInner(wrapper: ShallowWrapper) {
- // TODO find a better way to do this
+function getForm(wrapper: ShallowWrapper) {
+ // We're wrapper by a <ConfirmButton>. Dive twice to get the actual form.
return wrapper.dive().dive();
}
+
+function expectButtonDisabled(
+ wrapper: ShallowWrapper,
+ button: React.ComponentType<{ disabled?: boolean }>
+) {
+ return expect(
+ getForm(wrapper)
+ .find(button)
+ .props().disabled
+ );
+}
+
+function expectProjectKeyInputValue(wrapper: ShallowWrapper) {
+ return expect(
+ getForm(wrapper)
+ .find(ProjectKeyInput)
+ .props().projectKey
+ );
+}
+
+function changeInput(wrapper: ShallowWrapper, value: string) {
+ getForm(wrapper)
+ .find(ProjectKeyInput)
+ .props()
+ .onProjectKeyChange(mockEvent({ currentTarget: { value } }));
+}
+
+function shallowRender(props: Partial<UpdateFormProps> = {}) {
+ return shallow<UpdateFormProps>(
+ <UpdateForm component={mockComponent()} onKeyChange={jest.fn()} {...props} />
+ );
+}
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should render 1`] = `
-<Fragment>
- <form
- onSubmit={[Function]}
- >
- <input
- className="input-super-large"
- id="update-key-new-key"
- onChange={[Function]}
- placeholder="update_key.new_key"
- required={true}
- type="text"
- value="foo"
- />
- <div
- className="spacer-top"
- >
- <SubmitButton
- disabled={true}
- id="update-key-submit"
- >
- update_verb
- </SubmitButton>
- <Button
- className="spacer-left"
- disabled={true}
- id="update-key-reset"
- onClick={[Function]}
- type="reset"
- >
- reset_verb
- </Button>
- </div>
- </form>
-</Fragment>
-`;
-
-exports[`should render 2`] = `
-<Fragment>
- <form
- onSubmit={[Function]}
- >
- <input
- className="input-super-large"
- id="update-key-new-key"
- onChange={[Function]}
- placeholder="update_key.new_key"
- required={true}
- type="text"
- value="bar"
- />
- <div
- className="spacer-top"
- >
- <SubmitButton
- disabled={false}
- id="update-key-submit"
+exports[`should render: default 1`] = `
+<ConfirmButton
+ confirmButtonText="update_verb"
+ modalBody={
+ <React.Fragment>
+ update_key.are_you_sure_to_change_key.MyProject
+ <div
+ className="spacer-top"
>
- update_verb
- </SubmitButton>
- <Button
- className="spacer-left"
- disabled={false}
- id="update-key-reset"
- onClick={[Function]}
- type="reset"
+ update_key.old_key
+ :
+ <strong>
+ my-project
+ </strong>
+ </div>
+ <div
+ className="spacer-top"
>
- reset_verb
- </Button>
- </div>
- </form>
-</Fragment>
+ update_key.new_key
+ :
+ <strong />
+ </div>
+ </React.Fragment>
+ }
+ modalHeader="update_key.page"
+ onConfirm={[MockFunction]}
+>
+ <Component />
+</ConfirmButton>
`;
-exports[`should render 3`] = `
+exports[`should render: form 1`] = `
<Fragment>
<form
onSubmit={[Function]}
>
- <input
- className="input-super-large"
- id="update-key-new-key"
- onChange={[Function]}
+ <ProjectKeyInput
+ label="update_key.new_key"
+ onProjectKeyChange={[Function]}
placeholder="update_key.new_key"
- required={true}
- type="text"
- value="foo"
+ projectKey="my-project"
+ touched={false}
/>
<div
className="spacer-top"