Skip to content

Commit

Permalink
create pipeline tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alisonelizabeth committed Apr 28, 2020
1 parent 61a33e2 commit a00787e
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,21 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
]);
};

const setCreatePipelineResponse = (response?: object, error?: any) => {
const status = error ? error.status || 400 : 200;
const body = error ? JSON.stringify(error.body) : JSON.stringify(response);

server.respondWith('POST', API_BASE_PATH, [
status,
{ 'Content-Type': 'application/json' },
body,
]);
};

return {
setLoadPipelinesResponse,
setDeletePipelineResponse,
setCreatePipelineResponse,
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
*/

import { setup as ingestPipelinesListSetup } from './ingest_pipelines_list.helpers';
import { setup as pipelinesCreateSetup } from './pipelines_create.helpers';

export { nextTick, getRandomString, findTestSubject } from '../../../../../test_utils';

export { setupEnvironment } from './setup_environment';

export const pageHelpers = {
ingestPipelinesList: { setup: ingestPipelinesListSetup },
pipelinesCreate: { setup: pipelinesCreateSetup },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { TestBed, SetupFunc, UnwrapPromise } from '../../../../../test_utils';
import { nextTick } from './index';

export type TemplateFormTestBed = TestBed<PipelineFormTestSubjects> &
UnwrapPromise<ReturnType<typeof formSetup>>;

export const formSetup = async (initTestBed: SetupFunc<PipelineFormTestSubjects>) => {
const testBed = await initTestBed();

// User actions
const clickSubmitButton = () => {
testBed.find('submitButton').simulate('click');
};

const clickTestPipelineButton = () => {
testBed.find('testPipelineButton').simulate('click');
};

const clickShowRequestLink = () => {
testBed.find('showRequestLink').simulate('click');
};

const toggleVersionSwitch = () => {
testBed.form.toggleEuiSwitch('versionToggle');
};

const toggleOnFailureSwitch = () => {
testBed.form.toggleEuiSwitch('onFailureToggle');
};

const setEditorInputValue = async (testSubject: PipelineFormTestSubjects, value: string) => {
testBed.find(testSubject).simulate('change', {
jsonString: value,
});
await nextTick();
testBed.component.update();
};

return {
...testBed,
actions: {
clickSubmitButton,
setEditorInputValue,
clickShowRequestLink,
toggleVersionSwitch,
toggleOnFailureSwitch,
clickTestPipelineButton,
},
};
};

export type PipelineFormTestSubjects =
| 'submitButton'
| 'pageTitle'
| 'savePipelineError'
| 'pipelineForm'
| 'versionToggle'
| 'versionField'
| 'nameField.input'
| 'descriptionField.input'
| 'processorsField'
| 'onFailureToggle'
| 'onFailureEditor'
| 'testPipelineButton'
| 'showRequestLink'
| 'requestFlyout'
| 'requestFlyout.title'
| 'testPipelineFlyout'
| 'testPipelineFlyout.title'
| 'documentationLink';
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { registerTestBed, TestBedConfig } from '../../../../../test_utils';
import { BASE_PATH } from '../../../common/constants';
import { PipelinesCreate } from '../../../public/application/sections/pipelines_create'; // eslint-disable-line @kbn/eslint/no-restricted-paths
import { formSetup, PipelineFormTestSubjects } from './pipeline_form.helpers';
import { WithAppDependencies } from './setup_environment';

const testBedConfig: TestBedConfig = {
memoryRouter: {
initialEntries: [`${BASE_PATH}/create`],
componentRoutePath: `${BASE_PATH}/create`,
},
doMountAsync: true,
};

const initTestBed = registerTestBed<PipelineFormTestSubjects>(
WithAppDependencies(PipelinesCreate),
testBedConfig
);

export const setup = formSetup.bind(null, initTestBed);
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { act } from 'react-dom/test-utils';

import { setupEnvironment, pageHelpers, nextTick } from './helpers';
import { TemplateFormTestBed } from './helpers/pipeline_form.helpers';

const { setup } = pageHelpers.pipelinesCreate;

jest.mock('@elastic/eui', () => ({
...jest.requireActual('@elastic/eui'),
// Mocking EuiCodeEditor, which uses React Ace under the hood
EuiCodeEditor: (props: any) => (
<input
data-test-subj={props['data-test-subj']}
onChange={(syntheticEvent: any) => {
props.onChange(syntheticEvent.jsonString);
}}
/>
),
}));

describe('<PipelinesCreate />', () => {
let testBed: TemplateFormTestBed;

const { server, httpRequestsMockHelpers } = setupEnvironment();

afterAll(() => {
server.restore();
});

describe('on component mount', () => {
beforeEach(async () => {
await act(async () => {
testBed = await setup();
await testBed.waitFor('pipelineForm');
});
});

test('should render the correct page header', () => {
const { exists, find } = testBed;

// Verify page title
expect(exists('pageTitle')).toBe(true);
expect(find('pageTitle').text()).toEqual('Create pipeline');

// Verify documentation link
expect(exists('documentationLink')).toBe(true);
expect(find('documentationLink').text()).toBe('Create pipeline docs');
});

test('should toggle the version field', async () => {
const { actions, component, exists } = testBed;

// Version field should be hidden by default
expect(exists('versionField')).toBe(false);

await act(async () => {
actions.toggleVersionSwitch();
await nextTick();
component.update();
});

expect(exists('versionField')).toBe(true);
});

test('should toggle the on-failure processors editor', async () => {
const { actions, component, exists } = testBed;

// On-failure editor should be hidden by default
expect(exists('onFailureEditor')).toBe(false);

await act(async () => {
actions.toggleOnFailureSwitch();
await nextTick();
component.update();
});

expect(exists('onFailureEditor')).toBe(true);
});

test('should show the request flyout', async () => {
const { actions, component, find, exists } = testBed;

await act(async () => {
actions.clickShowRequestLink();
await nextTick();
component.update();
});

// Verify request flyout opens
expect(exists('requestFlyout')).toBe(true);
expect(find('requestFlyout.title').text()).toBe('Request');
});

describe('form validation', () => {
test('should prevent form submission if required fields are missing', async () => {
const { form, actions, component, find } = testBed;

await act(async () => {
actions.clickSubmitButton();
await nextTick();
component.update();
});

expect(form.getErrorsMessages()).toEqual([
'A pipeline name is required.',
'A pipeline description is required.',
]);
expect(find('submitButton').props().disabled).toEqual(true);

// Add required fields and verify button is enabled again
form.setInputValue('nameField.input', 'my_pipeline');
form.setInputValue('descriptionField.input', 'pipeline description');

await act(async () => {
await nextTick();
component.update();
});

expect(find('submitButton').props().disabled).toEqual(false);
});
});

describe('form submission', () => {
beforeEach(async () => {
await act(async () => {
testBed = await setup();

const { waitFor, form } = testBed;

await waitFor('pipelineForm');

form.setInputValue('nameField.input', 'my_pipeline');
form.setInputValue('descriptionField.input', 'pipeline description');
});
});

test('should send the correct payload', async () => {
const { actions } = testBed;

await act(async () => {
actions.clickSubmitButton();
await nextTick(100);
});

const latestRequest = server.requests[server.requests.length - 1];

const expected = {
name: 'my_pipeline',
description: 'pipeline description',
processors: [],
};

expect(JSON.parse(latestRequest.requestBody)).toEqual(expected);
});

test('should surface API errors from the request', async () => {
const { component, actions, find, exists } = testBed;

const error = {
status: 409,
error: 'Conflict',
message: `There is already a pipeline with name 'my_pipeline'.`,
};

httpRequestsMockHelpers.setCreatePipelineResponse(undefined, { body: error });

await act(async () => {
actions.clickSubmitButton();
await nextTick(100);
component.update();
});

expect(exists('savePipelineError')).toBe(true);
expect(find('savePipelineError').text()).toContain(error.message);
});
});

describe('test pipeline', () => {
beforeEach(async () => {
await act(async () => {
testBed = await setup();

const { waitFor } = testBed;

await waitFor('pipelineForm');
});
});

test('should open the test pipeline flyout', async () => {
const { actions, component, exists, find } = testBed;

await act(async () => {
actions.clickTestPipelineButton();
await nextTick();
component.update();
});

// Verify test pipeline flyout opens
expect(exists('testPipelineFlyout')).toBe(true);
expect(find('testPipelineFlyout.title').text()).toBe('Test pipeline');
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export const PipelineForm: React.FunctionComponent<PipelineFormProps> = ({
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
data-test-subj="showRequestLink"
onClick={() => setIsRequestVisible(prevIsRequestVisible => !prevIsRequestVisible)}
>
{isRequestVisible ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,12 @@ export const PipelineFormFields: React.FunctionComponent<Props> = ({

<EuiSpacer />

<EuiButton size="s" onClick={onTestPipelineClick} disabled={isTestButtonDisabled}>
<EuiButton
size="s"
onClick={onTestPipelineClick}
disabled={isTestButtonDisabled}
data-test-subj="testPipelineButton"
>
<FormattedMessage
id="xpack.ingestPipelines.form.testPipelineButtonLabel"
defaultMessage="Test pipeline"
Expand All @@ -149,8 +154,8 @@ export const PipelineFormFields: React.FunctionComponent<Props> = ({
path="processors"
component={JsonEditorField}
componentProps={{
['data-test-subj']: 'processorsField',
euiCodeEditorProps: {
['data-test-subj']: 'processorsField',
height: '300px',
'aria-label': i18n.translate('xpack.ingestPipelines.form.processorsFieldAriaLabel', {
defaultMessage: 'Processors JSON editor',
Expand Down Expand Up @@ -203,8 +208,8 @@ export const PipelineFormFields: React.FunctionComponent<Props> = ({
path="on_failure"
component={JsonEditorField}
componentProps={{
['data-test-subj']: 'onFailureEditor',
euiCodeEditorProps: {
['data-test-subj']: 'onFailureEditor',
height: '300px',
'aria-label': i18n.translate('xpack.ingestPipelines.form.onFailureFieldAriaLabel', {
defaultMessage: 'On-failure processors JSON editor',
Expand Down
Loading

0 comments on commit a00787e

Please sign in to comment.