import { BranchParameters } from '../types/branch-like';
import { QualityGateApplicationStatus, QualityGateProjectStatus } from '../types/quality-gates';
-export function fetchQualityGates(data?: {
- organization?: string;
-}): Promise<{
+export function fetchQualityGates(): Promise<{
actions: { create: boolean };
qualitygates: T.QualityGate[];
}> {
- return getJSON('/api/qualitygates/list', data).catch(throwGlobalError);
+ return getJSON('/api/qualitygates/list').catch(throwGlobalError);
}
-export function fetchQualityGate(data: {
- id: number | string;
- organization?: string;
-}): Promise<T.QualityGate> {
+export function fetchQualityGate(data: { id: number | string }): Promise<T.QualityGate> {
return getJSON('/api/qualitygates/show', data).catch(throwGlobalError);
}
-export function createQualityGate(data: {
- name: string;
- organization?: string;
-}): Promise<T.QualityGate> {
+export function createQualityGate(data: { name: string }): Promise<T.QualityGate> {
return postJSON('/api/qualitygates/create', data).catch(throwGlobalError);
}
-export function deleteQualityGate(data: {
- id: string;
- organization?: string;
-}): Promise<void | Response> {
+export function deleteQualityGate(data: { id: string }): Promise<void | Response> {
return post('/api/qualitygates/destroy', data).catch(throwGlobalError);
}
-export function renameQualityGate(data: {
- id: string;
- name: string;
- organization?: string;
-}): Promise<void | Response> {
+export function renameQualityGate(data: { id: string; name: string }): Promise<void | Response> {
return post('/api/qualitygates/rename', data).catch(throwGlobalError);
}
-export function copyQualityGate(data: {
- id: string;
- name: string;
- organization?: string;
-}): Promise<T.QualityGate> {
+export function copyQualityGate(data: { id: string; name: string }): Promise<T.QualityGate> {
return postJSON('/api/qualitygates/copy', data).catch(throwGlobalError);
}
-export function setQualityGateAsDefault(data: {
- id: string;
- organization?: string;
-}): Promise<void | Response> {
+export function setQualityGateAsDefault(data: { id: string }): Promise<void | Response> {
return post('/api/qualitygates/set_as_default', data).catch(throwGlobalError);
}
export function createCondition(
data: {
gateId: string;
- organization?: string;
} & T.Omit<T.Condition, 'id'>
): Promise<T.Condition> {
return postJSON('/api/qualitygates/create_condition', data).catch(throwGlobalError);
}
-export function updateCondition(
- data: { organization?: string } & T.Condition
-): Promise<T.Condition> {
+export function updateCondition(data: T.Condition): Promise<T.Condition> {
return postJSON('/api/qualitygates/update_condition', data).catch(throwGlobalError);
}
-export function deleteCondition(data: { id: number; organization?: string }): Promise<void> {
+export function deleteCondition(data: { id: number }): Promise<void> {
return post('/api/qualitygates/delete_condition', data);
}
-export function getGateForProject(data: {
- organization?: string;
- project: string;
-}): Promise<T.QualityGate | undefined> {
+export function getGateForProject(data: { project: string }): Promise<T.QualityGate | undefined> {
return getJSON('/api/qualitygates/get_by_project', data).then(
({ qualityGate }) =>
qualityGate && {
export function searchProjects(data: {
gateName: string;
- organization?: string;
page?: number;
pageSize?: number;
query?: string;
export function associateGateWithProject(data: {
gateId: string;
- organization?: string;
projectKey: string;
}): Promise<void | Response> {
return post('/api/qualitygates/select', data).catch(throwGlobalError);
export function dissociateGateWithProject(data: {
gateId: string;
- organization?: string;
projectKey: string;
}): Promise<void | Response> {
return post('/api/qualitygates/deselect', data).catch(throwGlobalError);
export function getApplicationQualityGate(data: {
application: string;
branch?: string;
- organization?: string;
}): Promise<QualityGateApplicationStatus> {
return getJSON('/api/qualitygates/application_status', data).catch(throwGlobalError);
}
import List from './List';
import ListHeader from './ListHeader';
-interface Props extends WithRouterProps {
- organization?: Pick<T.Organization, 'key'>;
-}
-
interface State {
canCreate: boolean;
loading: boolean;
qualityGates: T.QualityGate[];
}
-class App extends React.PureComponent<Props, State> {
+class App extends React.PureComponent<WithRouterProps, State> {
mounted = false;
state: State = { canCreate: false, loading: true, qualityGates: [] };
addSideBarClass();
}
- componentDidUpdate(prevProps: Props) {
+ componentDidUpdate(prevProps: WithRouterProps) {
if (prevProps.params.id !== undefined && this.props.params.id === undefined) {
this.openDefault(this.state.qualityGates);
}
}
fetchQualityGates = () => {
- const { organization } = this.props;
- return fetchQualityGates({ organization: organization && organization.key }).then(
+ return fetchQualityGates().then(
({ actions, qualitygates: qualityGates }) => {
if (this.mounted) {
this.setState({ canCreate: actions.create, loading: false, qualityGates });
const { id } = this.props.params;
const { canCreate, qualityGates } = this.state;
const defaultTitle = translate('quality_gates.page');
- const organization = this.props.organization && this.props.organization.key;
return (
<>
<div className="layout-page-filters">
<ListHeader
canCreate={canCreate}
- organization={organization}
refreshQualityGates={this.fetchQualityGates}
/>
<DeferredSpinner loading={this.state.loading}>
<Details
id={id}
onSetDefault={this.handleSetDefault}
- organization={organization}
qualityGates={this.state.qualityGates}
refreshQualityGates={this.fetchQualityGates}
/>
condition: T.Condition;
canEdit: boolean;
metric: T.Metric;
- organization?: string;
onRemoveCondition: (Condition: T.Condition) => void;
onSaveCondition: (newCondition: T.Condition, oldCondition: T.Condition) => void;
qualityGate: T.QualityGate;
};
removeCondition = (condition: T.Condition) => {
- deleteCondition({ id: condition.id, organization: this.props.organization }).then(
+ deleteCondition({ id: condition.id }).then(
() => this.props.onRemoveCondition(condition),
() => {}
);
}
render() {
- const { condition, canEdit, metric, organization, qualityGate, updated } = this.props;
+ const { condition, canEdit, metric, qualityGate, updated } = this.props;
return (
<tr className={classNames({ highlighted: updated })}>
<td className="text-middle">
metric={metric}
onAddCondition={this.handleUpdateCondition}
onClose={this.handleUpdateClose}
- organization={organization}
qualityGate={qualityGate}
/>
)}
header: string;
onAddCondition: (condition: T.Condition) => void;
onClose: () => void;
- organization?: string;
qualityGate: T.QualityGate;
}
handleFormSubmit = () => {
if (this.state.metric) {
- const { condition, qualityGate, organization } = this.props;
+ const { condition, qualityGate } = this.props;
const newCondition: T.Omit<T.Condition, 'id'> = {
metric: this.state.metric.key,
op: this.getSinglePossibleOperator(this.state.metric) || this.state.op,
error: this.state.error
};
const submitPromise = condition
- ? updateCondition({ organization, id: condition.id, ...newCondition })
- : createCondition({ gateId: qualityGate.id, organization, ...newCondition });
+ ? updateCondition({ id: condition.id, ...newCondition })
+ : createCondition({ gateId: qualityGate.id, ...newCondition });
return submitPromise.then(this.props.onAddCondition);
}
return Promise.reject();
onAddCondition: (condition: T.Condition) => void;
onRemoveCondition: (Condition: T.Condition) => void;
onSaveCondition: (newCondition: T.Condition, oldCondition: T.Condition) => void;
- organization?: string;
qualityGate: T.QualityGate;
updatedConditionId?: number;
}
canEdit,
onRemoveCondition,
onSaveCondition,
- organization,
updatedConditionId
} = this.props;
return (
metric={metrics[condition.metric]}
onRemoveCondition={onRemoveCondition}
onSaveCondition={onSaveCondition}
- organization={organization}
qualityGate={qualityGate}
updated={condition.id === updatedConditionId}
/>
metrics={availableMetrics}
onAddCondition={this.props.onAddCondition}
onClose={onClose}
- organization={this.props.organization}
qualityGate={this.props.qualityGate}
/>
)}>
interface Props {
onClose: () => void;
onCopy: () => Promise<void>;
- organization?: string;
qualityGate: T.QualityGate;
router: Pick<Router, 'push'>;
}
name: string;
}
-class CopyQualityGateForm extends React.PureComponent<Props, State> {
+export class CopyQualityGateForm extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = { name: props.qualityGate.name };
};
handleCopy = () => {
- const { qualityGate, organization } = this.props;
+ const { qualityGate } = this.props;
const { name } = this.state;
if (!name) {
return undefined;
}
- return copyQualityGate({ id: qualityGate.id, name, organization }).then(qualityGate => {
+ return copyQualityGate({ id: qualityGate.id, name }).then(qualityGate => {
this.props.onCopy();
this.props.router.push(getQualityGateUrl(String(qualityGate.id)));
});
interface Props {
onClose: () => void;
onCreate: () => Promise<void>;
- organization?: string;
router: Pick<Router, 'push'>;
}
};
handleCreate = () => {
- const { organization } = this.props;
const { name } = this.state;
if (!name) {
return undefined;
}
- return createQualityGate({ name, organization })
+ return createQualityGate({ name })
.then(qualityGate => {
return this.props.onCreate().then(() => qualityGate);
})
interface Props {
onDelete: () => Promise<void>;
- organization?: string;
qualityGate: T.QualityGate;
router: Pick<Router, 'push'>;
}
-class DeleteQualityGateForm extends React.PureComponent<Props> {
+export class DeleteQualityGateForm extends React.PureComponent<Props> {
onDelete = () => {
- const { organization, qualityGate } = this.props;
- return deleteQualityGate({ id: qualityGate.id, organization })
+ const { qualityGate } = this.props;
+ return deleteQualityGate({ id: qualityGate.id })
.then(this.props.onDelete)
.then(() => {
this.props.router.push(getQualityGatesUrl());
interface OwnProps {
id: string;
onSetDefault: (qualityGate: T.QualityGate) => void;
- organization?: string;
qualityGates: T.QualityGate[];
refreshQualityGates: () => Promise<void>;
}
}
fetchDetails = () => {
- const { id, organization } = this.props;
+ const { id } = this.props;
this.setState({ loading: true });
- return fetchQualityGate({ id, organization }).then(
+ return fetchQualityGate({ id }).then(
qualityGate => {
if (this.mounted) {
this.setState({ loading: false, qualityGate, updatedConditionId: undefined });
};
render() {
- const { organization, metrics, refreshQualityGates } = this.props;
+ const { metrics, refreshQualityGates } = this.props;
const { loading, qualityGate, updatedConditionId } = this.state;
return (
<Helmet defer={false} title={qualityGate.name} />
<DetailsHeader
onSetDefault={this.handleSetDefault}
- organization={organization}
qualityGate={qualityGate}
refreshItem={this.fetchDetails}
refreshList={refreshQualityGates}
onAddCondition={this.handleAddCondition}
onRemoveCondition={this.handleRemoveCondition}
onSaveCondition={this.handleSaveCondition}
- organization={organization}
qualityGate={qualityGate}
updatedConditionId={updatedConditionId}
/>
export interface DetailsContentProps {
isDefault?: boolean;
metrics: T.Dict<T.Metric>;
- organization?: string;
onAddCondition: (condition: T.Condition) => void;
onRemoveCondition: (Condition: T.Condition) => void;
onSaveCondition: (newCondition: T.Condition, oldCondition: T.Condition) => void;
}
export function DetailsContent(props: DetailsContentProps) {
- const { isDefault, metrics, organization, qualityGate, updatedConditionId } = props;
+ const { isDefault, metrics, qualityGate, updatedConditionId } = props;
const conditions = qualityGate.conditions || [];
const actions = qualityGate.actions || ({} as any);
onAddCondition={props.onAddCondition}
onRemoveCondition={props.onRemoveCondition}
onSaveCondition={props.onSaveCondition}
- organization={organization}
qualityGate={qualityGate}
updatedConditionId={updatedConditionId}
/>
canEdit={actions.associateProjects}
// pass unique key to re-mount the component when the quality gate changes
key={qualityGate.id}
- organization={organization}
qualityGate={qualityGate}
/>
)}
interface Props {
onSetDefault: () => void;
- organization?: string;
qualityGate: T.QualityGate;
refreshItem: () => Promise<void>;
refreshList: () => Promise<void>;
};
handleSetAsDefaultClick = () => {
- const { organization, qualityGate } = this.props;
+ const { qualityGate } = this.props;
if (!qualityGate.isDefault) {
// Optimistic update
this.props.onSetDefault();
- setQualityGateAsDefault({ id: qualityGate.id, organization }).then(
+ setQualityGateAsDefault({ id: qualityGate.id }).then(
this.handleActionRefresh,
this.handleActionRefresh
);
};
render() {
- const { organization, qualityGate } = this.props;
+ const { qualityGate } = this.props;
const actions = qualityGate.actions || ({} as any);
return (
<div className="layout-page-header-panel layout-page-main-header issues-main-header">
<RenameQualityGateForm
onClose={onClose}
onRename={this.handleActionRefresh}
- organization={organization}
qualityGate={qualityGate}
/>
)}>
<CopyQualityGateForm
onClose={onClose}
onCopy={this.handleActionRefresh}
- organization={organization}
qualityGate={qualityGate}
/>
)}>
{actions.delete && (
<DeleteQualityGateForm
onDelete={this.props.refreshList}
- organization={organization}
qualityGate={qualityGate}
/>
)}
interface Props {
canCreate: boolean;
refreshQualityGates: () => Promise<void>;
- organization?: string;
}
-export default function ListHeader({ canCreate, refreshQualityGates, organization }: Props) {
+export default function ListHeader({ canCreate, refreshQualityGates }: Props) {
return (
<header className="page-header">
{canCreate && (
<div className="page-actions">
<ModalButton
modal={({ onClose }) => (
- <CreateQualityGateForm
- onClose={onClose}
- onCreate={refreshQualityGates}
- organization={organization}
- />
+ <CreateQualityGateForm onClose={onClose} onCreate={refreshQualityGates} />
)}>
{({ onClick }) => (
<Button data-test="quality-gates__add" onClick={onClick}>
interface Props {
canEdit?: boolean;
- organization?: string;
qualityGate: T.QualityGate;
}
fetchProjects = (searchParams: SelectListSearchParams) =>
searchProjects({
gateName: this.props.qualityGate.name,
- organization: this.props.organization,
page: searchParams.page,
pageSize: searchParams.pageSize,
query: searchParams.query !== '' ? searchParams.query : undefined,
handleSelect = (key: string) =>
associateGateWithProject({
gateId: this.props.qualityGate.id,
- organization: this.props.organization,
projectKey: key
}).then(() => {
if (this.mounted) {
handleUnselect = (key: string) =>
dissociateGateWithProject({
gateId: this.props.qualityGate.id,
- organization: this.props.organization,
projectKey: key
}).then(() => {
if (this.mounted) {
interface Props {
onClose: () => void;
onRename: () => Promise<void>;
- organization?: string;
qualityGate: T.QualityGate;
}
};
handleRename = () => {
- const { qualityGate, organization } = this.props;
+ const { qualityGate } = this.props;
const { name } = this.state;
if (!name) {
return undefined;
}
- return renameQualityGate({ id: qualityGate.id, name, organization }).then(() =>
- this.props.onRename()
- );
+ return renameQualityGate({ id: qualityGate.id, name }).then(() => this.props.onRename());
};
render() {
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { createCondition, updateCondition } from '../../../../api/quality-gates';
import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
-import { mockMetric } from '../../../../helpers/testMocks';
+import { mockCondition, mockMetric } from '../../../../helpers/testMocks';
import { MetricKey } from '../../../../types/metrics';
import ConditionModal from '../ConditionModal';
+jest.mock('../../../../api/quality-gates', () => ({
+ createCondition: jest.fn().mockResolvedValue({}),
+ updateCondition: jest.fn().mockResolvedValue({})
+}));
+
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot();
expect(shallowRender({ metric: mockMetric() })).toMatchSnapshot();
expect(wrapper).toMatchSnapshot();
});
+it('should handle submission', async () => {
+ const onAddCondition = jest.fn();
+ const wrapper = shallowRender({ onAddCondition });
+
+ wrapper.setState({ metric: mockMetric() });
+
+ await wrapper.instance().handleFormSubmit();
+
+ expect(createCondition).toBeCalled();
+ expect(updateCondition).not.toBeCalled();
+
+ jest.clearAllMocks();
+
+ wrapper.setProps({ condition: mockCondition() });
+ await wrapper.instance().handleFormSubmit();
+
+ expect(createCondition).not.toBeCalled();
+ expect(updateCondition).toBeCalled();
+});
+
function shallowRender(props: Partial<ConditionModal['props']> = {}) {
return shallow<ConditionModal>(
<ConditionModal
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { copyQualityGate } from '../../../../api/quality-gates';
import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
-import CopyQualityGateForm from '../CopyQualityGateForm';
+import { mockRouter } from '../../../../helpers/testMocks';
+import { CopyQualityGateForm } from '../CopyQualityGateForm';
+
+jest.mock('../../../../api/quality-gates', () => ({
+ copyQualityGate: jest.fn().mockResolvedValue({})
+}));
it('should render correctly', () => {
- expect(
- shallow(
- <CopyQualityGateForm onClose={jest.fn()} onCopy={jest.fn()} qualityGate={mockQualityGate()} />
- )
- ).toMatchSnapshot();
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should handle copy', async () => {
+ const onCopy = jest.fn();
+ const router = mockRouter();
+ const qualityGate = mockQualityGate();
+ const wrapper = shallowRender({ onCopy, qualityGate, router });
+
+ const name = 'name';
+ wrapper.setState({ name });
+
+ await wrapper.instance().handleCopy();
+
+ expect(copyQualityGate).toBeCalledWith({ id: qualityGate.id, name });
+ expect(onCopy).toBeCalled();
+ expect(router.push).toBeCalled();
+
+ jest.clearAllMocks();
+
+ wrapper.setState({ name: '' });
+ await wrapper.instance().handleCopy();
+
+ expect(copyQualityGate).not.toBeCalled();
});
+
+function shallowRender(overrides: Partial<CopyQualityGateForm['props']> = {}) {
+ return shallow<CopyQualityGateForm>(
+ <CopyQualityGateForm
+ onClose={jest.fn()}
+ onCopy={jest.fn()}
+ qualityGate={mockQualityGate()}
+ router={mockRouter()}
+ {...overrides}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { deleteQualityGate } from '../../../../api/quality-gates';
+import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
+import { mockRouter } from '../../../../helpers/testMocks';
+import { DeleteQualityGateForm } from '../DeleteQualityGateForm';
+
+jest.mock('../../../../api/quality-gates', () => ({
+ deleteQualityGate: jest.fn().mockResolvedValue({})
+}));
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should handle onDelete', async () => {
+ const onDelete = jest.fn();
+ const router = mockRouter();
+ const qualityGate = mockQualityGate();
+ const wrapper = shallowRender({ onDelete, qualityGate, router });
+
+ await wrapper.instance().onDelete();
+
+ expect(deleteQualityGate).toBeCalledWith({ id: qualityGate.id });
+ expect(onDelete).toBeCalled();
+ expect(router.push).toBeCalled();
+});
+
+function shallowRender(overrides: Partial<DeleteQualityGateForm['props']> = {}) {
+ return shallow<DeleteQualityGateForm>(
+ <DeleteQualityGateForm
+ onDelete={jest.fn()}
+ qualityGate={mockQualityGate()}
+ router={mockRouter()}
+ {...overrides}
+ />
+ );
+}
import Projects from '../Projects';
const qualityGate = mockQualityGate();
-const organization = 'TEST';
jest.mock('../../../../api/quality-gates', () => ({
searchProjects: jest.fn().mockResolvedValue({
expect(searchProjects).toHaveBeenCalledWith(
expect.objectContaining({
gateName: qualityGate.name,
- organization,
page: 1,
pageSize: 100,
query: undefined,
});
function shallowRender(props: Partial<Projects['props']> = {}) {
- return shallow<Projects>(
- <Projects organization={organization} qualityGate={qualityGate} {...props} />
- );
+ return shallow<Projects>(<Projects qualityGate={qualityGate} {...props} />);
}
*/
import { shallow } from 'enzyme';
import * as React from 'react';
+import { renameQualityGate } from '../../../../api/quality-gates';
import { mockQualityGate } from '../../../../helpers/mocks/quality-gates';
import RenameQualityGateForm from '../RenameQualityGateForm';
+jest.mock('../../../../api/quality-gates', () => ({
+ renameQualityGate: jest.fn().mockResolvedValue({})
+}));
+
it('should render correctly', () => {
- expect(
- shallow(
- <RenameQualityGateForm
- onClose={jest.fn()}
- onRename={jest.fn()}
- qualityGate={mockQualityGate()}
- />
- )
- ).toMatchSnapshot();
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should handle rename', async () => {
+ const qualityGate = mockQualityGate();
+ const wrapper = shallowRender({ qualityGate });
+
+ const name = 'new name';
+
+ wrapper.setState({ name });
+
+ await wrapper.instance().handleRename();
+
+ expect(renameQualityGate).toBeCalledWith({ ...qualityGate, name });
+
+ jest.clearAllMocks();
+
+ wrapper.setState({ name: '' });
+
+ await wrapper.instance().handleRename();
+
+ expect(renameQualityGate).not.toBeCalled();
});
+
+function shallowRender(overrides: Partial<RenameQualityGateForm['props']> = {}) {
+ return shallow<RenameQualityGateForm>(
+ <RenameQualityGateForm
+ onClose={jest.fn()}
+ onRename={jest.fn()}
+ qualityGate={mockQualityGate()}
+ {...overrides}
+ />
+ );
+}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render correctly 1`] = `
-<CopyQualityGateForm
+<ConfirmModal
+ confirmButtonText="copy"
+ confirmDisable={true}
+ header="quality_gates.copy"
onClose={[MockFunction]}
- onCopy={[MockFunction]}
- qualityGate={
- Object {
- "id": "1",
- "name": "qualitygate",
- }
- }
-/>
+ onConfirm={[Function]}
+ size="small"
+>
+ <div
+ className="modal-field"
+ >
+ <label
+ htmlFor="quality-gate-form-name"
+ >
+ name
+ <em
+ className="mandatory"
+ >
+ *
+ </em>
+ </label>
+ <input
+ autoFocus={true}
+ id="quality-gate-form-name"
+ maxLength={100}
+ onChange={[Function]}
+ required={true}
+ size={50}
+ type="text"
+ value="qualitygate"
+ />
+ </div>
+</ConfirmModal>
`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<ConfirmButton
+ confirmButtonText="delete"
+ isDestructive={true}
+ modalBody="quality_gates.delete.confirm.message.qualitygate"
+ modalHeader="quality_gates.delete"
+ onConfirm={[Function]}
+>
+ <Component />
+</ConfirmButton>
+`;