mirror of
https://github.com/ansible/awx.git
synced 2026-02-28 00:08:44 -03:30
Merge pull request #6229 from AlexSCorey/5895-SurveyListToolbar
Adds SurveyList tool bar Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -74,6 +74,14 @@ class JobTemplates extends SchedulesMixin(
|
|||||||
readSurvey(id) {
|
readSurvey(id) {
|
||||||
return this.http.get(`${this.baseUrl}${id}/survey_spec/`);
|
return this.http.get(`${this.baseUrl}${id}/survey_spec/`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSurvey(id, survey = null) {
|
||||||
|
return this.http.post(`${this.baseUrl}${id}/survey_spec/`, survey);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroySurvey(id) {
|
||||||
|
return this.http.delete(`${this.baseUrl}${id}/survey_spec/`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JobTemplates;
|
export default JobTemplates;
|
||||||
|
|||||||
@@ -1,48 +1,227 @@
|
|||||||
import React, { useEffect, useCallback } from 'react';
|
import React, { useEffect, useCallback, useState } from 'react';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
|
||||||
|
import useRequest, { useDeleteItems } from '@util/useRequest';
|
||||||
|
import { Button } from '@patternfly/react-core';
|
||||||
|
|
||||||
import useRequest from '@util/useRequest';
|
|
||||||
import ContentError from '@components/ContentError';
|
import ContentError from '@components/ContentError';
|
||||||
import ContentLoading from '@components/ContentLoading';
|
import ContentLoading from '@components/ContentLoading';
|
||||||
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
import { JobTemplatesAPI } from '@api';
|
import { JobTemplatesAPI } from '@api';
|
||||||
|
import ContentEmpty from '@components/ContentEmpty';
|
||||||
|
import { getQSConfig } from '@util/qs';
|
||||||
|
import AlertModal from '@components/AlertModal';
|
||||||
import SurveyListItem from './SurveyListItem';
|
import SurveyListItem from './SurveyListItem';
|
||||||
|
import SurveyToolbar from './SurveyToolbar';
|
||||||
|
|
||||||
|
const QS_CONFIG = getQSConfig('survey', {
|
||||||
|
page: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
function SurveyList({ template, i18n }) {
|
||||||
|
const [selected, setSelected] = useState([]);
|
||||||
|
const [surveyEnabled, setSurveyEnabled] = useState(template.survey_enabled);
|
||||||
|
const [showToggleError, setShowToggleError] = useState(false);
|
||||||
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
|
|
||||||
function SurveyList({ template }) {
|
|
||||||
const {
|
const {
|
||||||
result: questions,
|
result: { questions, name, description },
|
||||||
error: contentError,
|
error: contentError,
|
||||||
isLoading,
|
isLoading,
|
||||||
request: fetchSurvey,
|
request: fetchSurvey,
|
||||||
} = useRequest(
|
} = useRequest(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const {
|
const {
|
||||||
data: { spec },
|
data: { spec = [], description: surveyDescription, name: surveyName },
|
||||||
} = await JobTemplatesAPI.readSurvey(template.id);
|
} = await JobTemplatesAPI.readSurvey(template.id);
|
||||||
|
return {
|
||||||
return spec.map((s, index) => ({ ...s, id: index }));
|
questions: spec.map((s, index) => ({ ...s, id: index })),
|
||||||
}, [template.id])
|
description: surveyDescription,
|
||||||
|
name: surveyName,
|
||||||
|
};
|
||||||
|
}, [template.id]),
|
||||||
|
{ questions: [], name: '', description: '' }
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchSurvey();
|
fetchSurvey();
|
||||||
}, [fetchSurvey]);
|
}, [fetchSurvey]);
|
||||||
if (contentError) {
|
|
||||||
return <ContentError error={contentError} />;
|
|
||||||
}
|
|
||||||
if (isLoading) {
|
|
||||||
return <ContentLoading />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
const isAllSelected =
|
||||||
questions?.length > 0 &&
|
selected.length === questions?.length && selected.length > 0;
|
||||||
questions.map((question, index) => (
|
|
||||||
|
const {
|
||||||
|
isLoading: isDeleteLoading,
|
||||||
|
deleteItems: deleteQuestions,
|
||||||
|
deletionError,
|
||||||
|
clearDeletionError,
|
||||||
|
} = useDeleteItems(
|
||||||
|
useCallback(async () => {
|
||||||
|
if (isAllSelected) {
|
||||||
|
return JobTemplatesAPI.destroySurvey(template.id);
|
||||||
|
}
|
||||||
|
const surveyQuestions = [];
|
||||||
|
questions.forEach(q => {
|
||||||
|
if (!selected.some(s => s.id === q.id)) {
|
||||||
|
surveyQuestions.push(q);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return JobTemplatesAPI.updateSurvey(template.id, {
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
spec: surveyQuestions,
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [selected]),
|
||||||
|
{
|
||||||
|
qsConfig: QS_CONFIG,
|
||||||
|
fetchItems: fetchSurvey,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const {
|
||||||
|
isToggleLoading,
|
||||||
|
error: toggleError,
|
||||||
|
request: toggleSurvey,
|
||||||
|
} = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
|
await JobTemplatesAPI.update(template.id, {
|
||||||
|
survey_enabled: !surveyEnabled,
|
||||||
|
});
|
||||||
|
return setSurveyEnabled(!surveyEnabled);
|
||||||
|
}, [template, surveyEnabled]),
|
||||||
|
template.survey_enabled
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (toggleError) {
|
||||||
|
setShowToggleError(true);
|
||||||
|
}
|
||||||
|
}, [toggleError]);
|
||||||
|
|
||||||
|
const handleSelectAll = isSelected => {
|
||||||
|
setSelected(isSelected ? [...questions] : []);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelect = item => {
|
||||||
|
if (selected.some(s => s.id === item.id)) {
|
||||||
|
setSelected(selected.filter(s => s.id !== item.id));
|
||||||
|
} else {
|
||||||
|
setSelected(selected.concat(item));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
await deleteQuestions();
|
||||||
|
setIsDeleteModalOpen(false);
|
||||||
|
setSelected([]);
|
||||||
|
};
|
||||||
|
const canEdit = template.summary_fields.user_capabilities.edit;
|
||||||
|
const canDelete = template.summary_fields.user_capabilities.delete;
|
||||||
|
|
||||||
|
let content;
|
||||||
|
if (isLoading || isToggleLoading || isDeleteLoading) {
|
||||||
|
content = <ContentLoading />;
|
||||||
|
} else if (contentError) {
|
||||||
|
content = <ContentError error={contentError} />;
|
||||||
|
} else if (!questions || questions?.length <= 0) {
|
||||||
|
content = (
|
||||||
|
<ContentEmpty
|
||||||
|
title={i18n._(t`No Survey Questions Found`)}
|
||||||
|
message={i18n._(t`Please add survey questions.`)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
content = questions?.map((question, index) => (
|
||||||
<SurveyListItem
|
<SurveyListItem
|
||||||
key={question.id}
|
key={question.id}
|
||||||
isLast={index === questions.length - 1}
|
isLast={index === questions.length - 1}
|
||||||
isFirst={index === 0}
|
isFirst={index === 0}
|
||||||
question={question}
|
question={question}
|
||||||
|
isChecked={selected.some(s => s.id === question.id)}
|
||||||
|
onSelect={() => handleSelect(question)}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SurveyToolbar
|
||||||
|
isAllSelected={isAllSelected}
|
||||||
|
onSelectAll={handleSelectAll}
|
||||||
|
surveyEnabled={surveyEnabled}
|
||||||
|
onToggleSurvey={toggleSurvey}
|
||||||
|
isDeleteDisabled={selected?.length === 0 || !canEdit || !canDelete}
|
||||||
|
onToggleDeleteModal={() => setIsDeleteModalOpen(true)}
|
||||||
|
/>
|
||||||
|
{content}
|
||||||
|
{isDeleteModalOpen && (
|
||||||
|
<AlertModal
|
||||||
|
variant="danger"
|
||||||
|
title={
|
||||||
|
isAllSelected
|
||||||
|
? i18n._(t`Delete Survey`)
|
||||||
|
: i18n._(t`Delete Questions`)
|
||||||
|
}
|
||||||
|
isOpen={isDeleteModalOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsDeleteModalOpen(false);
|
||||||
|
setSelected([]);
|
||||||
|
}}
|
||||||
|
actions={[
|
||||||
|
<Button
|
||||||
|
key="delete"
|
||||||
|
variant="danger"
|
||||||
|
aria-label={i18n._(t`confirm delete`)}
|
||||||
|
onClick={handleDelete}
|
||||||
|
>
|
||||||
|
{i18n._(t`Delete`)}
|
||||||
|
</Button>,
|
||||||
|
<Button
|
||||||
|
key="cancel"
|
||||||
|
variant="secondary"
|
||||||
|
aria-label={i18n._(t`cancel delete`)}
|
||||||
|
onClick={() => {
|
||||||
|
setIsDeleteModalOpen(false);
|
||||||
|
setSelected([]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n._(t`Cancel`)}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<div>{i18n._(t`This action will delete the following:`)}</div>
|
||||||
|
{selected.map(question => (
|
||||||
|
<span key={question.id}>
|
||||||
|
<strong>{question.question_name}</strong>
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</AlertModal>
|
||||||
|
)}
|
||||||
|
{deletionError && (
|
||||||
|
<AlertModal
|
||||||
|
isOpen={deletionError}
|
||||||
|
variant="error"
|
||||||
|
title={i18n._(t`Error!`)}
|
||||||
|
onClose={clearDeletionError}
|
||||||
|
>
|
||||||
|
{i18n._(t`Failed to delete one or more jobs.`)}
|
||||||
|
<ErrorDetail error={deletionError} />
|
||||||
|
</AlertModal>
|
||||||
|
)}
|
||||||
|
{toggleError && (
|
||||||
|
<AlertModal
|
||||||
|
variant="error"
|
||||||
|
title={i18n._(t`Error!`)}
|
||||||
|
isOpen={showToggleError && !isLoading}
|
||||||
|
onClose={() => setShowToggleError(false)}
|
||||||
|
>
|
||||||
|
{i18n._(t`Failed to toggle host.`)}
|
||||||
|
<ErrorDetail error={toggleError} />
|
||||||
|
</AlertModal>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withI18n()(SurveyList);
|
export default withI18n()(SurveyList);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
import SurveyList from './SurveyList';
|
import SurveyList from './SurveyList';
|
||||||
import { JobTemplatesAPI } from '@api';
|
import { JobTemplatesAPI } from '@api';
|
||||||
import mockJobTemplateData from './data.job_template.json';
|
import mockJobTemplateData from './data.job_template.json';
|
||||||
@@ -10,7 +10,11 @@ jest.mock('@api/models/JobTemplates');
|
|||||||
describe('<SurveyList />', () => {
|
describe('<SurveyList />', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
JobTemplatesAPI.readSurvey.mockResolvedValue({
|
JobTemplatesAPI.readSurvey.mockResolvedValue({
|
||||||
data: { spec: [{ question_name: 'Foo', type: 'text', default: 'Bar' }] },
|
data: {
|
||||||
|
name: 'Survey',
|
||||||
|
description: 'description for survey',
|
||||||
|
spec: [{ question_name: 'Foo', type: 'text', default: 'Bar' }],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
test('expect component to mount successfully', async () => {
|
test('expect component to mount successfully', async () => {
|
||||||
@@ -30,6 +34,7 @@ describe('<SurveyList />', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
expect(JobTemplatesAPI.readSurvey).toBeCalledWith(7);
|
expect(JobTemplatesAPI.readSurvey).toBeCalledWith(7);
|
||||||
|
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('SurveyListItem').length).toBe(1);
|
expect(wrapper.find('SurveyListItem').length).toBe(1);
|
||||||
});
|
});
|
||||||
@@ -41,7 +46,91 @@ describe('<SurveyList />', () => {
|
|||||||
<SurveyList template={{ ...mockJobTemplateData, id: 'a' }} />
|
<SurveyList template={{ ...mockJobTemplateData, id: 'a' }} />
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
|
|
||||||
expect(wrapper.find('ContentError').length).toBe(1);
|
expect(wrapper.find('ContentError').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
test('can toggle survey on and off', async () => {
|
||||||
|
JobTemplatesAPI.update.mockResolvedValue();
|
||||||
|
let wrapper;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<SurveyList
|
||||||
|
template={{ ...mockJobTemplateData, survey_enabled: false }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.find('Switch').length).toBe(1);
|
||||||
|
expect(wrapper.find('Switch').prop('isChecked')).toBe(false);
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('Switch').invoke('onChange')(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.update();
|
||||||
|
|
||||||
|
expect(wrapper.find('Switch').prop('isChecked')).toBe(true);
|
||||||
|
expect(JobTemplatesAPI.update).toBeCalledWith(7, {
|
||||||
|
survey_enabled: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('selectAll enables delete button and calls the api to delete properly', async () => {
|
||||||
|
let wrapper;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<SurveyList
|
||||||
|
template={{ ...mockJobTemplateData, survey_enabled: false }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await waitForElement(wrapper, 'SurveyListItem');
|
||||||
|
expect(wrapper.find('Button[variant="danger"]').prop('isDisabled')).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
wrapper.find('Checkbox[aria-label="Select all"]').prop('isChecked')
|
||||||
|
).toBe(false);
|
||||||
|
act(() => {
|
||||||
|
wrapper.find('Checkbox[aria-label="Select all"]').invoke('onChange')(
|
||||||
|
{ target: { checked: true } },
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.update();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
wrapper.find('Checkbox[aria-label="Select all"]').prop('isChecked')
|
||||||
|
).toBe(true);
|
||||||
|
|
||||||
|
expect(wrapper.find('Button[variant="danger"]').prop('isDisabled')).toBe(
|
||||||
|
false
|
||||||
|
);
|
||||||
|
act(() => {
|
||||||
|
wrapper.find('Button[variant="danger"]').invoke('onClick')();
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.update();
|
||||||
|
|
||||||
|
await act(() =>
|
||||||
|
wrapper.find('Button[aria-label="confirm delete"]').invoke('onClick')()
|
||||||
|
);
|
||||||
|
expect(JobTemplatesAPI.destroySurvey).toBeCalledWith(7);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Survey with no questions', () => {
|
||||||
|
test('Survey with no questions renders empty state', async () => {
|
||||||
|
JobTemplatesAPI.readSurvey.mockResolvedValue({});
|
||||||
|
let wrapper;
|
||||||
|
await act(async () => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<SurveyList template={mockJobTemplateData} />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(wrapper.find('ContentEmpty').length).toBe(1);
|
||||||
|
expect(wrapper.find('SurveyListItem').length).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,11 +28,18 @@ const Button = styled(_Button)`
|
|||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
`;
|
`;
|
||||||
function SurveyListItem({ question, i18n, isLast, isFirst }) {
|
function SurveyListItem({
|
||||||
|
question,
|
||||||
|
i18n,
|
||||||
|
isLast,
|
||||||
|
isFirst,
|
||||||
|
isChecked,
|
||||||
|
onSelect,
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<DataList aria-label={i18n._(t`Survey List`)}>
|
<DataList aria-label={i18n._(t`Survey List`)}>
|
||||||
<DataListItem aria-labelledby={i18n._(t`Survey questions`)}>
|
<DataListItem aria-labelledby={i18n._(t`Survey questions`)}>
|
||||||
<DataListItemRow>
|
<DataListItemRow css="padding-left:16px">
|
||||||
<DataListAction
|
<DataListAction
|
||||||
id="sortQuestions"
|
id="sortQuestions"
|
||||||
aria-labelledby={i18n._(t`Sort question order`)}
|
aria-labelledby={i18n._(t`Sort question order`)}
|
||||||
@@ -59,7 +66,11 @@ function SurveyListItem({ question, i18n, isLast, isFirst }) {
|
|||||||
</StackItem>
|
</StackItem>
|
||||||
</Stack>
|
</Stack>
|
||||||
</DataListAction>
|
</DataListAction>
|
||||||
<DataListCheck checked={false} aria-labelledby="survey check" />
|
<DataListCheck
|
||||||
|
checked={isChecked}
|
||||||
|
onChange={onSelect}
|
||||||
|
aria-labelledby="survey check"
|
||||||
|
/>
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key={question.question_name}>
|
<DataListCell key={question.question_name}>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
|||||||
import SurveyListItem from './SurveyListItem';
|
import SurveyListItem from './SurveyListItem';
|
||||||
|
|
||||||
describe('<SurveyListItem />', () => {
|
describe('<SurveyListItem />', () => {
|
||||||
const item = { question_name: 'Foo', default: 'Bar', type: 'text' };
|
const item = { question_name: 'Foo', default: 'Bar', type: 'text', id: 1 };
|
||||||
test('renders successfully', () => {
|
test('renders successfully', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
act(() => {
|
act(() => {
|
||||||
@@ -32,7 +32,7 @@ describe('<SurveyListItem />', () => {
|
|||||||
let wrapper;
|
let wrapper;
|
||||||
act(() => {
|
act(() => {
|
||||||
wrapper = mountWithContexts(
|
wrapper = mountWithContexts(
|
||||||
<SurveyListItem question={item} isFirst isLast />
|
<SurveyListItem question={item} isChecked={false} isFirst isLast />
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const moveUp = wrapper
|
const moveUp = wrapper
|
||||||
|
|||||||
65
awx/ui_next/src/screens/Template/shared/SurveyToolbar.jsx
Normal file
65
awx/ui_next/src/screens/Template/shared/SurveyToolbar.jsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { withI18n } from '@lingui/react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
DataToolbar,
|
||||||
|
DataToolbarContent,
|
||||||
|
DataToolbarGroup,
|
||||||
|
DataToolbarItem,
|
||||||
|
} from '@patternfly/react-core/dist/umd/experimental';
|
||||||
|
import { Switch, Checkbox, Button } from '@patternfly/react-core';
|
||||||
|
import { ToolbarAddButton } from '@components/PaginatedDataList';
|
||||||
|
|
||||||
|
function SurveyToolbar({
|
||||||
|
isAllSelected,
|
||||||
|
onSelectAll,
|
||||||
|
i18n,
|
||||||
|
surveyEnabled,
|
||||||
|
onToggleSurvey,
|
||||||
|
isDeleteDisabled,
|
||||||
|
onToggleDeleteModal,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<DataToolbar id="survey-toolbar">
|
||||||
|
<DataToolbarContent>
|
||||||
|
<DataToolbarItem>
|
||||||
|
<Checkbox
|
||||||
|
isChecked={isAllSelected}
|
||||||
|
onChange={isChecked => {
|
||||||
|
onSelectAll(isChecked);
|
||||||
|
}}
|
||||||
|
aria-label={i18n._(t`Select all`)}
|
||||||
|
id="select-all"
|
||||||
|
/>
|
||||||
|
</DataToolbarItem>
|
||||||
|
<DataToolbarItem>
|
||||||
|
<Switch
|
||||||
|
aria-label={i18n._(t`Survey Toggle`)}
|
||||||
|
id="survey-toggle"
|
||||||
|
label={i18n._(t`On`)}
|
||||||
|
labelOff={i18n._(t`Off`)}
|
||||||
|
isChecked={surveyEnabled}
|
||||||
|
onChange={() => onToggleSurvey(!surveyEnabled)}
|
||||||
|
/>
|
||||||
|
</DataToolbarItem>
|
||||||
|
<DataToolbarGroup>
|
||||||
|
<DataToolbarItem>
|
||||||
|
<ToolbarAddButton linkTo="/" />
|
||||||
|
</DataToolbarItem>
|
||||||
|
<DataToolbarItem>
|
||||||
|
<Button
|
||||||
|
variant="danger"
|
||||||
|
isDisabled={isDeleteDisabled}
|
||||||
|
onClick={() => onToggleDeleteModal(true)}
|
||||||
|
>
|
||||||
|
{i18n._(t`Delete`)}
|
||||||
|
</Button>
|
||||||
|
</DataToolbarItem>
|
||||||
|
</DataToolbarGroup>
|
||||||
|
</DataToolbarContent>
|
||||||
|
</DataToolbar>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withI18n()(SurveyToolbar);
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import SurveyToolbar from './SurveyToolbar';
|
||||||
|
|
||||||
|
jest.mock('@api/models/JobTemplates');
|
||||||
|
|
||||||
|
describe('<SurveyToolbar />', () => {
|
||||||
|
test('delete Button is disabled', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<SurveyToolbar
|
||||||
|
isDeleteDisabled
|
||||||
|
onSelectAll={jest.fn()}
|
||||||
|
isAllSelected
|
||||||
|
onToggleDeleteModal={jest.fn()}
|
||||||
|
onToggleSurvey={jest.fn()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.find('Button[variant="danger"]').prop('isDisabled')).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('delete Button is enabled', () => {
|
||||||
|
let wrapper;
|
||||||
|
act(() => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<SurveyToolbar
|
||||||
|
isDeleteDisabled={false}
|
||||||
|
onSelectAll={jest.fn()}
|
||||||
|
isAllSelected
|
||||||
|
onToggleDeleteModal={jest.fn()}
|
||||||
|
onToggleSurvey={jest.fn()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
wrapper.find('Checkbox[aria-label="Select all"]').prop('isChecked')
|
||||||
|
).toBe(true);
|
||||||
|
expect(wrapper.find('Button[variant="danger"]').prop('isDisabled')).toBe(
|
||||||
|
false
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('switch is off', () => {
|
||||||
|
let wrapper;
|
||||||
|
act(() => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<SurveyToolbar
|
||||||
|
surveyEnabled={false}
|
||||||
|
isDeleteDisabled={false}
|
||||||
|
onSelectAll={jest.fn()}
|
||||||
|
isAllSelected
|
||||||
|
onToggleDelete={jest.fn()}
|
||||||
|
onToggleSurvey={jest.fn()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.find('Switch').length).toBe(1);
|
||||||
|
expect(wrapper.find('Switch').prop('isChecked')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('switch is on', () => {
|
||||||
|
let wrapper;
|
||||||
|
act(() => {
|
||||||
|
wrapper = mountWithContexts(
|
||||||
|
<SurveyToolbar
|
||||||
|
surveyEnabled
|
||||||
|
isDeleteDisabled={false}
|
||||||
|
onSelectAll={jest.fn()}
|
||||||
|
isAllSelected
|
||||||
|
onToggleDelete={jest.fn()}
|
||||||
|
onToggleSurvey={jest.fn()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.find('Switch').length).toBe(1);
|
||||||
|
expect(wrapper.find('Switch').prop('isChecked')).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user