Skip to content

Commit

Permalink
[Component template] Details flyout (#68732)
Browse files Browse the repository at this point in the history
  • Loading branch information
alisonelizabeth authored Jun 17, 2020
1 parent ca9a162 commit a34a3a7
Show file tree
Hide file tree
Showing 29 changed files with 1,044 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*
* 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 { act } from 'react-dom/test-utils';

import { setupEnvironment, pageHelpers } from './helpers';
import { ComponentTemplateDetailsTestBed } from './helpers/component_template_details.helpers';
import { ComponentTemplateDeserialized } from '../../shared_imports';

const { setup } = pageHelpers.componentTemplateDetails;

jest.mock('ui/i18n', () => {
const I18nContext = ({ children }: any) => children;
return { I18nContext };
});

const COMPONENT_TEMPLATE: ComponentTemplateDeserialized = {
name: 'comp-1',
template: {
mappings: { properties: { ip_address: { type: 'ip' } } },
aliases: { mydata: {} },
settings: { number_of_shards: 1 },
},
version: 1,
_meta: { description: 'component template test' },
_kbnMeta: { usedBy: ['template_1'] },
};

const COMPONENT_TEMPLATE_ONLY_REQUIRED_FIELDS: ComponentTemplateDeserialized = {
name: 'comp-base',
template: {},
_kbnMeta: { usedBy: [] },
};

describe('<ComponentTemplateDetails />', () => {
const { server, httpRequestsMockHelpers } = setupEnvironment();
let testBed: ComponentTemplateDetailsTestBed;

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

describe('With component template details', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadComponentTemplateResponse(COMPONENT_TEMPLATE);

await act(async () => {
testBed = setup({
componentTemplateName: COMPONENT_TEMPLATE.name,
onClose: () => {},
});
});

testBed.component.update();
});

test('renders the details flyout', () => {
const { exists, find, actions, component } = testBed;

// Verify flyout exists with correct title
expect(exists('componentTemplateDetails')).toBe(true);
expect(find('componentTemplateDetails.title').text()).toBe(COMPONENT_TEMPLATE.name);

// Verify footer does not display since "actions" prop was not provided
expect(exists('componentTemplateDetails.footer')).toBe(false);

// Verify tabs exist
expect(exists('settingsTab')).toBe(true);
expect(exists('mappingsTab')).toBe(true);
expect(exists('aliasesTab')).toBe(true);
// Summary tab should be active by default
expect(find('summaryTab').props()['aria-selected']).toBe(true);

// [Summary tab] Verify description list items
expect(exists('summaryTabContent.usedByTitle')).toBe(true);
expect(exists('summaryTabContent.versionTitle')).toBe(true);
expect(exists('summaryTabContent.metaTitle')).toBe(true);

// [Settings tab] Navigate to tab and verify content
act(() => {
actions.clickSettingsTab();
});

component.update();

expect(exists('settingsTabContent')).toBe(true);

// [Mappings tab] Navigate to tab and verify content
act(() => {
actions.clickMappingsTab();
});

component.update();
expect(exists('mappingsTabContent')).toBe(true);

// [Aliases tab] Navigate to tab and verify content
act(() => {
actions.clickAliasesTab();
});

component.update();
expect(exists('aliasesTabContent')).toBe(true);
});
});

describe('With only required component template fields', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadComponentTemplateResponse(
COMPONENT_TEMPLATE_ONLY_REQUIRED_FIELDS
);

await act(async () => {
testBed = setup({
componentTemplateName: COMPONENT_TEMPLATE_ONLY_REQUIRED_FIELDS.name,
onClose: () => {},
});
});

testBed.component.update();
});

test('renders the details flyout', () => {
const { exists, actions, component } = testBed;

// [Summary tab] Verify optional description list items do not display
expect(exists('summaryTabContent.usedByTitle')).toBe(false);
expect(exists('summaryTabContent.versionTitle')).toBe(false);
expect(exists('summaryTabContent.metaTitle')).toBe(false);
// Verify callout renders indicating the component template is not in use
expect(exists('notInUseCallout')).toBe(true);

// [Settings tab] Navigate to tab and verify info callout
act(() => {
actions.clickSettingsTab();
});

component.update();

expect(exists('noSettingsCallout')).toBe(true);

// [Mappings tab] Navigate to tab and verify info callout
act(() => {
actions.clickMappingsTab();
});

component.update();
expect(exists('noMappingsCallout')).toBe(true);

// [Aliases tab] Navigate to tab and verify info callout
act(() => {
actions.clickAliasesTab();
});

component.update();
expect(exists('noAliasesCallout')).toBe(true);
});
});

describe('With actions', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadComponentTemplateResponse(COMPONENT_TEMPLATE);

await act(async () => {
testBed = setup({
componentTemplateName: COMPONENT_TEMPLATE.name,
onClose: () => {},
actions: [
{
name: 'Test',
icon: 'info',
closePopoverOnClick: true,
handleActionClick: () => {},
},
],
});
});

testBed.component.update();
});

test('should render a footer with context menu', () => {
const { exists, actions, component, find } = testBed;

// Verify footer exists
expect(exists('componentTemplateDetails.footer')).toBe(true);
expect(exists('manageComponentTemplateButton')).toBe(true);

// Click manage button and verify actions
act(() => {
actions.clickManageButton();
});

component.update();

expect(exists('manageComponentTemplateContextMenu')).toBe(true);
expect(find('manageComponentTemplateContextMenu.action').length).toEqual(1);
});
});

describe('Error handling', () => {
const error = {
status: 500,
error: 'Internal server error',
message: 'Internal server error',
};

beforeEach(async () => {
httpRequestsMockHelpers.setLoadComponentTemplateResponse(undefined, { body: error });

await act(async () => {
testBed = setup({
componentTemplateName: COMPONENT_TEMPLATE.name,
onClose: () => {},
});
});

testBed.component.update();
});

test('should render an error message if error fetching pipelines', async () => {
const { exists, find } = testBed;

expect(exists('sectionError')).toBe(true);
expect(find('sectionError').text()).toContain('Error loading component template');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

import { act } from 'react-dom/test-utils';

import { ComponentTemplateListItem } from '../../shared_imports';

import { setupEnvironment, pageHelpers } from './helpers';
import { ComponentTemplateListTestBed } from './helpers/component_template_list.helpers';
import { API_BASE_PATH } from '../../../../../../common/constants';
import { ComponentTemplateListItem } from '../../types';
import { API_BASE_PATH } from './helpers/constants';

const { setup } = pageHelpers.componentTemplateList;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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, TestBed } from '../../../../../../../../../test_utils';
import { WithAppDependencies } from './setup_environment';
import { ComponentTemplateDetailsFlyout } from '../../../component_template_details';

export type ComponentTemplateDetailsTestBed = TestBed<ComponentTemplateDetailsTestSubjects> & {
actions: ReturnType<typeof createActions>;
};

const createActions = (testBed: TestBed<ComponentTemplateDetailsTestSubjects>) => {
const { find } = testBed;

/**
* User Actions
*/
const clickSettingsTab = () => {
find('settingsTab').simulate('click');
};

const clickMappingsTab = () => {
find('mappingsTab').simulate('click');
};

const clickAliasesTab = () => {
find('aliasesTab').simulate('click');
};

const clickManageButton = () => {
find('manageComponentTemplateButton').simulate('click');
};

return {
clickSettingsTab,
clickAliasesTab,
clickMappingsTab,
clickManageButton,
};
};

export const setup = (props: any): ComponentTemplateDetailsTestBed => {
const setupTestBed = registerTestBed<ComponentTemplateDetailsTestSubjects>(
WithAppDependencies(ComponentTemplateDetailsFlyout),
{
memoryRouter: {
wrapComponent: false,
},
defaultProps: props,
}
);

const testBed = setupTestBed() as ComponentTemplateDetailsTestBed;

return {
...testBed,
actions: createActions(testBed),
};
};

export type ComponentTemplateDetailsTestSubjects =
| 'componentTemplateDetails'
| 'componentTemplateDetails.title'
| 'componentTemplateDetails.footer'
| 'summaryTab'
| 'mappingsTab'
| 'settingsTab'
| 'aliasesTab'
| 'sectionError'
| 'summaryTabContent'
| 'summaryTabContent.usedByTitle'
| 'summaryTabContent.versionTitle'
| 'summaryTabContent.metaTitle'
| 'notInUseCallout'
| 'aliasesTabContent'
| 'noAliasesCallout'
| 'mappingsTabContent'
| 'noMappingsCallout'
| 'settingsTabContent'
| 'noSettingsCallout'
| 'manageComponentTemplateButton'
| 'manageComponentTemplateContextMenu'
| 'manageComponentTemplateContextMenu.action';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* 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.
*/

export const API_BASE_PATH = '/api/index_management';
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
*/

import sinon, { SinonFakeServer } from 'sinon';
import { API_BASE_PATH } from '../../../../../../../common';
import { ComponentTemplateListItem, ComponentTemplateDeserialized } from '../../../shared_imports';
import { API_BASE_PATH } from './constants';

// Register helpers to mock HTTP Requests
const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
const setLoadComponentTemplatesResponse = (response?: any[], error?: any) => {
const setLoadComponentTemplatesResponse = (
response?: ComponentTemplateListItem[],
error?: any
) => {
const status = error ? error.status || 400 : 200;
const body = error ? error.body : response;

Expand All @@ -20,6 +24,20 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
]);
};

const setLoadComponentTemplateResponse = (
response?: ComponentTemplateDeserialized,
error?: any
) => {
const status = error ? error.status || 400 : 200;
const body = error ? error.body : response;

server.respondWith('GET', `${API_BASE_PATH}/component_templates/:name`, [
status,
{ 'Content-Type': 'application/json' },
JSON.stringify(body),
]);
};

const setDeleteComponentTemplateResponse = (response?: object) => {
server.respondWith('DELETE', `${API_BASE_PATH}/component_templates/:name`, [
200,
Expand All @@ -31,6 +49,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => {
return {
setLoadComponentTemplatesResponse,
setDeleteComponentTemplateResponse,
setLoadComponentTemplateResponse,
};
};

Expand Down
Loading

0 comments on commit a34a3a7

Please sign in to comment.