Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
65900a7
[Index details page] Adds an internal api endpoint for index details
yuliacech Aug 15, 2023
0a8e6cf
[Index details page] Add an api service for loading index details
yuliacech Aug 15, 2023
ba1b14a
[Index details page] Use an api service to load index details on the …
yuliacech Aug 15, 2023
597ad61
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 15, 2023
f1b6bfe
[Index details page] Add a discover index button
yuliacech Aug 16, 2023
6afdf1b
[Index details page] Add a manage index button
yuliacech Aug 16, 2023
ef75f51
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 16, 2023
18c620d
[Index details page] Set up a component to replace redux index action…
yuliacech Aug 16, 2023
bf74fe8
Merge branch 'main' into im/details_page/api_index_details
yuliacech Aug 17, 2023
5e89667
Merge branch 'main' into im/details_page/api_index_details
yuliacech Aug 22, 2023
10ee5d9
[Index details page] Update translation files
yuliacech Aug 22, 2023
0837329
[Index details page] Add jest tests
yuliacech Aug 22, 2023
41b0f66
[Index details page] Add jest tests for error section
yuliacech Aug 22, 2023
d435d28
[Index details page] Fix jest test
yuliacech Aug 22, 2023
e5f683e
[Index details page] Add api integration tests
yuliacech Aug 22, 2023
f82bc7d
Merge branch 'main' into im/details_page/api_index_details
yuliacech Aug 22, 2023
fb0fa06
[Index details page] Make the "manage index" button secondary
yuliacech Aug 23, 2023
0d6f9eb
Merge branch 'main' into im/details_page/api_index_details
yuliacech Aug 23, 2023
1c3e39d
[Index details page] Add api integration tests for serverless, remove…
yuliacech Aug 23, 2023
616f729
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 23, 2023
8e30328
[Index details page] Update the changed fetchIndices call
yuliacech Aug 23, 2023
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 @@ -6,7 +6,7 @@
*/

import { httpServiceMock } from '@kbn/core/public/mocks';
import { API_BASE_PATH } from '../../../common/constants';
import { API_BASE_PATH, INTERNAL_API_BASE_PATH } from '../../../common/constants';

type HttpResponse = Record<string, any> | any[];
type HttpMethod = 'GET' | 'PUT' | 'DELETE' | 'POST';
Expand Down Expand Up @@ -121,6 +121,12 @@ const registerHttpRequestMockHelpers = (
const setLoadTelemetryResponse = (response?: HttpResponse, error?: ResponseError) =>
mockResponse('GET', '/api/ui_counters/_report', response, error);

const setLoadIndexDetailsResponse = (
indexName: string,
response?: HttpResponse,
error?: ResponseError
) => mockResponse('GET', `${INTERNAL_API_BASE_PATH}/indices/${indexName}`, response, error);

return {
setLoadTemplatesResponse,
setLoadIndicesResponse,
Expand All @@ -139,6 +145,7 @@ const registerHttpRequestMockHelpers = (
setLoadComponentTemplatesResponse,
setLoadNodesPluginsResponse,
setLoadTelemetryResponse,
setLoadIndexDetailsResponse,
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
* 2.0.
*/

import { AsyncTestBedConfig, registerTestBed, TestBed } from '@kbn/test-jest-helpers';
import {
AsyncTestBedConfig,
reactRouterMock,
registerTestBed,
TestBed,
} from '@kbn/test-jest-helpers';
import { HttpSetup } from '@kbn/core/public';
import { act } from 'react-dom/test-utils';
import {
Expand All @@ -14,19 +19,34 @@ import {
} from '../../../public/application/sections/home/index_list/details_page';
import { WithAppDependencies } from '../helpers';

let routerMock: typeof reactRouterMock;
const testBedConfig: AsyncTestBedConfig = {
memoryRouter: {
initialEntries: [`/indices/test_index`],
componentRoutePath: `/indices/:indexName/:indexDetailsSection?`,
onRouter: (router) => {
routerMock = router;
},
},
doMountAsync: true,
};

export interface IndexDetailsPageTestBed extends TestBed {
routerMock: typeof reactRouterMock;
actions: {
getHeader: () => string;
clickIndexDetailsTab: (tab: IndexDetailsSection) => Promise<void>;
getActiveTabContent: () => string;
clickBackToIndicesButton: () => Promise<void>;
discoverLinkExists: () => boolean;
contextMenu: {
clickManageIndexButton: () => Promise<void>;
isOpened: () => boolean;
};
errorSection: {
isDisplayed: () => boolean;
clickReloadButton: () => Promise<void>;
};
};
}

Expand All @@ -39,30 +59,67 @@ export const setup = async (
testBedConfig
);
const testBed = await initTestBed();
const { find, component, exists } = testBed;

const errorSection = {
isDisplayed: () => {
return exists('indexDetailsErrorLoadingDetails');
},
clickReloadButton: async () => {
await act(async () => {
find('indexDetailsReloadDetailsButton').simulate('click');
});
component.update();
},
};
const getHeader = () => {
return testBed.component.find('[data-test-subj="indexDetailsHeader"] h1').text();
return component.find('[data-test-subj="indexDetailsHeader"] h1').text();
};

const clickIndexDetailsTab = async (tab: IndexDetailsSection) => {
const { find, component } = testBed;

await act(async () => {
find(`indexDetailsTab-${tab}`).simulate('click');
});
component.update();
};

const getActiveTabContent = () => {
return testBed.find('indexDetailsContent').text();
return find('indexDetailsContent').text();
};

const clickBackToIndicesButton = async () => {
await act(async () => {
find('indexDetailsBackToIndicesButton').simulate('click');
});
component.update();
};

const discoverLinkExists = () => {
return exists('discoverButtonLink');
};

const contextMenu = {
clickManageIndexButton: async () => {
await act(async () => {
find('indexActionsContextMenuButton').simulate('click');
});
component.update();
},
isOpened: () => {
return exists('indexContextMenu');
},
};
return {
...testBed,
routerMock,
actions: {
getHeader,
clickIndexDetailsTab,
getActiveTabContent,
clickBackToIndicesButton,
discoverLinkExists,
contextMenu,
errorSection,
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,57 @@
import { setupEnvironment } from '../helpers';
import { IndexDetailsPageTestBed, setup } from './index_details_page.helpers';
import { act } from 'react-dom/test-utils';
import { httpServiceMock } from '@kbn/core/public/mocks';
import { IndexDetailsSection } from '../../../public/application/sections/home/index_list/details_page';
import { testIndexMock } from './mocks';

describe('<IndexDetailsPage />', () => {
let testBed: IndexDetailsPageTestBed;
let httpSetup: ReturnType<typeof setupEnvironment>['httpSetup'];
let httpRequestsMockHelpers: ReturnType<typeof setupEnvironment>['httpRequestsMockHelpers'];

beforeEach(async () => {
httpSetup = httpServiceMock.createSetupContract();
const mockEnvironment = setupEnvironment();
({ httpSetup, httpRequestsMockHelpers } = mockEnvironment);
// test_index is configured in initialEntries of the memory router
httpRequestsMockHelpers.setLoadIndexDetailsResponse('test_index', testIndexMock);

await act(async () => {
testBed = await setup(httpSetup);
testBed = await setup(httpSetup, {
url: {
locators: {
get: () => ({ navigate: jest.fn() }),
},
},
});
});
testBed.component.update();
});

describe('error section', () => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm not testing the loading indicator here, because I think I could re-use what @sabarasaba implemented for enrich policies here. So I'm planning to add the test later when enrich policies are merged into main.

beforeEach(async () => {
httpRequestsMockHelpers.setLoadIndexDetailsResponse('test_index', undefined, {
statusCode: 400,
message: 'Data for index .apm-agent-configuration was not found',
});
await act(async () => {
testBed = await setup(httpSetup);
});

testBed.component.update();
});
it('displays an error callout when failed to load index details', async () => {
expect(testBed.actions.errorSection.isDisplayed()).toBe(true);
});

it('resends a request when reload button is clicked', async () => {
// already sent 2 requests while setting up the component
const numberOfRequests = 2;
expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests);
await testBed.actions.errorSection.clickReloadButton();
expect(httpSetup.get).toHaveBeenCalledTimes(numberOfRequests + 1);
});
});

it('displays index name in the header', () => {
const header = testBed.actions.getHeader();
// test_index is configured in initialEntries of the memory router
Expand Down Expand Up @@ -58,4 +93,25 @@ describe('<IndexDetailsPage />', () => {
const tabContent = testBed.actions.getActiveTabContent();
expect(tabContent).toEqual('Pipelines');
});

it('navigates back to indices', async () => {
jest.spyOn(testBed.routerMock.history, 'push');
await testBed.actions.clickBackToIndicesButton();
expect(testBed.routerMock.history.push).toHaveBeenCalledTimes(1);
expect(testBed.routerMock.history.push).toHaveBeenCalledWith('/indices');
});

it('renders a link to discover', () => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

only testing that the button is displayed, since the discover link component has its own tests

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does it make sense to add a comment to this effect in the code?

// we only need to test that the link is rendered since the link component has its own tests for navigation
expect(testBed.actions.discoverLinkExists()).toBe(true);
});

it('opens an index context menu when "manage index" button is clicked', async () => {
const {
actions: { contextMenu },
} = testBed;
expect(contextMenu.isOpened()).toBe(false);
await testBed.actions.contextMenu.clickManageIndexButton();
expect(contextMenu.isOpened()).toBe(true);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { Index } from '../../../public';

export const testIndexMock: Index = {
health: 'green',
status: 'open',
name: 'test_index',
uuid: 'test1234',
primary: '1',
replica: '1',
documents: 1,
documents_deleted: 0,
size: '10kb',
primary_size: '10kb',
isFrozen: false,
aliases: 'none',
hidden: false,
isRollupIndex: false,
ilm: {
index: 'test_index',
managed: false,
},
isFollowerIndex: false,
};
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ describe('index table', () => {
indexNameLink.simulate('click');
rendered.update();
expect(findTestSubject(rendered, 'indexDetailFlyout').length).toBe(1);
expect(findTestSubject(rendered, 'indexDetailFlyoutDiscover').length).toBe(1);
expect(findTestSubject(rendered, 'discoverIconLink').length).toBe(1);
});

test('should show the right context menu options when one index is selected and open', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { mountWithIntl } from '@kbn/test-jest-helpers';
import { EuiButtonIcon } from '@elastic/eui';
import { DiscoverLink } from './discover_link';
import { AppContextProvider, AppDependencies } from '../app_context';

describe('DiscoverLink', () => {
const indexName = 'my-fancy-index';

it('renders the link as an icon by default', async () => {
const navigateMock = jest.fn();
const ctx = {
url: {
locators: {
get: () => ({ navigate: navigateMock }),
},
},
} as unknown as AppDependencies;

const component = mountWithIntl(
<AppContextProvider value={ctx}>
<DiscoverLink indexName={indexName} />
</AppContextProvider>
);

expect(component.exists('[data-test-subj="discoverIconLink"]')).toBe(true);
expect(component.exists('[data-test-subj="discoverButtonLink"]')).toBe(false);
});

it('renders the link as a button if the prop is set', async () => {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These tests are mostly from the renamed file render_discover_link.test.ts with an addition of new tests for rendering the link as a button (not only as an icon)

const navigateMock = jest.fn();
const ctx = {
url: {
locators: {
get: () => ({ navigate: navigateMock }),
},
},
} as unknown as AppDependencies;

const component = mountWithIntl(
<AppContextProvider value={ctx}>
<DiscoverLink indexName={indexName} asButton={true} />
</AppContextProvider>
);

expect(component.exists('[data-test-subj="discoverIconLink"]')).toBe(false);
expect(component.exists('[data-test-subj="discoverButtonLink"]')).toBe(true);
});

it('calls navigate method when button is clicked', async () => {
const navigateMock = jest.fn();
const ctx = {
url: {
locators: {
get: () => ({ navigate: navigateMock }),
},
},
} as unknown as AppDependencies;

const component = mountWithIntl(
<AppContextProvider value={ctx}>
<DiscoverLink indexName={indexName} />
</AppContextProvider>
);
const button = component.find(EuiButtonIcon);

await button.simulate('click');
expect(navigateMock).toHaveBeenCalledWith({ dataViewSpec: { title: indexName } });
});

it('does not render a button if locators is not defined', () => {
const ctx = {} as unknown as AppDependencies;

const component = mountWithIntl(
<AppContextProvider value={ctx}>
<DiscoverLink indexName={indexName} />
</AppContextProvider>
);
const button = component.find(EuiButtonIcon);

expect(button).toHaveLength(0);
});
});
Loading