Skip to content

Commit b25fdcf

Browse files
[Ingest pipelines] Add ability to stop pipeline simulation (#78183)
1 parent 1d48afc commit b25fdcf

File tree

23 files changed

+526
-322
lines changed

23 files changed

+526
-322
lines changed

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/test_pipeline.helpers.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,41 @@ const createActions = (testBed: TestBed<TestSubject>) => {
179179
});
180180
},
181181

182+
clickDocumentsDropdown() {
183+
act(() => {
184+
find('documentsDropdown.documentsButton').simulate('click');
185+
});
186+
component.update();
187+
},
188+
189+
clickEditDocumentsButton() {
190+
act(() => {
191+
find('editDocumentsButton').simulate('click');
192+
});
193+
component.update();
194+
},
195+
196+
clickClearAllButton() {
197+
act(() => {
198+
find('clearAllDocumentsButton').simulate('click');
199+
});
200+
component.update();
201+
},
202+
203+
async clickConfirmResetButton() {
204+
const modal = document.body.querySelector(
205+
'[data-test-subj="resetDocumentsConfirmationModal"]'
206+
);
207+
const confirmButton: HTMLButtonElement | null = modal!.querySelector(
208+
'[data-test-subj="confirmModalConfirmButton"]'
209+
);
210+
211+
await act(async () => {
212+
confirmButton!.click();
213+
});
214+
component.update();
215+
},
216+
182217
async clickProcessor(processorSelector: string) {
183218
await act(async () => {
184219
find(`${processorSelector}.manageItemButton`).simulate('click');
@@ -230,6 +265,7 @@ type TestSubject =
230265
| 'addDocumentsButton'
231266
| 'testPipelineFlyout'
232267
| 'documentsDropdown'
268+
| 'documentsDropdown.documentsButton'
233269
| 'outputTab'
234270
| 'documentsEditor'
235271
| 'runPipelineButton'
@@ -248,6 +284,8 @@ type TestSubject =
248284
| 'configurationTab'
249285
| 'outputTab'
250286
| 'processorOutputTabContent'
287+
| 'editDocumentsButton'
288+
| 'clearAllDocumentsButton'
251289
| 'addDocumentsAccordion'
252290
| 'addDocumentButton'
253291
| 'addDocumentError'

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/test_pipeline.test.tsx

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,27 @@ describe('Test pipeline', () => {
2222

2323
const { server, httpRequestsMockHelpers } = setupEnvironment();
2424

25+
// This is a hack
26+
// We need to provide the processor id in the mocked output;
27+
// this is generated dynamically
28+
// As a workaround, the value is added as a data attribute in the UI
29+
// and we retrieve it to generate the mocked output.
30+
const addProcessorTagtoMockOutput = (output: VerboseTestOutput) => {
31+
const { find } = testBed;
32+
33+
const docs = output.docs.map((doc) => {
34+
const results = doc.processor_results.map((result, index) => {
35+
const tag = find(`processors>${index}`).props()['data-processor-id'];
36+
return {
37+
...result,
38+
tag,
39+
};
40+
});
41+
return { processor_results: results };
42+
});
43+
return { docs };
44+
};
45+
2546
beforeAll(() => {
2647
jest.useFakeTimers();
2748
});
@@ -236,30 +257,77 @@ describe('Test pipeline', () => {
236257
expect(find('addDocumentError').text()).toContain(error.message);
237258
});
238259
});
239-
});
240260

241-
describe('Processors', () => {
242-
// This is a hack
243-
// We need to provide the processor id in the mocked output;
244-
// this is generated dynamically and not something we can stub.
245-
// As a workaround, the value is added as a data attribute in the UI
246-
// and we retrieve it to generate the mocked output.
247-
const addProcessorTagtoMockOutput = (output: VerboseTestOutput) => {
248-
const { find } = testBed;
261+
describe('Documents dropdown', () => {
262+
beforeEach(async () => {
263+
const { actions } = testBed;
249264

250-
const docs = output.docs.map((doc) => {
251-
const results = doc.processor_results.map((result, index) => {
252-
const tag = find(`processors>${index}`).props()['data-processor-id'];
253-
return {
254-
...result,
255-
tag,
256-
};
257-
});
258-
return { processor_results: results };
265+
httpRequestsMockHelpers.setSimulatePipelineResponse(
266+
addProcessorTagtoMockOutput(SIMULATE_RESPONSE)
267+
);
268+
269+
// Open flyout
270+
actions.clickAddDocumentsButton();
271+
// Add sample documents and click run
272+
actions.addDocumentsJson(JSON.stringify(DOCUMENTS));
273+
await actions.clickRunPipelineButton();
274+
// Close flyout
275+
actions.closeTestPipelineFlyout();
259276
});
260-
return { docs };
261-
};
262277

278+
it('should open flyout to edit documents', () => {
279+
const { exists, actions } = testBed;
280+
281+
// Dropdown should be visible
282+
expect(exists('documentsDropdown')).toBe(true);
283+
284+
// Open dropdown and edit documents
285+
actions.clickDocumentsDropdown();
286+
actions.clickEditDocumentsButton();
287+
288+
// Flyout should be visible with "Documents" tab enabled
289+
expect(exists('testPipelineFlyout')).toBe(true);
290+
expect(exists('documentsTabContent')).toBe(true);
291+
});
292+
293+
it('should clear all documents and stop pipeline simulation', async () => {
294+
const { exists, actions, find } = testBed;
295+
296+
// Dropdown should be visible and processor status should equal "success"
297+
expect(exists('documentsDropdown')).toBe(true);
298+
const initialProcessorStatusLabel = find('processors>0.processorStatusIcon').props()[
299+
'aria-label'
300+
];
301+
expect(initialProcessorStatusLabel).toEqual('Success');
302+
303+
// Open flyout and click clear all button
304+
actions.clickDocumentsDropdown();
305+
actions.clickEditDocumentsButton();
306+
actions.clickClearAllButton();
307+
308+
// Verify modal
309+
const modal = document.body.querySelector(
310+
'[data-test-subj="resetDocumentsConfirmationModal"]'
311+
);
312+
313+
expect(modal).not.toBe(null);
314+
expect(modal!.textContent).toContain('Clear documents');
315+
316+
// Confirm reset and close modal
317+
await actions.clickConfirmResetButton();
318+
319+
// Verify documents and processors were reset
320+
expect(exists('documentsDropdown')).toBe(false);
321+
expect(exists('addDocumentsButton')).toBe(true);
322+
const resetProcessorStatusIconLabel = find('processors>0.processorStatusIcon').props()[
323+
'aria-label'
324+
];
325+
expect(resetProcessorStatusIconLabel).toEqual('Not run');
326+
});
327+
});
328+
});
329+
330+
describe('Processors', () => {
263331
it('should show "inactive" processor status by default', async () => {
264332
const { find } = testBed;
265333

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processor_form/edit_processor_form.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export const EditProcessorForm: FunctionComponent<Props> = ({
102102
handleSubmit,
103103
resetProcessors,
104104
}) => {
105-
const { testPipelineData, setCurrentTestPipelineData } = useTestPipelineContext();
105+
const { testPipelineData, testPipelineDataDispatch } = useTestPipelineContext();
106106
const {
107107
testOutputPerProcessor,
108108
config: { selectedDocumentIndex, documents },
@@ -117,7 +117,7 @@ export const EditProcessorForm: FunctionComponent<Props> = ({
117117
testOutputPerProcessor[selectedDocumentIndex][processor.id];
118118

119119
const updateSelectedDocument = (index: number) => {
120-
setCurrentTestPipelineData({
120+
testPipelineDataDispatch({
121121
type: 'updateActiveDocument',
122122
payload: {
123123
config: {

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/test_pipeline/add_documents_button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { i18n } from '@kbn/i18n';
77
import React, { FunctionComponent } from 'react';
88
import { EuiButtonEmpty } from '@elastic/eui';
9-
import { TestPipelineFlyoutTab } from './test_pipeline_flyout_tabs';
9+
import { TestPipelineFlyoutTab } from './test_pipeline_tabs';
1010

1111
const i18nTexts = {
1212
buttonLabel: i18n.translate('xpack.ingestPipelines.pipelineEditor.testPipeline.buttonLabel', {

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/test_pipeline/documents_dropdown/documents_dropdown.tsx

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,15 @@ import React, { FunctionComponent, useState } from 'react';
88
import {
99
EuiButton,
1010
EuiPopover,
11+
EuiPopoverFooter,
1112
EuiButtonEmpty,
1213
EuiPopoverTitle,
1314
EuiSelectable,
14-
EuiHorizontalRule,
15-
EuiFlexGroup,
16-
EuiFlexItem,
17-
EuiSpacer,
1815
} from '@elastic/eui';
1916

2017
import { Document } from '../../../types';
2118

22-
import { TestPipelineFlyoutTab } from '../test_pipeline_flyout_tabs';
19+
import { TestPipelineFlyoutTab } from '../test_pipeline_tabs';
2320

2421
import './documents_dropdown.scss';
2522

@@ -31,9 +28,9 @@ const i18nTexts = {
3128
}
3229
),
3330
addDocumentsButtonLabel: i18n.translate(
34-
'xpack.ingestPipelines.pipelineEditor.testPipeline.documentsDropdown.buttonLabel',
31+
'xpack.ingestPipelines.pipelineEditor.testPipeline.documentsDropdown.editDocumentsButtonLabel',
3532
{
36-
defaultMessage: 'Add documents',
33+
defaultMessage: 'Edit documents',
3734
}
3835
),
3936
popoverTitle: i18n.translate(
@@ -88,8 +85,10 @@ export const DocumentsDropdown: FunctionComponent<Props> = ({
8885
>
8986
<EuiSelectable
9087
singleSelection
88+
data-test-subj="documentList"
9189
options={documents.map((doc, index) => ({
9290
key: index.toString(),
91+
'data-test-subj': 'documentListItem',
9392
checked: selectedDocumentIndex === index ? 'on' : undefined,
9493
label: i18n.translate('xpack.ingestPipelines.pipelineEditor.testPipeline.documentLabel', {
9594
defaultMessage: 'Document {documentNumber}',
@@ -107,32 +106,27 @@ export const DocumentsDropdown: FunctionComponent<Props> = ({
107106
setShowPopover(false);
108107
}}
109108
>
110-
{(list, search) => (
111-
<div>
109+
{(list) => (
110+
<>
112111
<EuiPopoverTitle>{i18nTexts.popoverTitle}</EuiPopoverTitle>
113112
{list}
114-
</div>
113+
</>
115114
)}
116115
</EuiSelectable>
117116

118-
<EuiHorizontalRule margin="xs" />
119-
120-
<EuiFlexGroup justifyContent="center">
121-
<EuiFlexItem grow={false}>
122-
<EuiButton
123-
size="s"
124-
onClick={() => {
125-
openFlyout('documents');
126-
setShowPopover(false);
127-
}}
128-
data-test-subj="addDocumentsButton"
129-
>
130-
{i18nTexts.addDocumentsButtonLabel}
131-
</EuiButton>
132-
</EuiFlexItem>
133-
</EuiFlexGroup>
134-
135-
<EuiSpacer size="s" />
117+
<EuiPopoverFooter>
118+
<EuiButton
119+
size="s"
120+
fullWidth
121+
onClick={() => {
122+
openFlyout('documents');
123+
setShowPopover(false);
124+
}}
125+
data-test-subj="editDocumentsButton"
126+
>
127+
{i18nTexts.addDocumentsButtonLabel}
128+
</EuiButton>
129+
</EuiPopoverFooter>
136130
</EuiPopover>
137131
);
138132
};

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/test_pipeline/test_output_button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { i18n } from '@kbn/i18n';
77
import React, { FunctionComponent } from 'react';
88
import { EuiButton } from '@elastic/eui';
9-
import { TestPipelineFlyoutTab } from './test_pipeline_flyout_tabs';
9+
import { TestPipelineFlyoutTab } from './test_pipeline_tabs';
1010

1111
const i18nTexts = {
1212
buttonLabel: i18n.translate(

x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/test_pipeline/test_pipeline_actions.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
99

1010
import { useTestPipelineContext, usePipelineProcessorsContext } from '../../context';
1111
import { DocumentsDropdown } from './documents_dropdown';
12-
import { TestPipelineFlyoutTab } from './test_pipeline_flyout_tabs';
12+
import { TestPipelineFlyoutTab } from './test_pipeline_tabs';
1313
import { AddDocumentsButton } from './add_documents_button';
1414
import { TestOutputButton } from './test_output_button';
1515
import { TestPipelineFlyout } from './test_pipeline_flyout.container';
@@ -24,7 +24,7 @@ const i18nTexts = {
2424
};
2525

2626
export const TestPipelineActions: FunctionComponent = () => {
27-
const { testPipelineData, setCurrentTestPipelineData } = useTestPipelineContext();
27+
const { testPipelineData, testPipelineDataDispatch } = useTestPipelineContext();
2828

2929
const {
3030
state: { processors },
@@ -39,7 +39,7 @@ export const TestPipelineActions: FunctionComponent = () => {
3939
const [activeFlyoutTab, setActiveFlyoutTab] = useState<TestPipelineFlyoutTab>('documents');
4040

4141
const updateSelectedDocument = (index: number) => {
42-
setCurrentTestPipelineData({
42+
testPipelineDataDispatch({
4343
type: 'updateActiveDocument',
4444
payload: {
4545
config: {

0 commit comments

Comments
 (0)