Skip to content

Commit

Permalink
Merge branch 'main' into testid-66
Browse files Browse the repository at this point in the history
Signed-off-by: Anan Zhuang <ananzh@amazon.com>
  • Loading branch information
ananzh authored Feb 14, 2025
2 parents 95e8747 + 4e21765 commit 6666f47
Show file tree
Hide file tree
Showing 6 changed files with 350 additions and 3 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/9307.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test:
- Add all recent queries tests ([#9307](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9307))
7 changes: 7 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { defineConfig } from 'cypress';
import webpackPreprocessor from '@cypress/webpack-preprocessor';
// TODO: import { paste } from 'copy-paste';

module.exports = defineConfig({
defaultCommandTimeout: 60000,
Expand Down Expand Up @@ -76,6 +77,12 @@ function setupNodeEvents(
webpackOptions,
})
);
// TODO: Define the custom task to read clipboard
/* on('task', {
readClipboard() {
return paste(); // Return the clipboard content
},
});*/

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

import {
DATASOURCE_NAME,
INDEX_PATTERN_WITH_TIME,
INDEX_WITH_TIME_1,
} from '../../../../../utils/apps/constants';
import { BASE_PATH, PATHS } from '../../../../../utils/constants';
import {
getRandomizedWorkspaceName,
setDatePickerDatesAndSearchIfRelevant,
generateAllTestConfigurations,
} from '../../../../../utils/apps/query_enhancements/shared';
import {
generateRecentQueriesTestConfiguration,
BaseQuery,
TestQueries,
//TODO: QueryRegex,
} from '../../../../../utils/apps/query_enhancements/recent_queries';
import { prepareTestSuite } from '../../../../../utils/helpers';

const workspace = getRandomizedWorkspaceName();
const runRecentQueryTests = () => {
describe('recent queries spec', { testIsolation: true }, () => {
const index = INDEX_PATTERN_WITH_TIME.replace('*', '');
beforeEach(() => {
// Load test data
cy.osd.setupTestData(
PATHS.SECONDARY_ENGINE,
['cypress/fixtures/query_enhancements/data_logs_1/data_logs_small_time_1.mapping.json'],
['cypress/fixtures/query_enhancements/data_logs_1/data_logs_small_time_1.data.ndjson']
);

// Add data source
cy.osd.addDataSource({
name: DATASOURCE_NAME,
url: `${PATHS.SECONDARY_ENGINE}`,
authType: 'no_auth',
});
// Create workspace
cy.deleteWorkspaceByName(workspace);
cy.visit('/app/home');
cy.osd.createInitialWorkspaceWithDataSource(DATASOURCE_NAME, workspace);
cy.createWorkspaceIndexPatterns({
workspaceName: workspace,
indexPattern: index,
timefieldName: 'timestamp',
indexPatternHasTimefield: true,
dataSource: DATASOURCE_NAME,
isEnhancement: true,
});

cy.navigateToWorkSpaceSpecificPage({
url: BASE_PATH,
workspaceName: workspace,
page: 'discover',
isEnhancement: true,
});
});

afterEach(() => {
cy.deleteWorkspaceByName(workspace);
cy.osd.deleteDataSourceByName(DATASOURCE_NAME);
// TODO: Modify deleteIndex to handle an array of index and remove hard code
cy.osd.deleteIndex(INDEX_WITH_TIME_1);
});

generateAllTestConfigurations(generateRecentQueriesTestConfiguration)
.filter(Boolean) // removes undefined values
.forEach((config) => {
it(`check max queries for ${config.testName}`, () => {
cy.setDataset(config.dataset, DATASOURCE_NAME, config.datasetType);
cy.setQueryLanguage(config.language);
setDatePickerDatesAndSearchIfRelevant(config.language);
const currentLang = BaseQuery[config.datasetType][config.language];
const currentBaseQuery = currentLang.query;
const currentWhereStatement = currentLang.where;
TestQueries.forEach((query) => {
cy.setQueryEditor(
currentBaseQuery + config.dataset + currentWhereStatement + query,
{},
true
);
});
cy.getElementByTestId('queryEditorFooterToggleRecentQueriesButton').click({
force: true,
});
// only 10 of the 11 queries should be displayed
cy.getElementByTestIdLike('row-').should('have.length', 10);
const reverseList = [...TestQueries].reverse();
const steps = [
{
// only check the table
action: () => {},
},
{
// check table after changing language and returning to the language under test
action: () => {
cy.setQueryLanguage(config.oppositeLang);
cy.setQueryLanguage(config.language);
cy.wrap(null).then(() => {
// force Cypress to run this method in order
reverseList.unshift(config.defaultQuery);
});
},
},
{
// check table after changing dataset and returning to the dataset under test
action: () => {
cy.setIndexAsDataset(
config.alternativeDataset,
DATASOURCE_NAME,
config.language,
"I don't want to use the time filter"
);
cy.setDataset(config.dataset, DATASOURCE_NAME, config.datasetType);
cy.wrap(null).then(() => {
// force Cypress to run this method in order
reverseList.unshift(config.defaultQuery);
});
},
},
{
// check table after visiting a different URL and coming back to the workspace
action: () => {
cy.visit('/app/workspace_initial');
cy.navigateToWorkSpaceSpecificPage({
url: BASE_PATH,
workspaceName: workspace,
page: 'discover',
isEnhancement: true,
});
cy.getElementByTestId('queryEditorFooterToggleRecentQueriesButton').click({
force: true,
});
},
},
];
steps.forEach(({ action }, stepIndex) => {
action();
cy.getElementByTestIdLike('row-').each(($row, rowIndex) => {
let expectedQuery = '';
if (rowIndex === 1 && stepIndex >= 2) {
expectedQuery =
currentBaseQuery + config.alternativeDataset + reverseList[rowIndex];
} else if (rowIndex === 0 && stepIndex >= 1) {
expectedQuery = currentBaseQuery + config.dataset + reverseList[rowIndex];
} else {
expectedQuery =
currentBaseQuery + config.dataset + currentWhereStatement + reverseList[rowIndex];
}
expect($row.text()).to.contain(expectedQuery);
});
});
});

it(`check duplicate query for ${config.testName}`, () => {
cy.setDataset(config.dataset, DATASOURCE_NAME, config.datasetType);
cy.setQueryLanguage(config.language);
setDatePickerDatesAndSearchIfRelevant(config.language);
const currentLang = BaseQuery[config.datasetType][config.language];
const currentBaseQuery = currentLang.query;
const currentWhereStatement = currentLang.where;
const testQueries = [
currentBaseQuery + config.dataset + currentWhereStatement + ' status_code = 504', // valid
currentBaseQuery + config.dataset + currentWhereStatement, // invalid
];
testQueries.forEach((query, index) => {
cy.setQueryEditor(query, {}, true);
cy.setQueryEditor(query, {}, true);
if (!index)
// it remains expanded for the second iteration, no need to expand it again
cy.getElementByTestId('queryEditorFooterToggleRecentQueriesButton').click({
force: true,
});
cy.getElementByTestIdLike('row-').should('have.length', index + 2);
});
});

/* TODO: adding these tests requires adding a dependency OR customizing the execSync function
//const { execSync } = require('child_process');
//console.log(execSync('xclip -selection clipboard -o').toString().trim()); // for Linux
//Caveat: the commands for reading the system's clipboard is OS-dependent.
it(`check running and copying recent queries for ${config.testName}`, () => {
cy.setDataset(config.dataset, DATASOURCE_NAME, config.datasetType);
cy.setQueryLanguage(config.language);
setDatePickerDatesAndSearchIfRelevant(config.language);
// Precondition: run some queries first
const currentLang = BaseQuery[config.datasetType][config.language];
const currentBaseQuery = currentLang.query + config.dataset + currentLang.where;
const queries = [...TestQueries].splice(0, 3);
queries.forEach((query) => {
cy.setQueryEditor(currentBaseQuery + query, {}, true);
});
cy.getElementByTestId('queryEditorFooterToggleRecentQueriesButton').click({
force: true,
});
const expectedQuery = currentBaseQuery + queries[0];
cy.getElementByTestIdLike('row-') // check query in original position
.eq(2)
.focus()
.then(($row) => {
expect($row.text()).to.include(expectedQuery);
});
cy.getElementByTestId('action-run').eq(2).focus().click({ force: true }); // run query again
cy.wait(2000);
cy.getElementByTestIdLike('row-') // check query in altered position
.eq(0)
.focus()
.then(($row) => {
expect($row.text()).to.include(expectedQuery);
});
cy.getElementByTestIdLike('row-') // copy another query to clipboard
.eq(1)
.focus()
.then(($row) => {
cy.get('[aria-label="Copy recent query"]').eq(1).click({ force: true });
cy.wait(1000); // Give the clipboard some time to update
const expectedQuery = $row.text().replace(QueryRegex[config.language], '$1');
cy.get('[aria-label="Copy recent query"]').eq(1).focus();
cy.task('readClipboard').then((clipboardText) => {
expect(clipboardText).to.eq(expectedQuery);
});
});
});*/
});
});
};

prepareTestSuite('Recent Query', runRecentQueryTests);
97 changes: 97 additions & 0 deletions cypress/utils/apps/query_enhancements/recent_queries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { QueryLanguages } from './constants';

export const RecentQueriesDataTypes = {
INDEX_PATTERN: {
name: 'INDEX_PATTERN',
supportedLanguages: [QueryLanguages.SQL, QueryLanguages.PPL],
},
INDEXES: {
name: 'INDEXES',
supportedLanguages: [QueryLanguages.SQL, QueryLanguages.PPL],
},
};

export const BaseQuery = {
INDEX_PATTERN: {
'OpenSearch SQL': {
query: `SELECT * FROM `,
where: ' WHERE ',
},
PPL: {
query: `source = `,
where: ' | where ',
},
},
INDEXES: {
'OpenSearch SQL': {
query: `SELECT * FROM `,
where: ' WHERE ',
},
PPL: {
query: `source = `,
where: ' | where ',
},
},
};

export const TestQueries = [
'bytes_transferred >',
'bytes_transferred < 8000',
'bytes_transferred > 8000',
'status_code = 404',
'status_code = 501',
'status_code = 503',
'status_code = 400',
'status_code = 401',
'status_code = 403',
'status_code = 200',
'event_sequence_number > 10000000',
];

/* // TODO
export const QueryRegex = {
PPL: /.*?(source .*? 8000)(?:.*)/s,
'OpenSearch SQL': /.*?(SELECT .*? 8000)(?:.*)/s,
};*/

/**
* The configurations needed for recent queries tests
* @typedef {Object} RecentQueriesFilteringTestConfig
* @property {string} dataset - the dataset name to use
* @property {QueryEnhancementDataset} datasetType - the type of dataset
* @property {QueryEnhancementLanguage} language - the name of query language as it appears in the dashboard app
* @property {string} testName - the phrase to add to the test case's title
*/

/**
* Returns the SavedSearchTestConfig for the provided dataset, datasetType, and language
* @param {string} dataset - the dataset name
* @param {QueryEnhancementDataset} datasetType - the type of the dataset
* @param {QueryEnhancementLanguageData} language - the relevant data for the query language to use
* @returns {RecentQueriesFilteringTestConfig}
*/
export const generateRecentQueriesTestConfiguration = (dataset, datasetType, language) => {
if (language.name !== 'PPL' && language.name !== 'OpenSearch SQL') {
return; // undefined
}
const oppositeLang = {
PPL: 'OpenSearch SQL',
'OpenSearch SQL': 'PPL',
};
const defaultQuery = language.name === 'PPL' ? '' : ' LIMIT 10';
const customDatasetType = RecentQueriesDataTypes[datasetType].name;
return {
dataset,
datasetType: customDatasetType,
language: language.name,
oppositeLang: oppositeLang[language.name],
alternativeDataset: '.opensearch-sap-log-types-config',
defaultQuery: defaultQuery,
testName: `dataset: ${datasetType} and language: ${language.name}`,
};
};
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@
"osd:ciGroup11": "echo \"cypress/integration/dashboard_sanity_test.spec.ts\"",
"osd:ciGroup12": "BASE_PATH='cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements' && echo \"$BASE_PATH/language_specific_display.spec.js,$BASE_PATH/time_range_selection.spec.js,$BASE_PATH/saved_queries.spec.js,$BASE_PATH/saved_search_in_dashboards.spec.js\"",
"osd:ciGroup13": "BASE_PATH='cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements' && echo \"$BASE_PATH/caching.spec.js,$BASE_PATH/field_display_filtering.spec.js,$BASE_PATH/inspect.spec.js,$BASE_PATH/shared_links.spec.js,$BASE_PATH/table.spec.js\"",
"osd:ciGroup14": "BASE_PATH='cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements' && echo \"$BASE_PATH/s3_dataset.spec.js,$BASE_PATH/advanced_settings.spec.js,$BASE_PATH/queries_more.spec.js\"",
"osd:ciGroup15": "BASE_PATH='cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements' && echo \"$BASE_PATH/autocomplete_switch.spec.js,$BASE_PATH/autocomplete_ui.spec.js,$BASE_PATH/autocomplete_query.spec.js,$BASE_PATH/sidebar.spec.js,$BASE_PATH/histogram_interaction.spec.js\"",
"osd:ciGroup14": "BASE_PATH='cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements' && echo \"$BASE_PATH/s3_dataset.spec.js,$BASE_PATH/advanced_settings.spec.js,$BASE_PATH/queries_more.spec.js,histogram_interaction.spec.js\"",
"osd:ciGroup15": "BASE_PATH='cypress/integration/core_opensearch_dashboards/opensearch_dashboards/apps/query_enhancements' && echo \"$BASE_PATH/autocomplete_switch.spec.js,$BASE_PATH/autocomplete_ui.spec.js,$BASE_PATH/autocomplete_query.spec.js,$BASE_PATH/sidebar.spec.js,$BASE_PATH/recent_queries.spec.js\"",
"generate:opensearchsqlantlr": "./node_modules/antlr4ng-cli/index.js -Dlanguage=TypeScript -o ./src/plugins/data/public/antlr/opensearch_sql/.generated -visitor -no-listener -Xexact-output-dir ./src/plugins/data/public/antlr/opensearch_sql/grammar/OpenSearchSQLLexer.g4 ./src/plugins/data/public/antlr/opensearch_sql/grammar/OpenSearchSQLParser.g4",
"generate:opensearchpplantlr": "./node_modules/antlr4ng-cli/index.js -Dlanguage=TypeScript -o ./src/plugins/data/public/antlr/opensearch_ppl/.generated -visitor -no-listener -Xexact-output-dir ./src/plugins/data/public/antlr/opensearch_ppl/grammar/OpenSearchPPLLexer.g4 ./src/plugins/data/public/antlr/opensearch_ppl/grammar/OpenSearchPPLParser.g4"
},
Expand Down Expand Up @@ -198,6 +198,7 @@
"chokidar": "^3.4.2",
"color": "1.0.3",
"commander": "^3.0.2",
"copy-paste": "^1.5.3",
"core-js": "^3.6.5",
"deep-freeze-strict": "^1.1.1",
"del": "^6.1.1",
Expand Down
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6203,6 +6203,13 @@ copy-concurrently@^1.0.0:
rimraf "^2.5.4"
run-queue "^1.0.0"

copy-paste@^1.5.3:
version "1.5.3"
resolved "https://registry.yarnpkg.com/copy-paste/-/copy-paste-1.5.3.tgz#ee9e775858d05c57a91ea2a063188ab686840797"
integrity sha512-qOnFo+8l8vemGmdcoCiD7gPTefkXEg2rivYE+EBtuKOj754eFivkGhGAM9e/xqShrpuVE11evSxGnHwVAUK1Iw==
dependencies:
iconv-lite "^0.4.8"

copy-to-clipboard@^3.2.0:
version "3.3.1"
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae"
Expand Down Expand Up @@ -9939,7 +9946,7 @@ hyphenate-style-name@^1.0.2:
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==

iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@^0.4.8, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
Expand Down

0 comments on commit 6666f47

Please sign in to comment.