-
Notifications
You must be signed in to change notification settings - Fork 22
NETOBSERV-2252: Fix ConsolePlugin cypress tests #1042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8c71840
96afab6
4198915
95e5c0f
5639079
308b4b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -164,13 +164,11 @@ Cypress.Commands.add('changeTimeRange', (name, topology) => { | |
cy.checkContent(topology); | ||
}); | ||
|
||
Cypress.Commands.add('changeMetricFunction', (name) => { | ||
Cypress.Commands.add('clickShowDuplicates', () => { | ||
cy.showAdvancedOptions(); | ||
cy.showDisplayOptions(); | ||
|
||
cy.get('#metricFunction-dropdown').click(); | ||
cy.get('.pf-v5-c-menu__content').contains(name).click(); | ||
cy.get('[data-layer-id="default"]').children().its('length').should('be.gte', 5); | ||
cy.get('#table-display-dropdown').contains('Show duplicates').click(); | ||
cy.checkContent(); | ||
}); | ||
|
||
Cypress.Commands.add('changeMetricType', (name) => { | ||
|
@@ -191,27 +189,107 @@ Cypress.Commands.add('checkRecordField', (field, name, values) => { | |
}); | ||
}); | ||
|
||
|
||
Cypress.Commands.add('setupNetworkIdleTracking', (method: string = 'GET', urlPattern: string = '/api/**') => { | ||
cy.wrap({ | ||
requestCount: 0, | ||
lastRequestTime: 0, | ||
startTime: Date.now() | ||
}).as('networkIdleTracker'); | ||
|
||
cy.intercept(method, urlPattern, (req) => { | ||
cy.get('@networkIdleTracker').then((tracker: Cypress.networkIdleTracker) => { | ||
tracker.requestCount++; | ||
tracker.lastRequestTime = Date.now(); | ||
}); | ||
req.continue(); | ||
}).as('networkIdleActivity'); | ||
}); | ||
|
||
|
||
Cypress.Commands.add('waitForNetworkIdle', (idleTime: number = 3000, timeout: number = 120000) => { | ||
cy.get('@networkIdleTracker', { timeout: timeout }) | ||
.then((tracker: Cypress.networkIdleTracker) => { | ||
const startTime = Date.now(); | ||
|
||
const checkIdleCondition = () => { | ||
const now = Date.now(); | ||
|
||
if (tracker.requestCount > 0 && (now - tracker.lastRequestTime) >= idleTime) { | ||
return true; | ||
} | ||
|
||
if (tracker.requestCount === 0 && (now - startTime) >= idleTime) { | ||
oliver-smakal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return true; | ||
} | ||
|
||
if (now - startTime > timeout) { | ||
throw new Error('Timed out waiting for network idle.'); | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
const pollUntilIdle = () => { | ||
const isIdle = checkIdleCondition(); | ||
|
||
if (isIdle) { | ||
return; | ||
} else { | ||
return cy.wait(1000, { log: false }).then(pollUntilIdle); | ||
} | ||
}; | ||
|
||
return cy.then(pollUntilIdle); | ||
}); | ||
}); | ||
|
||
declare global { | ||
namespace Cypress { | ||
interface Chainable { | ||
openNetflowTrafficPage(clearCache?: boolean): Chainable<void> | ||
showAdvancedOptions(): Chainable<Element> | ||
showDisplayOptions(): Chainable<Element> | ||
checkPanels(panels?: number): Chainable<Element> | ||
openPanelsModal(): Chainable<Element> | ||
checkColumns(groups?: number, cols?: number): Chainable<Element> | ||
openColumnsModal(): Chainable<Element> | ||
selectPopupItems(id: string, names: string[]): Chainable<Element> | ||
checkPopupItems(id: string, ids: string[]): Chainable<Element> | ||
sortColumn(name: string): Chainable<Element> | ||
dropdownSelect(id: string, name: string): Chainable<Element> | ||
checkContent(topology?: boolean): Chainable<Element> | ||
addFilter(filter: string, value: string, topology?: boolean): Chainable<Element> | ||
changeQueryOption(name: string, topology?: boolean): Chainable<Element> | ||
changeTimeRange(name: string, topology?: boolean): Chainable<Element> | ||
changeMetricFunction(name: string): Chainable<Element> | ||
changeMetricType(name: string): Chainable<Element> | ||
checkRecordField(field: string, name: string, values: string[]) | ||
showAdvancedOptions(): Chainable<void> | ||
showDisplayOptions(): Chainable<void> | ||
checkPanels(panels?: number): Chainable<void> | ||
openPanelsModal(): Chainable<void> | ||
checkColumns(groups?: number, cols?: number): Chainable<void> | ||
openColumnsModal(): Chainable<void> | ||
selectPopupItems(id: string, names: string[]): Chainable<void> | ||
checkPopupItems(id: string, ids: string[]): Chainable<void> | ||
sortColumn(name: string): Chainable<void> | ||
dropdownSelect(id: string, name: string): Chainable<void> | ||
checkContent(topology?: boolean): Chainable<void> | ||
addFilter(filter: string, value: string, topology?: boolean): Chainable<void> | ||
changeQueryOption(name: string, topology?: boolean): Chainable<void> | ||
changeTimeRange(name: string, topology?: boolean): Chainable<void> | ||
changeMetricType(name: string): Chainable<void> | ||
checkRecordField(field: string, name: string, values: string[]): Chainable<void> | ||
clickShowDuplicates():Chainable<void> | ||
|
||
/** | ||
* Sets up network interception to track active requests for idle detection. | ||
* This command *must* be called before `cy.waitForNetworkIdle` | ||
* | ||
* @param method HTTP method to intercept (default: 'GET') | ||
* @param urlPattern URL pattern to intercept (default: '/api/**') | ||
*/ | ||
setupNetworkIdleTracking(method?: string, urlPattern?: string): Chainable<void> | ||
|
||
/** | ||
* Waits until no intercepted requests (matching the patterns | ||
* set in `setupNetworkIdleTracking`) have been active for `idleTime`, | ||
* or until the `timeout` is reached. | ||
* | ||
* @param idleTime How long the network must be idle (in ms) | ||
* @param timeout Total time to wait before timing out (in ms) | ||
*/ | ||
waitForNetworkIdle(idleTime?: number, timeout?: number): Chainable<void> | ||
|
||
networkIdleTracker: { | ||
requestCount: number; | ||
lastRequestTime: number; | ||
startTime: number; | ||
}; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of the method signature definitions in here:
Seems to not be matching the signatures of the function declaratinons. For example:
has not return, but the return type of Am I missing something or is this wrong? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that looks like bad copy pastes 😉 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. interesting, I guess our custom commands have that problem too :) , mostly from copy pasting the signatures :). We mostly use custom commands to abstract set of common of UI interactions. thanks for spotting that. |
||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am curious, how this is different than simply intercepting for
/api/flow/metrics
request and waiting for call to happen, like we have here:https://github.com/openshift/openshift-tests-private/blob/master/frontend/views/netflow-page.ts#L4-L7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the interception you are referencing would be the easiest way to solve it, if there would be only one (or a few requests) that would be triggered.
The problem I ran into is there are like 60 request done on which it is necessary to wait. In theory, it could be implemented in a way that I count all the requests that are being done and wait for the exact amount to be finished, but I believe that could be quite easy to break if something in the implementation of how the data is fetched, which is not really a subject this test case.
So essentially this implementation waiting until the network is idle for some time. Once it is idle, it assumes the all of the data-fetching is done and would stop waiting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it, thanks for the explanation.