Skip to content

Commit

Permalink
[D&D] Initial functional tests (#2070)
Browse files Browse the repository at this point in the history
* fix: searchable dropdown

Signed-off-by: Ashwin Pc <ashwinpc@amazon.com>

* fix: broken empty test

Signed-off-by: Ashwin Pc <ashwinpc@amazon.com>

* test(FTR): Adds basic functional tests for D&D

Signed-off-by: Ashwin Pc <ashwinpc@amazon.com>

* test(FTR): Adds CI group 13 to test workflow

Signed-off-by: Ashwin Pc <ashwinpc@amazon.com>

* fix: nit fixes

Signed-off-by: Ashwin Pc <ashwinpc@amazon.com>

* chore: att test to jenkinsfile

Signed-off-by: Ashwin Pc <ashwinpc@amazon.com>

* chore: minor nit fixes

Signed-off-by: Ashwin Pc <ashwinpc@amazon.com>
  • Loading branch information
ashwin-pc authored Aug 4, 2022
1 parent 159f4a6 commit 63e0bc4
Show file tree
Hide file tree
Showing 19 changed files with 325 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_and_test_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
name: Run functional tests
strategy:
matrix:
group: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
group: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
steps:
- run: echo Running functional tests for ciGroup${{ matrix.group }}

Expand Down
1 change: 1 addition & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def functionalDynamicParallelSteps(image){
"ciGroup10",
"ciGroup11",
"ciGroup12",
"ciGroup13",
]
for (int i = 0; i < ciGroups.size(); i++) {
def currentCiGroup = ciGroups[i];
Expand Down
17 changes: 16 additions & 1 deletion TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ To run specific functional tests, you can run by CI group:

To debug functional tests:
Say that you would want to debug a test in CI group 1, you can run the following command in your environment:
`node --debug-brk --inspect scripts/functional_tests.js --config test/functional/config.js --include ciGroup1 --debug`
`node --inspect-brk --inspect scripts/functional_tests.js --config test/functional/config.js --include ciGroup1 --debug`

This will print off an address, to which you could open your chrome browser on your instance and navigate to `chrome://inspect/#devices` and inspect the functional test runner `scripts/functional_tests.js`.

Expand Down Expand Up @@ -89,9 +89,24 @@ Automated testing is provided with Jenkins for Continuous Integration. Jenkins e
Selenium tests are run in headless mode on CI. Locally the same tests will be executed in a real browser. You can activate headless mode by setting the environment variable:
`export TEST_BROWSER_HEADLESS=1`

Since local Selenium tests are run in a real browser, the dev environment should have a desktop environment and Google Chrome or Chromium installed to run the tests.

By default the version of OpenSearch Dashboards will pull the snapshot of the same version of OpenSearch if available while running a few integration tests and for running functional tests. However, if the version of OpenSearch Dashboards is not available, you can build OpenSearch locally and point the functional test runner to the executable with:
`export TEST_OPENSEARCH_FROM=[local directory of OpenSearch executable]`

Selinium tests require a chromedriver and a corresponding version of chrome to run properly. Depending on the version of chromedriver used, you may need to use a version of Google Chrome that is not the latest version. You can do this by running:

```sh
# Enter the version of chrome that you want to install
CHROME_VERSION=100.0.4896.127-1

# Download Chrome to a temp directory
curl -sSL "https://dl.google.com/linux/linux_signing_key.pub" | sudo apt-key add - && wget -O /tmp/chrome.deb "https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}_amd64.deb"

# Install/Downgrade Chrome
sudo apt-get install -y --allow-downgrades /tmp/chrome.deb
```

# Misc
Although Jest is the standard for this project, there are a few Mocha tests that still exist. You can run these tests by running:
`yarn test:mocha`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,12 @@ const DropboxComponent = ({
draggableId={id}
index={index}
>
<EuiPanel key={index} paddingSize="s" className="dropBox__field">
<EuiPanel
key={index}
paddingSize="s"
className="dropBox__field"
data-test-subj={`dropBoxField-${dropboxId}-${index}`}
>
<EuiText size="s" className="dropBox__field_text" onClick={() => onEditField(id)}>
<a role="button" tabIndex={0}>
{label}
Expand All @@ -108,13 +113,15 @@ const DropboxComponent = ({
aria-label="clear-field"
iconSize="s"
onClick={() => animateDelete(id)}
data-test-subj="dropBoxRemoveBtn"
/>
</EuiPanel>
</EuiDraggable>
))}
</EuiDroppable>
{fields.length < limit && (
<EuiPanel
data-test-subj={`dropBoxAddField-${dropboxId}`}
className={`dropBox__field dropBox__dropTarget ${
isValidDropTarget ? 'validField' : ''
} ${canDrop ? 'canDrop' : ''}`}
Expand All @@ -126,6 +133,7 @@ const DropboxComponent = ({
aria-label="clear-field"
iconSize="s"
onClick={() => onAddField()}
data-test-subj="dropBoxAddBtn"
/>
</EuiPanel>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export interface TitleProps {
}

export const Title = ({ title, isSecondary, closeMenu }: TitleProps) => {
const icon = isSecondary && <EuiIcon type="arrowLeft" onClick={closeMenu} />;
const icon = isSecondary && (
<EuiIcon type="arrowLeft" onClick={closeMenu} data-test-subj="panelCloseBtn" />
);
return (
<>
<div className="wizConfig__title">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,34 @@

.searchableDropdown {
overflow: "hidden";
}

.searchableDropdown .euiPopover,
.searchableDropdown .euiPopover__anchor {
width: 100%;
}
.euiFormControlLayout__childrenWrapper {
display: flex;
}

.searchableDropdown--fixedWidthChild {
width: calc(#{$wizSideNavWidth} - #{$euiSizeXL} * 2);
}
&--topDisplay {
padding-right: $euiSizeL;
font-size: $euiFontSizeS;
flex-grow: 1;

.searchableDropdown--topDisplay {
padding-right: $euiSizeL;
font-size: $euiFontSizeS;
}
.euiButtonEmpty__content {
justify-content: flex-start;
}
}

&--fixedWidthChild {
width: calc(#{$wizSideNavWidth} - #{$euiSizeXL} * 2);
}

&--selectableWrapper .euiSelectableList {
// When clicking on the selectable content it will "highlight" itself with a box shadow
// This turns that off
box-shadow: none !important;
margin: ($euiFormControlPadding * -1) - 4;
}

.searchableDropdown--selectableWrapper .euiSelectableList {
// When clicking on the selectable content it will "highlight" itself with a box shadow
// This turns that off
box-shadow: none !important;
margin: ($euiFormControlPadding * -1) - 4;
.euiPopover,
.euiPopover__anchor {
width: 100%;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export const SearchableDropdown = ({
<div className="searchableDropdown--selectableWrapper">
<EuiSelectable
aria-label="Selectable options"
data-test-subj="searchableDropdownList"
searchable
options={localOptions}
onChange={selectNewOption}
Expand Down Expand Up @@ -145,6 +146,7 @@ export const SearchableDropdown = ({
size="s"
style={{ textAlign: 'left' }}
className="searchableDropdown--topDisplay"
data-test-subj="searchableDropdownValue"
onClick={onButtonClick}
>
{selectedText}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ export const Workspace: FC = ({ children }) => {
<ExperimentalInfo />
</EuiFlexItem>
</EuiFlexGroup>
<EuiPanel className="wizCanvas">
<EuiPanel className="wizCanvas" data-test-subj="visualizationLoader">
{expression ? (
<ReactExpressionRenderer expression={expression} searchContext={searchContext} />
) : (
<EuiFlexItem className="wizWorkspace__empty">
<EuiFlexItem className="wizWorkspace__empty" data-test-subj="emptyWorkspace">
<EuiEmptyPrompt
title={<h2>Add a field to start</h2>}
body={
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions test/common/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export default function () {
`--opensearchDashboards.branding.mark.defaultUrl=https://opensearch.org/assets/brand/SVG/Mark/opensearch_mark_default.svg`,
`--opensearchDashboards.branding.mark.darkModeUrl=https://opensearch.org/assets/brand/SVG/Mark/opensearch_mark_darkmode.svg`,
`--opensearchDashboards.branding.applicationTitle=OpenSearch`,
`--wizard.enabled=true`,
],
},
services,
Expand Down
2 changes: 1 addition & 1 deletion test/examples/embeddables/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

import { PluginFunctionalProviderContext } from 'test/plugin_functional/services';

export const testDashboardInput = {
const testDashboardInput = {
panels: {
'1': {
gridData: {
Expand Down
48 changes: 48 additions & 0 deletions test/functional/apps/wizard/_base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import expect from '@osd/expect';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService, getPageObjects }: FtrProviderContext) {
const PageObjects = getPageObjects(['visualize', 'wizard']);
const log = getService('log');
const retry = getService('retry');

describe('Basic tests for wizard app ', function () {
before(async () => {
log.debug('navigateToApp wizard');
await PageObjects.wizard.navigateToCreateWizard();
});

it('should be able to switch data sources', async () => {
const dataSourceValue = await PageObjects.wizard.selectDataSource(
PageObjects.wizard.index.LOGSTASH_NON_TIME_BASED
);

expect(dataSourceValue).to.equal(PageObjects.wizard.index.LOGSTASH_NON_TIME_BASED);
// TODO: Switch with a datasource with unique fields to test if it exists
});

it('should show visualization when a field is added', async () => {
await PageObjects.wizard.addField('metric', 'Average', 'machine.ram');
const avgMachineRam = ['13,104,036,080.615', 'Average machine.ram'];

await retry.try(async function tryingForTime() {
const metricValue = await PageObjects.wizard.getMetric();
expect(avgMachineRam).to.eql(metricValue);
});
});

it('should clear visualization when field is deleted', async () => {
await PageObjects.wizard.removeField('metric', 0);

await retry.try(async function tryingForTime() {
const isEmptyWorkspace = await PageObjects.wizard.isEmptyWorkspace();
expect(isEmptyWorkspace).to.be(true);
});
});
});
}
51 changes: 51 additions & 0 deletions test/functional/apps/wizard/_experimental_vis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import expect from '@osd/expect';
import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../src/plugins/visualizations/common/constants';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService, getPageObjects }: FtrProviderContext) {
const PageObjects = getPageObjects(['visualize', 'wizard']);
const log = getService('log');
const opensearchDashboardsServer = getService('opensearchDashboardsServer');

describe('experimental settings for wizard app ', function () {
it('should show an notification when creating wizard visualization', async () => {
log.debug('navigateToApp visualize');
await PageObjects.visualize.navigateToNewVisualization();
await PageObjects.visualize.waitForVisualizationSelectPage();

// Try to find the wizard Vis type.
const wizardVisTypeExists = await PageObjects.visualize.hasVisType('wizard');
expect(wizardVisTypeExists).to.be(true);

// Create a new visualization
await PageObjects.visualize.clickVisType('wizard');

// Check that the experimental banner is there and state that this is experimental
const info = await PageObjects.wizard.getExperimentalInfo();
expect(await info.getVisibleText()).to.contain('experimental');
});

it('should not be available in the picker when disabled', async () => {
log.debug('navigateToApp visualize');
await opensearchDashboardsServer.uiSettings.replace({
[VISUALIZE_ENABLE_LABS_SETTING]: false,
});
await PageObjects.visualize.navigateToNewVisualization();
await PageObjects.visualize.waitForVisualizationSelectPage();

// Try to find the wizard Vis type.
const wizardVisTypeExists = await PageObjects.visualize.hasVisType('wizard');
expect(wizardVisTypeExists).to.be(false);
});

after(async () => {
// unset the experimental ui setting
await opensearchDashboardsServer.uiSettings.unset(VISUALIZE_ENABLE_LABS_SETTING);
});
});
}
39 changes: 39 additions & 0 deletions test/functional/apps/wizard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { FtrProviderContext } from '../../ftr_provider_context.d';
import { UI_SETTINGS } from '../../../../src/plugins/data/common';

export default function ({ getService, loadTestFile }: FtrProviderContext) {
const browser = getService('browser');
const log = getService('log');
const opensearchArchiver = getService('opensearchArchiver');
const opensearchDashboardsServer = getService('opensearchDashboardsServer');

describe('wizard app', function () {
this.tags('ciGroup13');

before(async function () {
log.debug('Starting wizard before method');
await browser.setWindowSize(1280, 800);
await opensearchArchiver.loadIfNeeded('logstash_functional');
await opensearchArchiver.loadIfNeeded('long_window_logstash');
await opensearchArchiver.loadIfNeeded('visualize');
await opensearchDashboardsServer.uiSettings.replace({
defaultIndex: 'logstash-*',
[UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN]: '0,0.[000]b',
});
});

after(async () => {
await opensearchArchiver.unload('logstash_functional');
await opensearchArchiver.unload('long_window_logstash');
await opensearchArchiver.unload('visualize');
});

loadTestFile(require.resolve('./_base'));
loadTestFile(require.resolve('./_experimental_vis'));
});
}
5 changes: 5 additions & 0 deletions test/functional/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default async function ({ readConfigFile }) {
require.resolve('./apps/status_page'),
require.resolve('./apps/timeline'),
require.resolve('./apps/visualize'),
require.resolve('./apps/wizard'),
],
pageObjects,
services,
Expand Down Expand Up @@ -91,6 +92,10 @@ export default async function ({ readConfigFile }) {
pathname: '/app/visualize',
hash: '/',
},
wizard: {
pathname: '/app/wizard',
hash: '/',
},
dashboard: {
pathname: '/app/dashboards',
hash: '/list',
Expand Down
2 changes: 2 additions & 0 deletions test/functional/page_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { TimePickerProvider } from './time_picker';
import { TimelinePageProvider } from './timeline_page';
import { VisualBuilderPageProvider } from './visual_builder_page';
import { VisualizePageProvider } from './visualize_page';
import { WizardPageProvider } from './wizard_page';
import { VisualizeEditorPageProvider } from './visualize_editor_page';
import { VisualizeChartPageProvider } from './visualize_chart_page';
import { TileMapPageProvider } from './tile_map_page';
Expand All @@ -68,6 +69,7 @@ export const pageObjects = {
timePicker: TimePickerProvider,
visualBuilder: VisualBuilderPageProvider,
visualize: VisualizePageProvider,
wizard: WizardPageProvider,
visEditor: VisualizeEditorPageProvider,
visChart: VisualizeChartPageProvider,
tileMap: TileMapPageProvider,
Expand Down
Loading

0 comments on commit 63e0bc4

Please sign in to comment.