Skip to content

Commit

Permalink
[Unit Testing] Configure react-testing-library queries to use Kibana'…
Browse files Browse the repository at this point in the history
…s data-test-subj instead of default data-testid (#59445) (#59742)

# Conflicts:
#	x-pack/plugins/endpoint/public/applications/endpoint/view/managing/index.test.tsx
  • Loading branch information
Dosant authored Mar 10, 2020
1 parent 7022f9e commit 958d733
Show file tree
Hide file tree
Showing 19 changed files with 67 additions and 81 deletions.
5 changes: 4 additions & 1 deletion src/dev/jest/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ export default {
'<rootDir>/src/dev/jest/setup/polyfills.js',
'<rootDir>/src/dev/jest/setup/enzyme.js',
],
setupFilesAfterEnv: ['<rootDir>/src/dev/jest/setup/mocks.js'],
setupFilesAfterEnv: [
'<rootDir>/src/dev/jest/setup/mocks.js',
'<rootDir>/src/dev/jest/setup/react_testing_library.js',
],
coverageDirectory: '<rootDir>/target/kibana-coverage/jest',
coverageReporters: ['html', 'text'],
moduleFileExtensions: ['js', 'json', 'ts', 'tsx'],
Expand Down
32 changes: 32 additions & 0 deletions src/dev/jest/setup/react_testing_library.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import '@testing-library/jest-dom/extend-expect';
/**
* Have to import "/pure" here to not register afterEach() hook clean up
* in the very beginning. There are couple tests which fail with clean up hook.
* On CI they run before first test which imports '@testing-library/react'
* and registers afterEach hook so the whole suite is passing.
* This have to be fixed as we depend on test order execution
* https://github.com/elastic/kibana/issues/59469
*/
import { configure } from '@testing-library/react/pure';

// instead of default 'data-testid', use kibana's 'data-test-subj'
configure({ testIdAttribute: 'data-test-subj' });
1 change: 1 addition & 0 deletions x-pack/dev-tools/jest/create_jest_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) {
setupFilesAfterEnv: [
`<rootDir>/dev-tools/jest/setup/setup_test.js`,
`${kibanaDirectory}/src/dev/jest/setup/mocks.js`,
`${kibanaDirectory}/src/dev/jest/setup/react_testing_library.js`,
],
testMatch: ['**/*.test.{js,ts,tsx}'],
transform: {
Expand Down
1 change: 0 additions & 1 deletion x-pack/dev-tools/jest/setup/setup_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@
*/

import 'jest-styled-components';
import '@testing-library/jest-dom/extend-expect';
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export function KeyValueTable({
{keyValuePairs.map(({ key, value }) => (
<EuiTableRow key={key}>
<EuiTableRowCell>
<strong data-testid="dot-key">{key}</strong>
<strong data-test-subj="dot-key">{key}</strong>
</EuiTableRowCell>
<EuiTableRowCell data-testid="value">
<EuiTableRowCell data-test-subj="value">
<FormattedValue value={value} />
</EuiTableRowCell>
</EuiTableRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export function CustomSelectionTable({
{!singleSelection && (
<EuiCheckbox
id={`${item.id}-checkbox`}
data-testid={`${item.id}-checkbox`}
data-test-subj={`${item.id}-checkbox`}
checked={isItemSelected(item.id)}
onChange={() => toggleItem(item.id)}
type="inList"
Expand All @@ -265,7 +265,7 @@ export function CustomSelectionTable({
{singleSelection && (
<EuiRadio
id={item.id}
data-testid={`${item.id}-radio-button`}
data-test-subj={`${item.id}-radio-button`}
checked={isItemSelected(item.id)}
onChange={() => toggleItem(item.id)}
disabled={timeseriesOnly && item.isSingleMetricViewerJob === false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import React from 'react';
import { render } from '@testing-library/react';

import * as CheckPrivilige from '../../../../../privilege/check_privilege';
import { queryByTestSubj } from '../../../../../util/test_utils';

import { DeleteAction } from './action_delete';

Expand All @@ -21,24 +20,22 @@ jest.mock('../../../../../privilege/check_privilege', () => ({

describe('DeleteAction', () => {
test('When canDeleteDataFrameAnalytics permission is false, button should be disabled.', () => {
const { container } = render(<DeleteAction item={mockAnalyticsListItem} />);
expect(queryByTestSubj(container, 'mlAnalyticsJobDeleteButton')).toHaveAttribute('disabled');
const { getByTestId } = render(<DeleteAction item={mockAnalyticsListItem} />);
expect(getByTestId('mlAnalyticsJobDeleteButton')).toHaveAttribute('disabled');
});

test('When canDeleteDataFrameAnalytics permission is true, button should not be disabled.', () => {
const mock = jest.spyOn(CheckPrivilige, 'checkPermission');
mock.mockImplementation(p => p === 'canDeleteDataFrameAnalytics');
const { container } = render(<DeleteAction item={mockAnalyticsListItem} />);
const { getByTestId } = render(<DeleteAction item={mockAnalyticsListItem} />);

expect(queryByTestSubj(container, 'mlAnalyticsJobDeleteButton')).not.toHaveAttribute(
'disabled'
);
expect(getByTestId('mlAnalyticsJobDeleteButton')).not.toHaveAttribute('disabled');

mock.mockRestore();
});

test('When job is running, delete button should be disabled.', () => {
const { container } = render(
const { getByTestId } = render(
<DeleteAction
item={{
...mockAnalyticsListItem,
Expand All @@ -47,6 +44,6 @@ describe('DeleteAction', () => {
/>
);

expect(queryByTestSubj(container, 'mlAnalyticsJobDeleteButton')).toHaveAttribute('disabled');
expect(getByTestId('mlAnalyticsJobDeleteButton')).toHaveAttribute('disabled');
});
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export const CalendarForm = ({
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
data-testid="ml_save_calendar_button"
data-test-subj="ml_save_calendar_button"
fill
onClick={isEdit ? onEdit : onCreate}
isDisabled={saveButtonDisabled}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const EventsTable = ({
name: '',
render: event => (
<DeleteButton
data-testid="event_delete"
data-test-subj="event_delete"
canDeleteCalendar={canDeleteCalendar}
onClick={() => {
onDeleteClick(event.event_id);
Expand All @@ -106,7 +106,7 @@ export const EventsTable = ({
<EuiButton
isDisabled={canCreateCalendar === false}
key="ml_new_event"
data-testid="ml_new_event"
data-test-subj="ml_new_event"
size="s"
iconType="plusInCircle"
onClick={showNewEventModal}
Expand All @@ -119,7 +119,7 @@ export const EventsTable = ({
<EuiButton
isDisabled={canCreateCalendar === false}
key="ml_import_event"
data-testid="ml_import_events"
data-test-subj="ml_import_events"
size="s"
iconType="importAction"
onClick={showImportModal}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('ImportModal', () => {
instance.setState(testState);
wrapper.update();
expect(wrapper.state('selectedEvents').length).toBe(2);
const deleteButton = wrapper.find('[data-testid="event_delete"]');
const deleteButton = wrapper.find('[data-test-subj="event_delete"]');
const button = deleteButton.find('EuiButtonEmpty').first();
button.simulate('click');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ describe('NewCalendar', () => {
test('Import modal shown on Import Events button click', () => {
const wrapper = mountWithIntl(<NewCalendar {...props} />);

const importButton = wrapper.find('[data-testid="ml_import_events"]');
const importButton = wrapper.find('[data-test-subj="ml_import_events"]');
const button = importButton.find('EuiButton');
button.simulate('click');

Expand All @@ -127,7 +127,7 @@ describe('NewCalendar', () => {
test('New event modal shown on New event button click', () => {
const wrapper = mountWithIntl(<NewCalendar {...props} />);

const importButton = wrapper.find('[data-testid="ml_new_event"]');
const importButton = wrapper.find('[data-test-subj="ml_new_event"]');
const button = importButton.find('EuiButton');
button.simulate('click');

Expand All @@ -154,7 +154,7 @@ describe('NewCalendar', () => {

const wrapper = mountWithIntl(<NewCalendar {...noCreateProps} />);

const buttons = wrapper.find('[data-testid="ml_save_calendar_button"]');
const buttons = wrapper.find('[data-test-subj="ml_save_calendar_button"]');
const saveButton = buttons.find('EuiButton');

expect(saveButton.prop('isDisabled')).toBe(true);
Expand Down
18 changes: 0 additions & 18 deletions x-pack/legacy/plugins/ml/public/application/util/test_utils.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export const HeaderNavigation: React.FunctionComponent<{ basename: string }> = R
return tabs.map((tab, index) => {
return (
<EuiTab
data-testid={`${tab.id}EndpointTab`}
data-test-subj={`${tab.id}EndpointTab`}
key={index}
href={`${basename}${tab.href}`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AlertIndex } from './index';
import { appStoreFactory } from '../../store';
import { coreMock } from 'src/core/public/mocks';
import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public';
import { fireEvent, waitForElement, act } from '@testing-library/react';
import { fireEvent, act } from '@testing-library/react';
import { RouteCapture } from '../route_capture';
import { createMemoryHistory, MemoryHistory } from 'history';
import { Router } from 'react-router-dom';
Expand All @@ -24,18 +24,6 @@ describe('when on the alerting page', () => {
let history: MemoryHistory<never>;
let store: ReturnType<typeof appStoreFactory>;

/**
* @testing-library/react provides `queryByTestId`, but that uses the data attribute
* 'data-testid' whereas our FTR and EUI's tests all use 'data-test-subj'. While @testing-library/react
* could be configured to use 'data-test-subj', it is not currently configured that way.
*
* This provides an equivalent function to `queryByTestId` but that uses our 'data-test-subj' attribute.
*/
let queryByTestSubjId: (
renderResult: reactTestingLibrary.RenderResult,
testSubjId: string
) => Promise<Element | null>;

beforeEach(async () => {
/**
* Create a 'history' instance that is only in-memory and causes no side effects to the testing environment.
Expand Down Expand Up @@ -70,17 +58,6 @@ describe('when on the alerting page', () => {
</Provider>
);
};
queryByTestSubjId = async (renderResult, testSubjId) => {
return await waitForElement(
/**
* Use document.body instead of container because EUI renders things like popover out of the DOM heirarchy.
*/
() => document.body.querySelector(`[data-test-subj="${testSubjId}"]`),
{
container: renderResult.container,
}
);
};
});
it('should show a data grid', async () => {
await render().findByTestId('alertListGrid');
Expand Down Expand Up @@ -147,7 +124,7 @@ describe('when on the alerting page', () => {
/**
* Use our helper function to find the flyout's close button, as it uses a different test ID attribute.
*/
const closeButton = await queryByTestSubjId(renderResult, 'euiFlyoutCloseButton');
const closeButton = await renderResult.findByTestId('euiFlyoutCloseButton');
if (closeButton) {
fireEvent.click(closeButton);
}
Expand All @@ -169,16 +146,13 @@ describe('when on the alerting page', () => {
describe('when the user changes page size to 10', () => {
beforeEach(async () => {
const renderResult = render();
const paginationButton = await queryByTestSubjId(
renderResult,
'tablePaginationPopoverButton'
);
const paginationButton = await renderResult.findByTestId('tablePaginationPopoverButton');
if (paginationButton) {
act(() => {
fireEvent.click(paginationButton);
});
}
const show10RowsButton = await queryByTestSubjId(renderResult, 'tablePagination-10-rows');
const show10RowsButton = await renderResult.findByTestId('tablePagination-10-rows');
if (show10RowsButton) {
act(() => {
fireEvent.click(show10RowsButton);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const AlertIndex = memo(() => {
if (columnId === 'alert_type') {
return (
<EuiLink
data-testid="alertTypeCellLink"
data-test-subj="alertTypeCellLink"
onClick={() =>
history.push(urlFromQueryParams({ ...queryParams, selected_alert: row.id }))
}
Expand Down Expand Up @@ -211,7 +211,7 @@ export const AlertIndex = memo(() => {
return (
<>
{hasSelectedAlert && (
<EuiFlyout data-testid="alertDetailFlyout" size="l" onClose={handleFlyoutClose}>
<EuiFlyout data-test-subj="alertDetailFlyout" size="l" onClose={handleFlyoutClose}>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>
Expand All @@ -226,7 +226,7 @@ export const AlertIndex = memo(() => {
</EuiFlyoutBody>
</EuiFlyout>
)}
<EuiPage data-test-subj="alertListPage" data-testid="alertListPage">
<EuiPage data-test-subj="alertListPage">
<EuiPageBody>
<EuiPageContent>
<EuiPageContentHeader>
Expand All @@ -250,7 +250,6 @@ export const AlertIndex = memo(() => {
renderCellValue={renderCellValue}
pagination={pagination}
data-test-subj="alertListGrid"
data-testid="alertListGrid"
/>
</EuiPageContentBody>
</EuiPageContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const AlertDetailResolver = styled(
const { store } = storeFactory(context);

return (
<div className={className} data-test-subj="alertResolver" data-testid="alertResolver">
<div className={className} data-test-subj="alertResolver">
<Provider store={store}>
<Resolver selectedEvent={selectedEvent} />
</Provider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('useCamera on an unpainted element', () => {
const camera = useCamera();
const { ref, onMouseDown } = camera;
projectionMatrix = camera.projectionMatrix;
return <div data-testid={testID} onMouseDown={onMouseDown} ref={ref} />;
return <div data-test-subj={testID} onMouseDown={onMouseDown} ref={ref} />;
};

simulator = sideEffectSimulator();
Expand Down

0 comments on commit 958d733

Please sign in to comment.