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

[Ingest pipelines] Add ability to stop pipeline simulation #78183

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,41 @@ const createActions = (testBed: TestBed<TestSubject>) => {
});
},

clickDocumentsDropdown() {
act(() => {
find('documentsDropdown.documentsButton').simulate('click');
});
component.update();
},

clickEditDocumentsButton() {
act(() => {
find('editDocumentsButton').simulate('click');
});
component.update();
},

clickClearAllButton() {
act(() => {
find('clearAllDocumentsButton').simulate('click');
});
component.update();
},

async clickConfirmResetButton() {
const modal = document.body.querySelector(
'[data-test-subj="resetDocumentsConfirmationModal"]'
);
const confirmButton: HTMLButtonElement | null = modal!.querySelector(
'[data-test-subj="confirmModalConfirmButton"]'
);

await act(async () => {
confirmButton!.click();
});
component.update();
},

async clickProcessor(processorSelector: string) {
await act(async () => {
find(`${processorSelector}.manageItemButton`).simulate('click');
Expand Down Expand Up @@ -230,6 +265,7 @@ type TestSubject =
| 'addDocumentsButton'
| 'testPipelineFlyout'
| 'documentsDropdown'
| 'documentsDropdown.documentsButton'
| 'outputTab'
| 'documentsEditor'
| 'runPipelineButton'
Expand All @@ -248,6 +284,8 @@ type TestSubject =
| 'configurationTab'
| 'outputTab'
| 'processorOutputTabContent'
| 'editDocumentsButton'
| 'clearAllDocumentsButton'
| 'addDocumentsAccordion'
| 'addDocumentButton'
| 'addDocumentError'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,27 @@ describe('Test pipeline', () => {

const { server, httpRequestsMockHelpers } = setupEnvironment();

// This is a hack
// We need to provide the processor id in the mocked output;
// this is generated dynamically
// As a workaround, the value is added as a data attribute in the UI
// and we retrieve it to generate the mocked output.
const addProcessorTagtoMockOutput = (output: VerboseTestOutput) => {
const { find } = testBed;

const docs = output.docs.map((doc) => {
const results = doc.processor_results.map((result, index) => {
const tag = find(`processors>${index}`).props()['data-processor-id'];
return {
...result,
tag,
};
});
return { processor_results: results };
});
return { docs };
};

beforeAll(() => {
jest.useFakeTimers();
});
Expand Down Expand Up @@ -236,30 +257,77 @@ describe('Test pipeline', () => {
expect(find('addDocumentError').text()).toContain(error.message);
});
});
});

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

const docs = output.docs.map((doc) => {
const results = doc.processor_results.map((result, index) => {
const tag = find(`processors>${index}`).props()['data-processor-id'];
return {
...result,
tag,
};
});
return { processor_results: results };
httpRequestsMockHelpers.setSimulatePipelineResponse(
addProcessorTagtoMockOutput(SIMULATE_RESPONSE)
);

// Open flyout
actions.clickAddDocumentsButton();
// Add sample documents and click run
actions.addDocumentsJson(JSON.stringify(DOCUMENTS));
await actions.clickRunPipelineButton();
// Close flyout
actions.closeTestPipelineFlyout();
});
return { docs };
};

it('should open flyout to edit documents', () => {
const { exists, actions } = testBed;

// Dropdown should be visible
expect(exists('documentsDropdown')).toBe(true);

// Open dropdown and edit documents
actions.clickDocumentsDropdown();
actions.clickEditDocumentsButton();

// Flyout should be visible with "Documents" tab enabled
expect(exists('testPipelineFlyout')).toBe(true);
expect(exists('documentsTabContent')).toBe(true);
});

it('should clear all documents and stop pipeline simulation', async () => {
const { exists, actions, find } = testBed;

// Dropdown should be visible and processor status should equal "success"
expect(exists('documentsDropdown')).toBe(true);
const initialProcessorStatusLabel = find('processors>0.processorStatusIcon').props()[
'aria-label'
];
expect(initialProcessorStatusLabel).toEqual('Success');

// Open flyout and click clear all button
actions.clickDocumentsDropdown();
actions.clickEditDocumentsButton();
actions.clickClearAllButton();

// Verify modal
const modal = document.body.querySelector(
'[data-test-subj="resetDocumentsConfirmationModal"]'
);

expect(modal).not.toBe(null);
expect(modal!.textContent).toContain('Clear documents');

// Confirm reset and close modal
await actions.clickConfirmResetButton();

// Verify documents and processors were reset
expect(exists('documentsDropdown')).toBe(false);
expect(exists('addDocumentsButton')).toBe(true);
const resetProcessorStatusIconLabel = find('processors>0.processorStatusIcon').props()[
'aria-label'
];
expect(resetProcessorStatusIconLabel).toEqual('Not run');
});
});
});

describe('Processors', () => {
it('should show "inactive" processor status by default', async () => {
const { find } = testBed;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export const EditProcessorForm: FunctionComponent<Props> = ({
handleSubmit,
resetProcessors,
}) => {
const { testPipelineData, setCurrentTestPipelineData } = useTestPipelineContext();
const { testPipelineData, testPipelineDataDispatch } = useTestPipelineContext();
const {
testOutputPerProcessor,
config: { selectedDocumentIndex, documents },
Expand All @@ -117,7 +117,7 @@ export const EditProcessorForm: FunctionComponent<Props> = ({
testOutputPerProcessor[selectedDocumentIndex][processor.id];

const updateSelectedDocument = (index: number) => {
setCurrentTestPipelineData({
testPipelineDataDispatch({
type: 'updateActiveDocument',
payload: {
config: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
import React, { FunctionComponent } from 'react';
import { EuiButtonEmpty } from '@elastic/eui';
import { TestPipelineFlyoutTab } from './test_pipeline_flyout_tabs';
import { TestPipelineFlyoutTab } from './test_pipeline_tabs';

const i18nTexts = {
buttonLabel: i18n.translate('xpack.ingestPipelines.pipelineEditor.testPipeline.buttonLabel', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {

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

import { TestPipelineFlyoutTab } from '../test_pipeline_flyout_tabs';
import { TestPipelineFlyoutTab } from '../test_pipeline_tabs';

import './documents_dropdown.scss';

Expand All @@ -31,9 +31,9 @@ const i18nTexts = {
}
),
addDocumentsButtonLabel: i18n.translate(
'xpack.ingestPipelines.pipelineEditor.testPipeline.documentsDropdown.buttonLabel',
'xpack.ingestPipelines.pipelineEditor.testPipeline.documentsDropdown.editDocumentsButtonLabel',
{
defaultMessage: 'Add documents',
defaultMessage: 'Edit documents',
}
),
popoverTitle: i18n.translate(
Expand Down Expand Up @@ -88,8 +88,10 @@ export const DocumentsDropdown: FunctionComponent<Props> = ({
>
<EuiSelectable
singleSelection
data-test-subj="documentList"
options={documents.map((doc, index) => ({
key: index.toString(),
'data-test-subj': 'documentListItem',
checked: selectedDocumentIndex === index ? 'on' : undefined,
label: i18n.translate('xpack.ingestPipelines.pipelineEditor.testPipeline.documentLabel', {
defaultMessage: 'Document {documentNumber}',
Expand All @@ -107,25 +109,27 @@ export const DocumentsDropdown: FunctionComponent<Props> = ({
setShowPopover(false);
}}
>
{(list, search) => (
<div>
{(list) => (
<>
<EuiPopoverTitle>{i18nTexts.popoverTitle}</EuiPopoverTitle>
{list}
</div>
</>
)}
</EuiSelectable>

<EuiHorizontalRule margin="xs" />

<EuiFlexGroup justifyContent="center">
<EuiSpacer size="s" />

<EuiFlexGroup justifyContent="center" gutterSize="xs">
<EuiFlexItem grow={false}>
<EuiButton
size="s"
onClick={() => {
openFlyout('documents');
setShowPopover(false);
}}
data-test-subj="addDocumentsButton"
data-test-subj="editDocumentsButton"
>
{i18nTexts.addDocumentsButtonLabel}
</EuiButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
import React, { FunctionComponent } from 'react';
import { EuiButton } from '@elastic/eui';
import { TestPipelineFlyoutTab } from './test_pipeline_flyout_tabs';
import { TestPipelineFlyoutTab } from './test_pipeline_tabs';

const i18nTexts = {
buttonLabel: i18n.translate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';

import { useTestPipelineContext, usePipelineProcessorsContext } from '../../context';
import { DocumentsDropdown } from './documents_dropdown';
import { TestPipelineFlyoutTab } from './test_pipeline_flyout_tabs';
import { TestPipelineFlyoutTab } from './test_pipeline_tabs';
import { AddDocumentsButton } from './add_documents_button';
import { TestOutputButton } from './test_output_button';
import { TestPipelineFlyout } from './test_pipeline_flyout.container';
Expand All @@ -24,7 +24,7 @@ const i18nTexts = {
};

export const TestPipelineActions: FunctionComponent = () => {
const { testPipelineData, setCurrentTestPipelineData } = useTestPipelineContext();
const { testPipelineData, testPipelineDataDispatch } = useTestPipelineContext();

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

const updateSelectedDocument = (index: number) => {
setCurrentTestPipelineData({
testPipelineDataDispatch({
type: 'updateActiveDocument',
payload: {
config: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import { Document } from '../../types';
import { useIsMounted } from '../../use_is_mounted';
import { TestPipelineFlyout as ViewComponent } from './test_pipeline_flyout';

import { TestPipelineFlyoutTab } from './test_pipeline_flyout_tabs';
import { documentsSchema } from './test_pipeline_flyout_tabs/documents_schema';
import { TestPipelineFlyoutTab } from './test_pipeline_tabs';

export interface Props {
activeTab: TestPipelineFlyoutTab;
Expand All @@ -39,7 +38,7 @@ export const TestPipelineFlyout: React.FunctionComponent<Props> = ({

const {
testPipelineData,
setCurrentTestPipelineData,
testPipelineDataDispatch,
updateTestOutputPerProcessor,
} = useTestPipelineContext();

Expand All @@ -48,7 +47,6 @@ export const TestPipelineFlyout: React.FunctionComponent<Props> = ({
} = testPipelineData;

const { form } = useForm({
schema: documentsSchema,
defaultValue: {
documents: cachedDocuments || '',
},
Expand Down Expand Up @@ -88,7 +86,7 @@ export const TestPipelineFlyout: React.FunctionComponent<Props> = ({
// reset the per-processor output
// this is needed in the scenario where the pipeline has already executed,
// but you modified the sample documents and there was an error on re-execution
setCurrentTestPipelineData({
testPipelineDataDispatch({
type: 'updateOutputPerProcessor',
payload: {
isExecutingPipeline: false,
Expand All @@ -99,7 +97,7 @@ export const TestPipelineFlyout: React.FunctionComponent<Props> = ({
return { isSuccessful: false };
}

setCurrentTestPipelineData({
testPipelineDataDispatch({
type: 'updateConfig',
payload: {
config: {
Expand Down Expand Up @@ -133,7 +131,7 @@ export const TestPipelineFlyout: React.FunctionComponent<Props> = ({
processors,
services.api,
services.notifications.toasts,
setCurrentTestPipelineData,
testPipelineDataDispatch,
updateTestOutputPerProcessor,
]
);
Expand All @@ -157,6 +155,12 @@ export const TestPipelineFlyout: React.FunctionComponent<Props> = ({
}
};

const resetTestOutput = () => {
testPipelineDataDispatch({
type: 'reset',
});
};

useEffect(() => {
if (cachedDocuments && activeTab === 'output') {
handleTestPipeline({ documents: cachedDocuments, verbose: cachedVerbose }, true);
Expand All @@ -169,6 +173,7 @@ export const TestPipelineFlyout: React.FunctionComponent<Props> = ({
return (
<ViewComponent
handleTestPipeline={handleTestPipeline}
resetTestOutput={resetTestOutput}
isRunningTest={isRunningTest}
cachedVerbose={cachedVerbose}
cachedDocuments={cachedDocuments}
Expand Down
Loading