Skip to content

Commit

Permalink
[Log Explorer] Add test suite for Dataset Selector (elastic#163079)
Browse files Browse the repository at this point in the history
## πŸ““ Summary

Closes elastic#160627 

This implementation adds the majority of the tests listed down here for
the Log Explorer current implementation.

βœ… [**Flaky Test Runner - x50
executions**](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/2844#_)

```
↳ Discover Log-Explorer profile
   ↳ Columns selection initialization and update
     ↳ when the log explorer profile loads
       ↳ should initialize the table columns to logs' default selection
       ↳ should restore the table columns from the URL state if exists
   ↳ Customizations
     ↳ when Discover is loaded with the log-explorer profile
       ↳ DatasetSelector should replace the DataViewPicker
       ↳ the TopNav bar should hide the New, Open and Save options
       ↳ should add a searchable deep link to the profile page
       ↳ should render a filter controls section as part of the unified search bar
   ↳ DatasetSelection initialization and update
     ↳ when the "index" query param does not exist
       ↳ should initialize the "All log datasets" selection
     ↳ when the "index" query param exists
       ↳ should decode and restore the selection from a valid encoded index
       ↳ should fallback to the "All log datasets" selection and notify the user of an invalid encoded index
     ↳ when navigating back and forth on the page history
       ↳ should decode and restore the selection for the current index
   ↳ Dataset Selector
     ↳ without installed integrations or uncategorized data streams
       ↳ when open on the first navigation level
         ↳ should always display the "All log datasets" entry as the first item
         ↳ should always display the unmanaged datasets entry as the second item
         ↳ should display an error prompt if could not retrieve the integrations
         ↳ should display an empty prompt for no integrations
       ↳ when navigating into Uncategorized data streams
         ↳ should display a loading skeleton while loading
         ↳ should display an error prompt if could not retrieve the data streams
         ↳ should display an empty prompt for no data streams
     ↳ with installed integrations and uncategorized data streams
       ↳ when open on the first navigation level
         ↳ should always display the "All log datasets" entry as the first item
         ↳ should always display the unmanaged datasets entry as the second item
         ↳ should display a list of installed integrations
         ↳ should sort the integrations list by the clicked sorting option
         ↳ should filter the integrations list by the typed integration name
         ↳ should display an empty prompt when the search does not match any result
         ↳ should load more integrations by scrolling to the end of the list
       ↳ when clicking on integration and moving into the second navigation level
         ↳ should display a list of available datasets
         ↳ should sort the datasets list by the clicked sorting option
         ↳ should filter the datasets list by the typed dataset name
         ↳ should update the current selection with the clicked dataset
       ↳ when navigating into Uncategorized data streams
         ↳ should display a list of available datasets
         ↳ should sort the datasets list by the clicked sorting option
         ↳ should filter the datasets list by the typed dataset name
         ↳ should update the current selection with the clicked dataset
       ↳ when open/close the selector
         ↳ should restore the latest navigation panel
         ↳ should restore the latest search results
       ↳ when switching between integration panels
         ↳ should remember the latest search and restore its results for each integration
```

## Note on serverless tests suite

For testing the feature in a serverless environment, we are copying all
the tests into the `x-pack/test_serverless` folder until
elastic#161574 is merged, which will
provide a new space to write tests independently from the deployment
type, avoiding then tests duplication.

## New `browser` service utils for Network conditions simulation

To properly test that this feature works correctly under poor network
conditions or offline scenarios, the `browser` service now exposes some
new methods for altering network conditions on demand.

Also, network profiles to match the [network profiles provided by Chrome
debugger](https://github.com/ChromeDevTools/devtools-frontend/blob/da276a3faec9769cb55e442f0db77ebdce5cd178/front_end/core/sdk/NetworkManager.ts#L363-L393)
have been created.

In case the browser is not of `chromium` type and the driver does not
support the network simulation, these methods throw an error that can be
caught for skipping the affected test.

---------

Co-authored-by: Marco Antonio Ghiani <marcoantonio.ghiani@elastic.co>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
3 people committed Aug 11, 2023
1 parent 27c394c commit f09a5c9
Show file tree
Hide file tree
Showing 20 changed files with 2,198 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export function DatasetSelector({
onPanelChange={changePanel}
className="eui-yScroll"
css={contextMenuStyles}
data-test-subj="datasetSelectorContextMenu"
size="s"
/>
</DatasetsPopover>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const DatasetsList = ({
if (hasError) {
return (
<EuiEmptyPrompt
data-test-subj="datasetErrorPrompt"
iconType="warning"
iconColor="danger"
paddingSize="m"
Expand All @@ -70,6 +71,7 @@ export const DatasetsList = ({
if (isEmpty) {
return (
<EuiEmptyPrompt
data-test-subj="emptyDatasetPrompt"
iconType="search"
paddingSize="m"
title={<h2>{noDatasetsLabel}</h2>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ export const DatasetsPopover = ({
return (
<EuiPopover
id={POPOVER_ID}
data-test-subj={POPOVER_ID}
data-test-subj="datasetSelectorPopover"
anchorPosition={isMobile ? 'downCenter' : 'downLeft'}
button={
<EuiButton
css={buttonStyles}
iconType="arrowDown"
iconSide="right"
onClick={onClick}
fullWidth={isMobile}
data-test-subj={`${POPOVER_ID}-button`}
data-test-subj="datasetSelectorPopoverButton"
>
{iconType ? (
<EuiIcon type={iconType} />
Expand All @@ -74,7 +75,12 @@ export const DatasetsPopover = ({
{...(isMobile && { display: 'block' })}
{...props}
>
<EuiPanel paddingSize="none" hasShadow={false} css={panelStyle}>
<EuiPanel
paddingSize="none"
hasShadow={false}
css={panelStyle}
data-test-subj="datasetSelectorContent"
>
<Title size="xxs">
<span>{selectDatasetLabel}</span>
</Title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { EuiPanel, EuiSkeletonText } from '@elastic/eui';
import { uncategorizedLabel } from '../constants';

export const DatasetSkeleton = () => (
<EuiPanel>
<EuiPanel data-test-subj="datasetSelectorSkeleton">
<EuiSkeletonText lines={7} isLoading contentAriaLabel={uncategorizedLabel} />
</EuiPanel>
);
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const IntegrationsListStatus = ({
if (hasError) {
return (
<EuiEmptyPrompt
data-test-subj="integrationsErrorPrompt"
iconType="warning"
iconColor="danger"
paddingSize="m"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ export const SearchControls = ({ search, onSearch, onSort, isLoading }: SearchCo
};

return (
<EuiPanel paddingSize="s" hasShadow={false} css={{ width: DATA_VIEW_POPOVER_CONTENT_WIDTH }}>
<EuiPanel
paddingSize="s"
hasShadow={false}
css={{ width: DATA_VIEW_POPOVER_CONTENT_WIDTH }}
data-test-subj="datasetSelectorSearchControls"
>
<EuiFlexGroup gutterSize="xs" responsive={false}>
<EuiFlexItem>
<EuiFieldSearch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const buildIntegrationsTree = ({
integrationsTree.items.push({
name: title,
icon: <PackageIcon packageName={name} version={version} size="m" icons={icons} tryApi />,
'data-test-subj': integration.id,
panel: integration.id,
...(isLastIntegration && { buttonRef: spyRef }),
});
Expand All @@ -85,6 +86,7 @@ export const createAllLogDatasetsItem = ({ onClick }: { onClick(): void }) => {
const allLogDataset = Dataset.createAllLogsDataset();
return {
name: allLogDataset.title,
'data-test-subj': 'allLogDatasets',
icon: allLogDataset.iconType && <EuiIcon type={allLogDataset.iconType} />,
onClick,
};
Expand All @@ -93,6 +95,7 @@ export const createAllLogDatasetsItem = ({ onClick }: { onClick(): void }) => {
export const createUnmanagedDatasetsItem = ({ onClick }: { onClick: LoadDatasets }) => {
return {
name: uncategorizedLabel,
'data-test-subj': 'unmanagedDatasets',
icon: <EuiIcon type="documents" />,
onClick,
panel: UNMANAGED_STREAMS_PANEL_ID,
Expand All @@ -103,5 +106,6 @@ export const createIntegrationStatusItem = (props: IntegrationsListStatusProps)
return {
disabled: true,
name: <IntegrationsListStatus {...props} />,
'data-test-subj': 'integrationStatusItem',
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { useControlPanels } from '../hooks/use_control_panels';
import { LogExplorerProfileStateService } from '../state_machines/log_explorer_profile';

const DATASET_FILTERS_CUSTOMIZATION_ID = 'datasetFiltersCustomization';

interface CustomDatasetFiltersProps {
logExplorerProfileStateService: LogExplorerProfileStateService;
data: DataPublicPluginStart;
Expand All @@ -27,7 +29,7 @@ const CustomDatasetFilters = ({
);

return (
<ControlGroupContainer>
<ControlGroupContainer data-test-subj={DATASET_FILTERS_CUSTOMIZATION_ID}>
<ControlGroupRenderer
ref={setControlGroupAPI}
getCreationOptions={getInitialInput}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';

const defaultLogColumns = ['@timestamp', 'message'];

export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const retry = getService('retry');
const PageObjects = getPageObjects(['common', 'discover']);

describe('Columns selection initialization and update', () => {
before(async () => {
await esArchiver.load(
'x-pack/test/functional/es_archives/discover_log_explorer/data_streams'
);
});

after(async () => {
await esArchiver.unload(
'x-pack/test/functional/es_archives/discover_log_explorer/data_streams'
);
});

describe('when the log explorer profile loads', () => {
it("should initialize the table columns to logs' default selection", async () => {
await PageObjects.common.navigateToApp('discover', { hash: '/p/log-explorer' });

await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage();

await retry.try(async () => {
expect(await PageObjects.discover.getColumnHeaders()).to.eql(defaultLogColumns);
});
});

it('should restore the table columns from the URL state if exists', async () => {
await PageObjects.common.navigateToApp('discover', {
hash: '/p/log-explorer?_a=(columns:!(message,data_stream.namespace))',
});

await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage();

await retry.try(async () => {
expect(await PageObjects.discover.getColumnHeaders()).to.eql([
...defaultLogColumns,
'data_stream.namespace',
]);
});
});
});
});
}
16 changes: 13 additions & 3 deletions x-pack/test/functional/apps/discover_log_explorer/customization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('DatasetSelector should replace the DataViewPicker', async () => {
// Assert does not render on discover app
await PageObjects.common.navigateToApp('discover');
await testSubjects.missingOrFail('dataset-selector-popover');
await testSubjects.missingOrFail('datasetSelectorPopover');

// Assert it renders on log-explorer profile
await PageObjects.common.navigateToApp('discover', { hash: '/p/log-explorer' });
await testSubjects.existOrFail('dataset-selector-popover');
await testSubjects.existOrFail('datasetSelectorPopover');
});

it('the TopNav bar should hide New, Open and Save options', async () => {
it('the TopNav bar should hide then New, Open and Save options', async () => {
// Assert does not render on discover app
await PageObjects.common.navigateToApp('discover');
await testSubjects.existOrFail('discoverNewButton');
Expand All @@ -59,6 +59,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const results = await PageObjects.navigationalSearch.getDisplayedResults();
expect(results[0].label).to.eql('Discover / Logs Explorer');
});

it('should render a filter controls section as part of the unified search bar', async () => {
// Assert does not render on discover app
await PageObjects.common.navigateToApp('discover');
await testSubjects.missingOrFail('datasetFiltersCustomization');

// Assert it renders on log-explorer profile
await PageObjects.common.navigateToApp('discover', { hash: '/p/log-explorer' });
await testSubjects.existOrFail('datasetFiltersCustomization', { allowHidden: true });
});
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
});

describe('when the "index" query param exist', () => {
describe('when the "index" query param exists', () => {
it('should decode and restore the selection from a valid encoded index', async () => {
const azureActivitylogsIndex =
'BQZwpgNmDGAuCWB7AdgLmAEwIay+W6yWAtmKgOQSIDmIAtFgF4CuATmAHRZzwBu8sAJ5VadAFTkANAlhRU3BPyEiQASklFS8lu2kC55AII6wAAgAyNEFN5hWIJGnIBGDgFYOAJgDM5deCgeFAAVQQAHMgdkaihVIA===';
Expand All @@ -37,7 +37,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(datasetSelectionTitle).to.be('[Azure Logs] activitylogs');
});

it('should fallback to "All log datasets" selection and notify the user for an invalid encoded index', async () => {
it('should fallback to the "All log datasets" selection and notify the user of an invalid encoded index', async () => {
const invalidEncodedIndex = 'invalid-encoded-index';
await PageObjects.common.navigateToApp('discover', {
hash: `/p/log-explorer?_a=(index:${encodeURIComponent(invalidEncodedIndex)})`,
Expand Down

0 comments on commit f09a5c9

Please sign in to comment.