Skip to content

Commit

Permalink
E2E Tests: Reduce default timeout (#10863)
Browse files Browse the repository at this point in the history
* e2e tests: reducedefault timeout to 10s

* Use timeouts in cluster manager test

* Fix timeout for cluster deletion

* Try even shorter timeout

* Revert back to 10s

* Address PR feedback

* Use common type for options

* Fix lint

* Fix lint - too many blank lines

* Increase timeout for terminal

* Improve reliability of the Istio tests

* Fix lint issues

* Fix typos in refactor to PO

* Fix typo in tab name

* Add resilience for the docs test

* Add timeout for extensions test

* Add test resilience for docs page

* Fix lint by removing trailing spaces

* Add test resilience

* Fix link opening exception handling

* Fix merge issue

* Fix whitespace

* Fix indentation

* Update extensions.spec.ts

* Fix lint and use standard timeout option

* Fix merge issue and revert some extra changes

* Revert extra test changes

* Remove test change for extensions
  • Loading branch information
nwmac committed Jun 12, 2024
1 parent 8629b36 commit 4e0c15f
Show file tree
Hide file tree
Showing 23 changed files with 195 additions and 46 deletions.
2 changes: 1 addition & 1 deletion cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ console.log('');
*/
export default defineConfig({
projectId: process.env.TEST_PROJECT_ID,
defaultCommandTimeout: process.env.TEST_TIMEOUT ? +process.env.TEST_TIMEOUT : 60000,
defaultCommandTimeout: process.env.TEST_TIMEOUT ? +process.env.TEST_TIMEOUT : 10000,
trashAssetsBeforeRuns: true,
chromeWebSecurity: false,
retries: {
Expand Down
34 changes: 27 additions & 7 deletions cypress/e2e/po/components/component.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ const isVisible = (selector: string) => () => {
export type CypressChainableFunction = () => CypressChainable;
export type JQueryElement = { jquery: string };

export type GetOptions = Partial<Cypress.Loggable & Cypress.Timeoutable & Cypress.Withinable & Cypress.Shadow>;

export default class ComponentPo {
public self: () => CypressChainable;
public self: (options?: GetOptions) => CypressChainable;
public isVisible?: () => Cypress.Chainable<boolean>;
protected selector = '';

Expand All @@ -22,7 +24,7 @@ export default class ComponentPo {
if (typeof args[0] === 'string') {
const [selector, parent] = args as [string, CypressChainable];

this.self = () => (parent || cy).get(selector);
this.self = (options) => (parent || cy).get(selector, options);
if (!parent) {
// only works if we can find the element via jquery
this.isVisible = isVisible(selector);
Expand All @@ -31,24 +33,42 @@ export default class ComponentPo {
} else if (typeof args[0] === 'function') {
const [self] = args as [CypressChainableFunction];

this.self = self;
this.self = (options?) => {
if (options) {
cy.log('self() does not support options when constructed with a Cypress chainable function');
}

return self();
};
} else if (args[0].jquery) {
// Jquery element - need to wrap (using a function means its evaluated when needed)
this.self = () => cy.wrap(args[0]);
this.self = (options?) => {
if (options) {
cy.log('self() does not support options when constructed with a jQuery element');
}

return cy.wrap(args[0]);
};
} else {
// Note - if the element is removed from screen and shown again this will fail
const [self] = args as [CypressChainable];

this.self = () => self;
this.self = (options?) => {
if (options) {
cy.log('self() does not support options when constructed with a Cypress chainable');
}

return self;
};
}
}

isDisabled(): Cypress.Chainable<boolean> {
return this.self().invoke('attr', 'disabled').then((disabled) => disabled === 'disabled');
}

checkVisible(): Cypress.Chainable<boolean> {
return this.self().scrollIntoView().should('be.visible');
checkVisible(options?: GetOptions): Cypress.Chainable<boolean> {
return this.self(options).scrollIntoView().should('be.visible');
}

checkNotVisible(): Cypress.Chainable<boolean> {
Expand Down
10 changes: 7 additions & 3 deletions cypress/e2e/po/components/kubectl.po.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';
import ComponentPo, { GetOptions } from '@/cypress/e2e/po/components/component.po';
import jsyaml from 'js-yaml';

export default class Kubectl extends ComponentPo {
Expand All @@ -9,9 +9,9 @@ export default class Kubectl extends ComponentPo {
readonly kubeCommand: string = 'kubectl'
readonly terminalRow: string = '.xterm-link-layer'

openTerminal() {
openTerminal(options?: GetOptions) {
cy.get('#btn-kubectl').click();
this.self().get('.window.show-grid .text-success').should('contain', 'Connected');
this.self().get('.window.show-grid .text-success', options).should('contain', 'Connected');

return this;
}
Expand All @@ -20,6 +20,10 @@ export default class Kubectl extends ComponentPo {
this.self().get('[data-testid="wm-tab-close-button"]').click();
}

waitForTerminalToBeVisible() {
this.self().get('[data-testid="wm-tab-close-button"]').should('be.visible');
}

/**
*
* @param command Kube command without the 'kubectl'
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/po/components/list-row.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class ListRowPo extends ComponentPo {
return this.self().find('.btn.actions');
}

get(selector: string) {
return this.self().get(selector);
get(selector: string, options?: any) {
return this.self().get(selector, options);
}
}
6 changes: 3 additions & 3 deletions cypress/e2e/po/components/sortable-table.po.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';
import ComponentPo, { GetOptions } from '@/cypress/e2e/po/components/component.po';
import ActionMenuPo from '@/cypress/e2e/po/components/action-menu.po';
import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po';
import ListRowPo from '@/cypress/e2e/po/components/list-row.po';
Expand Down Expand Up @@ -84,8 +84,8 @@ export default class SortableTablePo extends ComponentPo {
return this.self().find('tbody tr:not(.sub-row)', options);
}

rowElementWithName(name: string) {
return this.self().contains('tbody tr', new RegExp(` ${ name } `));
rowElementWithName(name: string, options?: GetOptions) {
return this.self().contains('tbody tr', new RegExp(` ${ name } `), options);
}

rowElementWithPartialName(name: string) {
Expand Down
3 changes: 3 additions & 0 deletions cypress/e2e/po/pages/chart-repositories.po.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import ChartRepositoriesListPo from '@/cypress/e2e/po/lists/chart-repositories.po';
import ChartRepositoriesCreateEditPo from '@/cypress/e2e/po/edit/chart-repositories.po';
import ClusterManagerListPagePo from '@/cypress/e2e/po/pages/cluster-manager/cluster-manager-list.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';

Expand Down Expand Up @@ -33,6 +34,8 @@ export default class ChartRepositoriesPagePo extends PagePo {
sideNav.navToSideMenuEntryByLabel('Repositories');
} else {
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
(new ClusterManagerListPagePo()).waitForPage();

sideNav.groups().contains('Advanced').click();
sideNav.navToSideMenuEntryByLabel('Repositories');
}
Expand Down
4 changes: 4 additions & 0 deletions cypress/e2e/po/pages/explorer/charts/chart.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export class ChartPage extends PagePo {
return `/c/${ clusterId }/apps/charts/chart`;
}

waitForChartPage(repository: string, chart: string) {
return this.waitForPage(`repo-type=cluster&repo=${ repository }&chart=${ chart }`);
}

static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(ChartPage.createPath(clusterId));
}
Expand Down
8 changes: 8 additions & 0 deletions cypress/e2e/po/pages/explorer/charts/install-charts.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export class InstallChartPage extends PagePo {
super(InstallChartPage.createPath(clusterId));
}

waitForChartPage(repository: string, chart: string) {
return this.waitForPage(`repo-type=cluster&repo=${ repository }&chart=${ chart }`);
}

nextPage() {
const btn = new AsyncButtonPo('.controls-steps .btn.role-primary');

Expand All @@ -29,6 +33,10 @@ export class InstallChartPage extends PagePo {
return this;
}

selectTab(options: TabbedPo, tabID: string) {
return this.editOptions(options, `[data-testid="btn-${ tabID }"]`);
}

installChart() {
const btn = new AsyncButtonPo('[data-testid="action-button-async-button"]');

Expand Down
12 changes: 12 additions & 0 deletions cypress/e2e/po/pages/explorer/charts/tabs/alerting-tab.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po';
import { MonitoringTab } from './monitoring-tab.po';

export class AlertingTab extends MonitoringTab {
tabID(): string {
return 'alerting';
}

deployCheckbox(): CheckboxInputPo {
return new CheckboxInputPo(cy.get('[aria-label="Deploy Alertmanager"]').parent().parent());
}
}
12 changes: 12 additions & 0 deletions cypress/e2e/po/pages/explorer/charts/tabs/istio-tab.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po';
import { MonitoringTab } from './monitoring-tab.po';

export class IstioTab extends MonitoringTab {
tabID(): string {
return 'istio';
}

enableIngressGatewayCheckbox(): CheckboxInputPo {
return new CheckboxInputPo(cy.get('[aria-label="Enable Ingress Gateway"]').parent().parent());
}
}
12 changes: 12 additions & 0 deletions cypress/e2e/po/pages/explorer/charts/tabs/monitoring-tab.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';

export class MonitoringTab extends ComponentPo {
constructor(selector = '.dashboard-root') {
super(selector);
}

// Scroll to bottom of tab view
scrollToTabBottom() {
cy.get('.main-layout > .outlet > .outer-container').scrollTo('bottom');
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';
import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po';
import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po';
import { MonitoringTab } from './monitoring-tab.po';

export class PrometheusTab extends ComponentPo {
constructor(selector = '.dashboard-root') {
super(selector);
export class PrometheusTab extends MonitoringTab {
tabID(): string {
return 'prometheus';
}

persistentStorage(): CheckboxInputPo {
Expand Down
7 changes: 6 additions & 1 deletion cypress/e2e/po/pages/extensions.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import NameNsDescriptionPo from '@/cypress/e2e/po/components/name-ns-description
import RepositoriesPagePo from '@/cypress/e2e/po/pages/chart-repositories.po';
import BannersPo from '@/cypress/e2e/po/components/banners.po';
import ChartRepositoriesCreateEditPo from '@/cypress/e2e/po/edit/chart-repositories.po';
import { LONG_TIMEOUT_OPT } from '@/cypress/support/utils/timeouts';

export default class ExtensionsPagePo extends PagePo {
static url = '/c/local/uiplugins'
Expand Down Expand Up @@ -36,6 +37,10 @@ export default class ExtensionsPagePo extends PagePo {
return this.self().get('.data-loading');
}

waitForTabs() {
return this.extensionTabs.checkVisible(LONG_TIMEOUT_OPT);
}

/**
* Adds a cluster repo for extensions
* @param repo - The repository url (e.g. https://github.com/rancher/ui-plugin-examples)
Expand Down Expand Up @@ -187,7 +192,7 @@ export default class ExtensionsPagePo extends PagePo {

// ------------------ extension menu ------------------
private extensionMenu() {
return this.self().getId('extensions-page-menu');
return this.self().get('[data-testid="extensions-page-menu"]', LONG_TIMEOUT_OPT);
}

extensionMenuToggle(): Cypress.Chainable {
Expand Down
3 changes: 2 additions & 1 deletion cypress/e2e/po/side-bars/product-side-nav.po.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';
import VersionNumberPo from '~/cypress/e2e/po/components/version-number.po';
import { LONG_TIMEOUT_OPT } from '@/cypress/support/utils/timeouts';

export default class ProductNavPo extends ComponentPo {
constructor() {
Expand Down Expand Up @@ -33,7 +34,7 @@ export default class ProductNavPo extends ComponentPo {
* Navigate to a side menu group by label
*/
navToSideMenuGroupByLabel(label: string): Cypress.Chainable {
return this.self().should('exist').contains('.accordion.has-children', label).click();
return cy.get('.side-nav', LONG_TIMEOUT_OPT).should('exist').contains('.accordion.has-children', label, LONG_TIMEOUT_OPT).click();
}

/**
Expand Down
Loading

0 comments on commit 4e0c15f

Please sign in to comment.