-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…1691) (#1692) Signed-off-by: Chenyang Ji <cyji@amazon.com> (cherry picked from commit 028e8d8) Co-authored-by: Chenyang Ji <chenyang.yale@gmail.com>
- Loading branch information
1 parent
221590d
commit db2594d
Showing
12 changed files
with
711 additions
and
0 deletions.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
.github/workflows/query-insights-dashboards-e2e-workflow.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Query Insights Dashboards Release tests workflow in Bundled OpenSearch Dashboards | ||
on: | ||
pull_request: | ||
branches: [ '**' ] | ||
jobs: | ||
changes: | ||
runs-on: ubuntu-latest | ||
outputs: | ||
tests: ${{ steps.filter.outputs.tests }} | ||
steps: | ||
- uses: dorny/paths-filter@v2 | ||
id: filter | ||
with: | ||
filters: | | ||
tests: | ||
- 'cypress/**/query-insights-dashboards/**' | ||
tests: | ||
needs: changes | ||
if: ${{ needs.changes.outputs.tests == 'true' }} | ||
uses: ./.github/workflows/release-e2e-workflow-template.yml | ||
with: | ||
test-name: Query Insights Dashboards | ||
test-command: env CYPRESS_NO_COMMAND_LOG=1 yarn cypress:run-with-security --browser chromium --spec 'cypress/integration/plugins/query-insights-dashboards/*' |
43 changes: 43 additions & 0 deletions
43
cypress/fixtures/plugins/query-insights-dashboards/sample_document.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"@timestamp": "2099-11-15T13:12:00", | ||
"message": "this is document 0", | ||
"user": { | ||
"id": "user1", | ||
"name": "John Doe", | ||
"email": "john.doe@example.com", | ||
"roles": ["admin", "editor"] | ||
}, | ||
"request": { | ||
"method": "GET", | ||
"url": "/api/v1/resource", | ||
"status": 200, | ||
"response_time_ms": 123, | ||
"headers": { | ||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", | ||
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5..." | ||
} | ||
}, | ||
"location": { | ||
"ip": "192.168.1.1", | ||
"city": "Seattle", | ||
"region": "Washington", | ||
"country": "US" | ||
}, | ||
"application": { | ||
"name": "OpenSearch Dashboard", | ||
"version": "2.8.0", | ||
"environment": "production" | ||
}, | ||
"event": { | ||
"id": "event123", | ||
"type": "user_action", | ||
"outcome": "success", | ||
"reason": null | ||
}, | ||
"tags": ["login", "dashboard", "analytics"], | ||
"metrics": { | ||
"cpu_usage": 2.4, | ||
"memory_usage": 512, | ||
"disk_space_remaining": 1048576 | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
cypress/integration/plugins/query-insights-dashboards/1_top_queries.cy.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import sampleDocument from '../../../fixtures/plugins/query-insights-dashboards/sample_document.json'; | ||
import { QUERY_INSIGHTS_METRICS } from '../../../utils/constants'; | ||
|
||
// Name of the test index used in tests | ||
const indexName = 'sample_index'; | ||
|
||
/** | ||
Helper function to clean up the environment: | ||
- Deletes the test index. | ||
- Disables the top queries features. | ||
*/ | ||
const clearAll = () => { | ||
cy.deleteIndexByName(indexName); | ||
cy.disableTopQueries(QUERY_INSIGHTS_METRICS.LATENCY); | ||
cy.disableTopQueries(QUERY_INSIGHTS_METRICS.CPU); | ||
cy.disableTopQueries(QUERY_INSIGHTS_METRICS.MEMORY); | ||
}; | ||
|
||
describe('Query Insights Dashboard', () => { | ||
// Setup before each test | ||
beforeEach(() => { | ||
clearAll(); | ||
cy.createIndexByName(indexName, sampleDocument); | ||
cy.enableTopQueries(QUERY_INSIGHTS_METRICS.LATENCY); | ||
cy.enableTopQueries(QUERY_INSIGHTS_METRICS.CPU); | ||
cy.enableTopQueries(QUERY_INSIGHTS_METRICS.MEMORY); | ||
cy.searchOnIndex(indexName); | ||
// wait for 1s to avoid same timestamp | ||
cy.wait(1000); | ||
cy.searchOnIndex(indexName); | ||
cy.wait(1000); | ||
cy.searchOnIndex(indexName); | ||
// waiting for the query insights queue to drain | ||
cy.wait(10000); | ||
cy.navigateToOverview(); | ||
}); | ||
|
||
/** | ||
* Validate the main overview page loads correctly | ||
*/ | ||
it('should display the main overview page', () => { | ||
cy.get('.euiBasicTable').should('be.visible'); | ||
cy.contains('Query insights - Top N queries'); | ||
cy.url().should('include', '/queryInsights'); | ||
|
||
// should display the query table on the overview page | ||
cy.get('.euiBasicTable').should('be.visible'); | ||
cy.get('.euiTableHeaderCell').should('have.length.greaterThan', 0); | ||
// should have top n queries displayed on the table | ||
cy.get('.euiTableRow').should('have.length.greaterThan', 0); | ||
}); | ||
|
||
it('should switch between tabs', () => { | ||
// Click Configuration tab | ||
cy.getElementByText('.euiTab', 'Configuration').click({ force: true }); | ||
cy.contains('Query insights - Configuration'); | ||
cy.url().should('include', '/configuration'); | ||
|
||
// Click back to Query Insights tab | ||
cy.getElementByText('.euiTab', 'Top N queries').click({ force: true }); | ||
cy.url().should('include', '/queryInsights'); | ||
}); | ||
|
||
it('should filter queries', () => { | ||
cy.get('.euiFieldSearch').should('be.visible'); | ||
cy.get('.euiFieldSearch').type('sample_index'); | ||
// Add assertions for filtered results | ||
cy.get('.euiTableRow').should('have.length.greaterThan', 0); | ||
}); | ||
|
||
it('should clear the search input and reset results', () => { | ||
cy.get('.euiFieldSearch').type('random_string'); | ||
cy.get('.euiTableRow').should('have.length.greaterThan', 0); | ||
cy.get('.euiFieldSearch').clear(); | ||
cy.get('.euiTableRow').should('have.length.greaterThan', 0); // Validate reset | ||
}); | ||
|
||
it('should display a message when no top queries are found', () => { | ||
clearAll(); // disable top n queries | ||
// waiting for the query insights queue to drain | ||
cy.wait(10000); | ||
cy.reload(); | ||
cy.contains('No items found'); | ||
}); | ||
|
||
after(() => clearAll()); | ||
}); |
148 changes: 148 additions & 0 deletions
148
cypress/integration/plugins/query-insights-dashboards/2_query_details.cy.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import sampleDocument from '../../../fixtures/plugins/query-insights-dashboards/sample_document.json'; | ||
import { QUERY_INSIGHTS_METRICS } from '../../../utils/constants'; | ||
|
||
const indexName = 'sample_index'; | ||
|
||
const clearAll = () => { | ||
cy.deleteIndexByName(indexName); | ||
cy.disableTopQueries(QUERY_INSIGHTS_METRICS.LATENCY); | ||
cy.disableTopQueries(QUERY_INSIGHTS_METRICS.CPU); | ||
cy.disableTopQueries(QUERY_INSIGHTS_METRICS.MEMORY); | ||
}; | ||
|
||
describe('Top Queries Details Page', () => { | ||
beforeEach(() => { | ||
clearAll(); | ||
cy.createIndexByName(indexName, sampleDocument); | ||
cy.enableTopQueries(QUERY_INSIGHTS_METRICS.LATENCY); | ||
cy.enableTopQueries(QUERY_INSIGHTS_METRICS.CPU); | ||
cy.enableTopQueries(QUERY_INSIGHTS_METRICS.MEMORY); | ||
cy.searchOnIndex(indexName); | ||
cy.searchOnIndex(indexName); | ||
cy.searchOnIndex(indexName); | ||
// waiting for the query insights queue to drain | ||
cy.wait(10000); | ||
cy.navigateToOverview(); | ||
cy.wait(10000); | ||
cy.get('.euiTableRow').first().find('button').first().trigger('mouseover'); | ||
cy.wait(1000); | ||
cy.get('.euiTableRow').first().find('button').first().click(); // Navigate to details | ||
cy.wait(1000); | ||
}); | ||
|
||
it('should display correct details on the query details page', () => { | ||
// cy.get('.euiBasicTable a').first().click(); // Navigate to details | ||
cy.url().should('include', '/query-details'); | ||
// Validate the page title | ||
cy.get('h1').contains('Query details').should('be.visible'); | ||
// Validate the summary section | ||
cy.get('[data-test-subj="query-details-summary-section"]').should( | ||
'be.visible' | ||
); | ||
// Validate the presence of latency chart | ||
cy.get('[data-test-subj="query-details-latency-chart"]').should( | ||
'be.visible' | ||
); | ||
// Validate the presence of query source details section | ||
cy.get('[data-test-subj="query-details-source-section"]').should( | ||
'be.visible' | ||
); | ||
}); | ||
|
||
/** | ||
* Validate summary panel has valid labels | ||
*/ | ||
it('the summary panel should display correctly', () => { | ||
// Validate all field labels exist | ||
const fieldLabels = [ | ||
'Timestamp', | ||
'Latency', | ||
'CPU Time', | ||
'Memory Usage', | ||
'Indices', | ||
'Search Type', | ||
'Coordinator Node ID', | ||
'Total Shards', | ||
]; | ||
fieldLabels.forEach((label) => { | ||
cy.get('.euiPanel').contains('h4', label).should('be.visible'); | ||
}); | ||
}); | ||
|
||
/** | ||
* Validate each field in the summary panel has valid content | ||
*/ | ||
it('should display correct values for all fields in the summary panel', () => { | ||
cy.get('[data-test-subj="query-details-summary-section"]').within(() => { | ||
// Validate Timestamp | ||
cy.contains('h4', 'Timestamp') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.should('match', /\w{3} \d{2}, \d{4} @ \d{1,2}:\d{2}:\d{2} [AP]M/); | ||
// Validate Latency | ||
cy.contains('h4', 'Latency') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.should('match', /^\d+(\.\d{1,2})? ms$/); | ||
// Validate CPU Time | ||
cy.contains('h4', 'CPU Time') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.should('match', /^\d+(\.\d+)? ms$/); | ||
// Validate Memory Usage | ||
cy.contains('h4', 'Memory Usage') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.should('match', /^\d+(\.\d+)? B$/); | ||
// Validate Indices | ||
cy.contains('h4', 'Indices') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.should('not.be.empty'); | ||
// Validate Search Type | ||
cy.contains('h4', 'Search Type') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.should('equal', 'query then fetch'); | ||
// Validate Coordinator Node ID | ||
cy.contains('h4', 'Coordinator Node ID') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.should('not.be.empty'); | ||
// Validate Total Shards | ||
cy.contains('h4', 'Total Shards') | ||
.parent() | ||
.next() | ||
.invoke('text') | ||
.then((text) => { | ||
const shardCount = parseInt(text.trim(), 10); | ||
expect(shardCount).to.be.a('number').and.to.be.greaterThan(0); | ||
}); | ||
}); | ||
}); | ||
|
||
/** | ||
* Validate the latency chart interaction | ||
*/ | ||
it('should render the latency chart and allow interaction', () => { | ||
// Ensure the chart is visible | ||
cy.get('#latency').should('be.visible'); | ||
cy.get('.plot-container').should('be.visible'); | ||
// Simulate hover over the chart for a data point | ||
cy.get('#latency').trigger('mousemove', { clientX: 100, clientY: 100 }); | ||
}); | ||
|
||
after(() => clearAll()); | ||
}); |
Oops, something went wrong.