Skip to content

Commit

Permalink
[MDS] Add FT for Vega (#1329)
Browse files Browse the repository at this point in the history
* Add FT for Vega

Signed-off-by: Huy Nguyen <73027756+huyaboo@users.noreply.github.com>

* Separate test case logic + use no auth for ingesting data

Signed-off-by: Huy Nguyen <73027756+huyaboo@users.noreply.github.com>

* Address comments

Signed-off-by: Huy Nguyen <73027756+huyaboo@users.noreply.github.com>

---------

Signed-off-by: Huy Nguyen <73027756+huyaboo@users.noreply.github.com>
  • Loading branch information
huyaboo authored May 28, 2024
1 parent 35fcf98 commit ae5917c
Show file tree
Hide file tree
Showing 11 changed files with 20,346 additions and 0 deletions.
20,000 changes: 20,000 additions & 0 deletions cypress/fixtures/dashboard/opensearch_dashboards/vis_type_vega/vis-vega.data.txt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import vegaSpec from './test_utils/test_vega_spec.json';
import {
VEGA_INDEX_ID,
VEGA_PATH_INDEX_DATA,
VEGA_INDEX_START_TIME,
VEGA_INDEX_END_TIME,
VEGA_CREATE_URL,
VEGA_VIS_APP_PATH,
VEGA_INDEX_PATTERN,
} from '../../../../../utils/constants';
import { CURRENT_TENANT } from '../../../../../utils/commands';
import { DS_NO_AUTH_LABEL } from '../../../../../utils/dashboards/datasource-management-dashboards-plugin/constants';
import { updateVegaSpec } from './test_utils/utils';

if (Cypress.env('DATASOURCE_MANAGEMENT_ENABLED')) {
describe('Vega Visualization (MDS enabled)', () => {
before(() => {
CURRENT_TENANT.newTenant = 'global';
cy.fleshTenantSettings();
cy.deleteIndex(VEGA_INDEX_ID);
cy.bulkUploadDocs(VEGA_PATH_INDEX_DATA);

// Dashboards requires an index pattern to continue to the Create Visualization stage
cy.deleteIndexPattern(VEGA_INDEX_PATTERN);
cy.createIndexPattern(VEGA_INDEX_PATTERN, {
title: VEGA_INDEX_ID,
timeFieldName: 'timestamp',
});

cy.deleteDataSourceIndexNoAuth(VEGA_INDEX_ID);
cy.deleteAllDataSources();

// Create and setup datasource
cy.createDataSourceNoAuth();
cy.bulkUploadDocsToDataSourceNoAuth(VEGA_PATH_INDEX_DATA);

// Visit the page
cy.log('create a new vega visualization: ', VEGA_CREATE_URL);
cy.visit(VEGA_CREATE_URL);
cy.url().should('contain', VEGA_VIS_APP_PATH);

cy.setTopNavDate(VEGA_INDEX_START_TIME, VEGA_INDEX_END_TIME);

// Wait for page to load
cy.waitForLoader();
});

[
{
dataSourceName: DS_NO_AUTH_LABEL,
canvasExists: 'exist',
vegaVisMessagesExists: 'not.exist',
},
{
dataSourceName: 'non-existent datasource',
canvasExists: 'not.exist',
vegaVisMessagesExists: 'exist',
},
].forEach(({ dataSourceName, canvasExists, vegaVisMessagesExists }) => {
it(`should query data from ${dataSourceName} and resulting visualization should ${canvasExists}`, () => {
const updatedVegaSpec = updateVegaSpec({
dataSourceName,
indexName: VEGA_INDEX_ID,
isDataFieldAnArray: false,
spec: vegaSpec,
});

cy.vegaSetVegaSpec(updatedVegaSpec);
cy.vegaUpdateVisualization();

cy.get('canvas.marks').should(canvasExists);
cy.get('ul.vgaVis__messages').should(vegaVisMessagesExists);
});
});

it('should query from local cluster when data_source_name is not present', () => {
const updatedVegaSpec = updateVegaSpec({
indexName: VEGA_INDEX_ID,
isDataFieldAnArray: false,
spec: vegaSpec,
});

cy.vegaSetVegaSpec(updatedVegaSpec);
cy.vegaUpdateVisualization();

if (Cypress.env('DISABLE_LOCAL_CLUSTER')) {
// Visualization should not be drawn
cy.get('canvas.marks').should('not.exist');
cy.get('ul.vgaVis__messages').should('exist');
} else {
// Visualization should be drawn; correct visualizations do not have warning messages
cy.get('canvas.marks').should('exist');
cy.get('ul.vgaVis__messages').should('not.exist');
}
});

after(() => {
cy.deleteIndex(VEGA_INDEX_ID);
cy.deleteIndexPattern(VEGA_INDEX_PATTERN);
cy.deleteDataSourceIndexNoAuth(VEGA_INDEX_ID);
cy.deleteAllDataSources();
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"url": {
"index": "your_index_name",
"body": {
"size": 0,
"aggs": {
"age_groups": {
"terms": {
"field": "age"
},
"aggs": {
"avg_salary": {
"avg": {
"field": "salary"
}
}
}
}
}
}
},
"format": {
"property": "aggregations.age_groups.buckets"
}
},
"mark": "bar",
"encoding": {
"x": {
"field": "key",
"type": "ordinal"
},
"y": {
"field": "avg_salary.value",
"type": "quantitative"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { cloneDeep } from 'lodash';

export const updateVegaSpec = ({
dataSourceName,
indexName,
isDataFieldAnArray,
spec,
}) => {
const newSpec = cloneDeep(spec);
if (isDataFieldAnArray) {
if (dataSourceName) {
newSpec.data[0].url.data_source_name = dataSourceName;
}
newSpec.data[0].url.index = indexName;
} else {
if (dataSourceName) {
newSpec.data.url.data_source_name = dataSourceName;
}
newSpec.data.url.index = indexName;
}

return newSpec;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import vegaSpec from './test_utils/test_vega_spec.json';
import {
VEGA_INDEX_ID,
VEGA_PATH_INDEX_DATA,
VEGA_INDEX_START_TIME,
VEGA_INDEX_END_TIME,
VEGA_CREATE_URL,
VEGA_VIS_APP_PATH,
VEGA_INDEX_PATTERN,
} from '../../../../../utils/constants';
import { CURRENT_TENANT } from '../../../../../utils/commands';
import { updateVegaSpec } from './test_utils/utils';

if (!Cypress.env('DATASOURCE_MANAGEMENT_ENABLED')) {
describe('Vega Visualization (MDS disabled)', () => {
before(() => {
CURRENT_TENANT.newTenant = 'global';
cy.fleshTenantSettings();
cy.deleteIndex(VEGA_INDEX_ID);
cy.bulkUploadDocs(VEGA_PATH_INDEX_DATA);

// Dashboards requires an index pattern to continue to the Create Visualization stage
cy.deleteIndexPattern(VEGA_INDEX_PATTERN);
cy.createIndexPattern(VEGA_INDEX_PATTERN, {
title: VEGA_INDEX_ID,
timeFieldName: 'timestamp',
});

// Visit the page
cy.log('create a new vega visualization: ', VEGA_CREATE_URL);
cy.visit(VEGA_CREATE_URL);
cy.url().should('contain', VEGA_VIS_APP_PATH);

cy.setTopNavDate(VEGA_INDEX_START_TIME, VEGA_INDEX_END_TIME);

// Wait for page to load
cy.waitForLoader();
});

it('should throw an error when data_source_name is used', () => {
const updatedVegaSpec = updateVegaSpec({
dataSourceName: 'non-existent datasource',
indexName: VEGA_INDEX_ID,
isDataFieldAnArray: false,
spec: vegaSpec,
});

cy.vegaSetVegaSpec(updatedVegaSpec);
cy.vegaUpdateVisualization();

// Visualization shouldn't exist; banner should exist
cy.get('canvas.marks').should('not.exist');
cy.get('ul.vgaVis__messages').should('exist');
});

it('should query from local cluster when data_source_name is not present', () => {
const updatedVegaSpec = updateVegaSpec({
indexName: VEGA_INDEX_ID,
isDataFieldAnArray: false,
spec: vegaSpec,
});

cy.vegaSetVegaSpec(updatedVegaSpec);
cy.vegaUpdateVisualization();

// Visualization should be drawn; correct visualizations do not have warning messages
cy.get('canvas.marks').should('exist');
cy.get('ul.vgaVis__messages').should('not.exist');
});

after(() => {
cy.deleteIndex(VEGA_INDEX_ID);
cy.deleteIndexPattern(VEGA_INDEX_PATTERN);
});
});
}
1 change: 1 addition & 0 deletions cypress/utils/dashboards/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import './vis_builder/commands';
import './vis_type_table/commands';
import './vis_type_vega/commands';
import './vis-augmenter/commands';
import './data_explorer/commands';

Expand Down
1 change: 1 addition & 0 deletions cypress/utils/dashboards/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * from './vis_builder/constants';
export * from './vis_type_table/constants';
export * from './vis-augmenter/constants';
export * from './data_explorer/constants';
export * from './vis_type_vega/constants';
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,51 @@ Cypress.Commands.add('visitDataSourcesListingPage', () => {
{ timeout: 60000 }
);
});

Cypress.Commands.add(
'bulkUploadDocsToDataSourceNoAuth',
(fixturePath, index) => {
const sendBulkAPIRequest = (ndjson) => {
const url = index
? `${Cypress.env('remoteDataSourceNoAuthUrl')}/${index}/_bulk`
: `${Cypress.env('remoteDataSourceNoAuthUrl')}/_bulk`;
cy.log('bulkUploadDocs')
.request({
method: 'POST',
url,
headers: {
'content-type': 'application/json;charset=UTF-8',
'osd-xsrf': true,
},
body: ndjson,
})
.then((response) => {
if (response.body.errors) {
console.error(response.body.items);
throw new Error('Bulk upload failed');
}
});
};

cy.fixture(fixturePath, 'utf8').then((ndjson) => {
sendBulkAPIRequest(ndjson);
});

cy.request({
method: 'POST',
url: `${Cypress.env('remoteDataSourceNoAuthUrl')}/_all/_refresh`,
});
}
);

Cypress.Commands.add(
'deleteDataSourceIndexNoAuth',
(indexName, options = {}) => {
cy.request({
method: 'DELETE',
url: `${Cypress.env('remoteDataSourceNoAuthUrl')}/${indexName}`,
failOnStatusCode: false,
...options,
});
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const DS_API = {
CREATE_DATA_SOURCE: `${DS_API_PREFIX}/data-source`,
DELETE_DATA_SOURCE: `${DS_API_PREFIX}/data-source/`,
};
export const DS_NO_AUTH_LABEL = 'RemoteDataSourceNoAuth';

export const TIMEOUT_OPTS = { timeout: 60000 };
export const FORCE_CLICK_OPTS = { force: true };
Expand Down
20 changes: 20 additions & 0 deletions cypress/utils/dashboards/vis_type_vega/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
Cypress.Commands.add('vegaSetVegaSpec', (spec) => {
const stringifiedSpec = JSON.stringify(spec);
cy.get('.ace_text-input')
.first()
.focus()
.clear()
.focus()
.type(stringifiedSpec, {
delay: 0,
parseSpecialCharSequences: false,
});
});

Cypress.Commands.add('vegaUpdateVisualization', () => {
cy.contains('button', 'Update').click();
});
19 changes: 19 additions & 0 deletions cypress/utils/dashboards/vis_type_vega/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { BASE_PATH } from '../../base_constants';

// Data
export const VEGA_INDEX_DATA = 'vis-vega.data.txt';
export const VEGA_PATH_FIXTURE =
'dashboard/opensearch_dashboards/vis_type_vega/';
export const VEGA_PATH_INDEX_DATA = VEGA_PATH_FIXTURE + VEGA_INDEX_DATA;
export const VEGA_INDEX_START_TIME = 'Dec 31, 2021 @ 00:00:00.000';
export const VEGA_INDEX_END_TIME = 'Oct 2, 2022 @ 00:00:00.000';
export const VEGA_INDEX_ID = 'vis-vega';
export const VEGA_INDEX_PATTERN = 'index-pattern-vis-vega';

// App URL Paths
export const VEGA_VIS_APP_PATH = '/app/visualize';
export const VEGA_CREATE_URL = `${BASE_PATH}${VEGA_VIS_APP_PATH}#/create?type=vega`;

0 comments on commit ae5917c

Please sign in to comment.