Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Job import and export functional tests #110578

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
const [exporting, setExporting] = useState(false);
const [selectedJobType, setSelectedJobType] = useState<JobType>(currentTab);
const [switchTabConfirmVisible, setSwitchTabConfirmVisible] = useState(false);
const [switchTabNextTab, setSwitchTabNextTab] = useState<JobType>(currentTab);
const { displayErrorToast, displaySuccessToast } = useMemo(
() => toastNotificationServiceProvider(toasts),
[toasts]
Expand Down Expand Up @@ -170,27 +171,31 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
}
}

const attemptTabSwitch = useCallback(() => {
// if the user has already selected some jobs, open a confirm modal
// rather than changing tabs
if (selectedJobIds.length > 0) {
setSwitchTabConfirmVisible(true);
return;
}
const attemptTabSwitch = useCallback(
(jobType: JobType) => {
if (jobType === selectedJobType) {
return;
}
// if the user has already selected some jobs, open a confirm modal
// rather than changing tabs
if (selectedJobIds.length > 0) {
setSwitchTabNextTab(jobType);
setSwitchTabConfirmVisible(true);
return;
}

switchTab();
}, [selectedJobIds]);
switchTab(jobType);
},
[selectedJobIds]
);

useEffect(() => {
setSelectedJobDependencies(
jobDependencies.filter(({ jobId }) => selectedJobIds.includes(jobId))
);
}, [selectedJobIds]);

function switchTab() {
const jobType =
selectedJobType === 'anomaly-detector' ? 'data-frame-analytics' : 'anomaly-detector';

function switchTab(jobType: JobType) {
setSwitchTabConfirmVisible(false);
setSelectedJobIds([]);
setSelectedJobType(jobType);
Expand All @@ -211,7 +216,12 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {

{showFlyout === true && isDisabled === false && (
<>
<EuiFlyout onClose={() => setShowFlyout(false)} hideCloseButton size="s">
<EuiFlyout
onClose={() => setShowFlyout(false)}
hideCloseButton
size="s"
data-test-subj="mlJobMgmtExportJobsFlyout"
>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
Expand All @@ -227,8 +237,9 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
<EuiTabs size="s">
<EuiTab
isSelected={selectedJobType === 'anomaly-detector'}
onClick={attemptTabSwitch}
onClick={() => attemptTabSwitch('anomaly-detector')}
disabled={exporting}
data-test-subj="mlJobMgmtExportJobsADTab"
>
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.adTab"
Expand All @@ -237,8 +248,9 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
</EuiTab>
<EuiTab
isSelected={selectedJobType === 'data-frame-analytics'}
onClick={attemptTabSwitch}
onClick={() => attemptTabSwitch('data-frame-analytics')}
disabled={exporting}
data-test-subj="mlJobMgmtExportJobsDFATab"
>
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.dfaTab"
Expand All @@ -254,26 +266,40 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
<LoadingSpinner />
) : (
<>
<EuiButtonEmpty size="xs" onClick={onSelectAll} isDisabled={isDisabled}>
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.adSelectAllButton"
defaultMessage="Select all"
/>
<EuiButtonEmpty
size="xs"
onClick={onSelectAll}
isDisabled={isDisabled}
data-test-subj="mlJobMgmtExportJobsSelectAllButton"
>
{selectedJobIds.length === adJobIds.length ? (
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.adDeselectAllButton"
defaultMessage="Deselect all"
/>
) : (
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.adSelectAllButton"
defaultMessage="Select all"
/>
)}
</EuiButtonEmpty>

<EuiSpacer size="xs" />

{adJobIds.map((id) => (
<div key={id}>
<EuiCheckbox
id={id}
label={id}
checked={selectedJobIds.includes(id)}
onChange={(e) => toggleSelectedJob(e.target.checked, id)}
/>
<EuiSpacer size="s" />
</div>
))}
<div data-test-subj="mlJobMgmtExportJobsADJobList">
{adJobIds.map((id) => (
<div key={id}>
<EuiCheckbox
id={id}
label={id}
checked={selectedJobIds.includes(id)}
onChange={(e) => toggleSelectedJob(e.target.checked, id)}
/>
<EuiSpacer size="s" />
</div>
))}
</div>
</>
)}
</>
Expand All @@ -284,26 +310,39 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
<LoadingSpinner />
) : (
<>
<EuiButtonEmpty size="xs" onClick={onSelectAll} isDisabled={isDisabled}>
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.dfaSelectAllButton"
defaultMessage="Select all"
/>
<EuiButtonEmpty
size="xs"
onClick={onSelectAll}
isDisabled={isDisabled}
data-test-subj="mlJobMgmtExportJobsSelectAllButton"
>
{selectedJobIds.length === dfaJobIds.length ? (
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.dfaDeselectAllButton"
defaultMessage="Deselect all"
/>
) : (
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.dfaSelectAllButton"
defaultMessage="Select all"
/>
)}
</EuiButtonEmpty>

<EuiSpacer size="xs" />

{dfaJobIds.map((id) => (
<div key={id}>
<EuiCheckbox
id={id}
label={id}
checked={selectedJobIds.includes(id)}
onChange={(e) => toggleSelectedJob(e.target.checked, id)}
/>
<EuiSpacer size="s" />
</div>
))}
<div data-test-subj="mlJobMgmtExportJobsDFAJobList">
{dfaJobIds.map((id) => (
<div key={id}>
<EuiCheckbox
id={id}
label={id}
checked={selectedJobIds.includes(id)}
onChange={(e) => toggleSelectedJob(e.target.checked, id)}
/>
<EuiSpacer size="s" />
</div>
))}
</div>
</>
)}
</>
Expand All @@ -329,6 +368,7 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
disabled={selectedJobIds.length === 0 || exporting === true}
onClick={onExport}
fill
data-test-subj="mlJobMgmtExportExportButton"
>
<FormattedMessage
id="xpack.ml.importExport.exportFlyout.exportButton"
Expand All @@ -343,7 +383,7 @@ export const ExportJobsFlyout: FC<Props> = ({ isDisabled, currentTab }) => {
{switchTabConfirmVisible === true ? (
<SwitchTabsConfirm
onCancel={setSwitchTabConfirmVisible.bind(null, false)}
onConfirm={switchTab}
onConfirm={() => switchTab(switchTabNextTab)}
/>
) : null}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const CannotImportJobsCallout: FC<Props> = ({ jobs, autoExpand = false })
values: { num: jobs.length },
})}
color="warning"
data-test-subj="mlJobMgmtImportJobsCannotBeImportedCallout"
>
{autoExpand ? (
<SkippedJobList jobs={jobs} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ export const CannotReadFileCallout: FC = () => {
})}
color="warning"
>
<FormattedMessage
id="xpack.ml.importExport.importFlyout.cannotReadFileCallout.body"
defaultMessage="Please select a file contained Machine Learning jobs which have been exported from Kibana using the Export Jobs option"
/>
<div data-test-subj="mlJobMgmtImportJobsFileReadErrorCallout">
<FormattedMessage
id="xpack.ml.importExport.importFlyout.cannotReadFileCallout.body"
defaultMessage="Please select a file contained Machine Learning jobs which have been exported from Kibana using the Export Jobs option"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR, but noticed a typo in this message - should be containing not contained.

/>
</div>
</EuiCallOut>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,12 @@ export const ImportJobsFlyout: FC<Props> = ({ isDisabled }) => {
<FlyoutButton onClick={toggleFlyout} isDisabled={isDisabled} />

{showFlyout === true && isDisabled === false && (
<EuiFlyout onClose={setShowFlyout.bind(null, false)} hideCloseButton size="m">
<EuiFlyout
onClose={setShowFlyout.bind(null, false)}
hideCloseButton
size="m"
data-test-subj="mlJobMgmtImportJobsFlyout"
>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
Expand Down Expand Up @@ -373,22 +378,26 @@ export const ImportJobsFlyout: FC<Props> = ({ isDisabled }) => {
{showFileReadError ? <CannotReadFileCallout /> : null}

{totalJobsRead > 0 && jobType !== null && (
<>
<div data-test-subj="mlJobMgmtImportJobsFileRead">
<EuiSpacer size="l" />
{jobType === 'anomaly-detector' && (
<FormattedMessage
id="xpack.ml.importExport.importFlyout.selectedFiles.ad"
defaultMessage="{num} anomaly detection {num, plural, one {job} other {jobs}} read from file"
values={{ num: totalJobsRead }}
/>
<div data-test-subj="mlJobMgmtImportJobsADTitle">
<FormattedMessage
id="xpack.ml.importExport.importFlyout.selectedFiles.ad"
defaultMessage="{num} anomaly detection {num, plural, one {job} other {jobs}} read from file"
values={{ num: totalJobsRead }}
/>
</div>
)}

{jobType === 'data-frame-analytics' && (
<FormattedMessage
id="xpack.ml.importExport.importFlyout.selectedFiles.dfa"
defaultMessage="{num} data frame analytics {num, plural, one {job} other {jobs}} read from file"
values={{ num: totalJobsRead }}
/>
<div data-test-subj="mlJobMgmtImportJobsDFATitle">
<FormattedMessage
id="xpack.ml.importExport.importFlyout.selectedFiles.dfa"
defaultMessage="{num} data frame analytics {num, plural, one {job} other {jobs}} read from file"
values={{ num: totalJobsRead }}
/>
</div>
)}

<EuiSpacer size="m" />
Expand Down Expand Up @@ -426,6 +435,7 @@ export const ImportJobsFlyout: FC<Props> = ({ isDisabled }) => {
value={jobId.jobId}
onChange={(e) => renameJob(e.target.value, i)}
isInvalid={jobId.jobIdValid === false}
data-test-subj="mlJobMgmtImportJobIdInput"
/>
</EuiFormRow>

Expand Down Expand Up @@ -465,7 +475,7 @@ export const ImportJobsFlyout: FC<Props> = ({ isDisabled }) => {
<EuiSpacer size="m" />
</div>
))}
</>
</div>
)}
</>
</EuiFlyoutBody>
Expand All @@ -484,7 +494,12 @@ export const ImportJobsFlyout: FC<Props> = ({ isDisabled }) => {
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton disabled={importDisabled} onClick={onImport} fill>
<EuiButton
disabled={importDisabled}
onClick={onImport}
fill
data-test-subj="mlJobMgmtImportImportButton"
>
<FormattedMessage
id="xpack.ml.importExport.importFlyout.closeButton.importButton"
defaultMessage="Import"
Expand Down
Loading