Skip to content

Commit

Permalink
Fix failing e2e tests
Browse files Browse the repository at this point in the history
- fix cluster dashboard events test
- fix and greatly improve flaky events test
- fix hpa test
- functional fixes
  - fix sorting/filtering events by object type
  - fix hpa columns
  • Loading branch information
richard-cox committed Jan 7, 2025
1 parent dc5a5a3 commit 457f117
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -265,30 +265,39 @@ describe('Cluster Dashboard', { testIsolation: 'off', tags: ['@explorer', '@admi

clusterDashboard.eventsList().resourceTable().sortableTable().checkRowCount(true, 1);

const expectedHeaders = ['Reason', 'Object', 'Message', 'Name', 'Date'];
let expectedHeaders = ['Reason', 'Object', 'Message', 'Name', 'Date'];

clusterDashboard.eventsList().resourceTable().sortableTable().tableHeaderRow()
.within('.table-header-container .content')
.each((el, i) => {
expect(el.text().trim()).to.eq(expectedHeaders[i]);
});
cy.isVaiCacheEnabled().then((isVaiCacheEnabled) => {
if (isVaiCacheEnabled) {
expectedHeaders = ['Reason', 'Object', 'Message', 'Name', 'First Seen', 'Last Seen', 'Count'];
}

clusterDashboard.fullEventsLink().click();
cy.wait('@eventsNoData');
const events = new EventsPagePo('local');
clusterDashboard.eventsList().resourceTable().sortableTable().tableHeaderRow()
.self()
.scrollIntoView();
clusterDashboard.eventsList().resourceTable().sortableTable().tableHeaderRow()
.within('.table-header-container .content')
.each((el, i) => {
expect(el.text().trim()).to.eq(expectedHeaders[i]);
});

events.waitForPage();
clusterDashboard.fullEventsLink().click();
cy.wait('@eventsNoData');
const events = new EventsPagePo('local');

events.eventslist().resourceTable().sortableTable().checkRowCount(true, 1);
events.waitForPage();

const expectedFullHeaders = ['State', 'Last Seen', 'Type', 'Reason', 'Object',
'Subobject', 'Source', 'Message', 'First Seen', 'Count', 'Name', 'Namespace'];
events.eventslist().resourceTable().sortableTable().checkRowCount(true, 1);

events.eventslist().resourceTable().sortableTable().tableHeaderRow()
.within('.table-header-container .content')
.each((el, i) => {
expect(el.text().trim()).to.eq(expectedFullHeaders[i]);
});
const expectedFullHeaders = ['State', 'Last Seen', 'Type', 'Reason', 'Object',
'Subobject', 'Source', 'Message', 'First Seen', 'Count', 'Name', 'Namespace'];

events.eventslist().resourceTable().sortableTable().tableHeaderRow()
.within('.table-header-container .content')
.each((el, i) => {
expect(el.text().trim()).to.eq(expectedFullHeaders[i]);
});
});
});

describe('Cluster dashboard with limited permissions', () => {
Expand Down
188 changes: 131 additions & 57 deletions cypress/e2e/tests/pages/explorer/dashboard/events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ import SortableTablePo from '@/cypress/e2e/po/components/sortable-table.po';
const cluster = 'local';
const clusterDashboard = new ClusterDashboardPagePo(cluster);
const events = new EventsPagePo(cluster);
const pageSize = 10;
// Should be enough to create at least 3 pages of events
const podCount = 15;

const countHelper = {
setupCount: (vaiCacheEnabled: boolean, initialCount: number) => {
if (vaiCacheEnabled) {
cy.intercept('GET', '/v1/events?*').as('getCount');
} else {
cy.wrap(initialCount).as('count');
}
},
handleCount: (vaiCacheEnabled) => {
if (vaiCacheEnabled) {
cy.wait('@getCount').then((interception) => {
cy.wrap(interception.response.body.count).as('count');
});
}
},
getCount: () => cy.get('@count').then((count) => count as any as number),
};

describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] }, () => {
before(() => {
Expand All @@ -20,7 +41,12 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },
let nsName2: string;

before('set up', () => {
cy.updateNamespaceFilter(cluster, 'none', '{\"local\":[]}');
cy.tableRowsPerPageAndPreferences(pageSize, {
clusterName: cluster,
groupBy: 'none',
namespaceFilter: '{\"local\":[]}',
allNamespaces: 'true',
});

cy.createE2EResourceName('ns1').then((ns1) => {
nsName1 = ns1;
Expand All @@ -30,7 +56,7 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },
// create pods
let i = 0;

while (i < 125) {
while (i < podCount) {
const podName = Cypress._.uniqueId(Date.now().toString());

cy.createPod(nsName1, podName, 'nginx:latest', false, { createNameOptions: { prefixContext: true } }).then((resp) => {
Expand All @@ -52,6 +78,9 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },
uniquePod = resp.body.metadata.name;
});
});

// I'm loathed to do this, but the events created from the pods need to settle before we start
cy.wait(20000); // eslint-disable-line cypress/no-unnecessary-waiting
});

it('pagination is visible and user is able to navigate through events data', () => {
Expand All @@ -61,73 +90,113 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },
EventsPagePo.navTo();
events.waitForPage();

cy.getRancherResource('v1', 'events').then((resp: Cypress.Response<any>) => {
// Why 500? there's a hardcoded figure to stops ui from storing more than 500 events ...
const count = resp.body.count < 500 ? resp.body.count : 500;

// Test break down if less than 400...
expect(count).to.be.greaterThan(400);
let vaiCacheEnabled = false;

// pagination is visible
events.sortableTable().pagination().checkVisible();
cy.isVaiCacheEnabled()
.then((isVaiCacheEnabled) => {
vaiCacheEnabled = isVaiCacheEnabled;

const loadingPo = new LoadingPo('.title .resource-loading-indicator');
return cy.getRancherResource('v1', 'events');
})
.then((resp: Cypress.Response<any>) => {
let initialCount = resp.body.count;

loadingPo.checkNotExists();
if (!vaiCacheEnabled && resp.body.count > 500) {
// Why 500? there's a hardcoded figure to stops ui from storing more than 500 events ...
initialCount = 500;
}

// basic checks on navigation buttons
events.sortableTable().pagination().beginningButton().isDisabled();
events.sortableTable().pagination().leftButton().isDisabled();
events.sortableTable().pagination().rightButton().isEnabled();
events.sortableTable().pagination().endButton().isEnabled();
// Test break down if less than 3 pages...
expect(initialCount).to.be.greaterThan(3 * pageSize);

// check text before navigation
events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`1 - 100 of ${ count } Events`);
});

// navigate to next page - right button
events.sortableTable().pagination().rightButton().click();
// pagination is visible
events.sortableTable().pagination().checkVisible();

// check text and buttons after navigation
events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`101 - 200 of ${ count } Events`);
});
events.sortableTable().pagination().beginningButton().isEnabled();
events.sortableTable().pagination().leftButton().isEnabled();
const loadingPo = new LoadingPo('.title .resource-loading-indicator');

// navigate to first page - left button
events.sortableTable().pagination().leftButton().click();
loadingPo.checkNotExists();

// check text and buttons after navigation
events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`1 - 100 of ${ count } Events`);
});
events.sortableTable().pagination().beginningButton().isDisabled();
events.sortableTable().pagination().leftButton().isDisabled();
// basic checks on navigation buttons
events.sortableTable().pagination().beginningButton().isDisabled();
events.sortableTable().pagination().leftButton().isDisabled();
events.sortableTable().pagination().rightButton().isEnabled();
events.sortableTable().pagination().endButton().isEnabled();

// navigate to last page - end button
events.sortableTable().pagination().endButton().scrollIntoView()
.click();
// check text before navigation
events.sortableTable().pagination().self().scrollIntoView();
events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`1 - ${ pageSize } of ${ initialCount } Events`);
});

// check row count on last page
events.sortableTable().checkRowCount(false, 100);
// navigate to next page - right button
countHelper.setupCount(vaiCacheEnabled, initialCount);
events.sortableTable().pagination().rightButton().click();
countHelper.handleCount(vaiCacheEnabled);

// check text and buttons after navigation
events.sortableTable().pagination().self().scrollIntoView();
countHelper.getCount().then((count) => {
return events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`${ pageSize + 1 } - ${ 2 * pageSize } of ${ count } Events`);
});
});
events.sortableTable().pagination().beginningButton().isEnabled();
events.sortableTable().pagination().leftButton().isEnabled();

// navigate to first page - left button
countHelper.setupCount(vaiCacheEnabled, initialCount);
events.sortableTable().pagination().leftButton().click();
countHelper.handleCount(vaiCacheEnabled);

// check text and buttons after navigation
events.sortableTable().pagination().self().scrollIntoView();
countHelper.getCount().then((count) => {
return events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`1 - ${ pageSize } of ${ count } Events`);
});
});

// check text after navigation
events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`401 - ${ count } of ${ count } Events`);
});
events.sortableTable().pagination().beginningButton().isDisabled();
events.sortableTable().pagination().leftButton().isDisabled();

// navigate to last page - end button
countHelper.setupCount(vaiCacheEnabled, initialCount);
events.sortableTable().pagination().endButton().scrollIntoView()
.click();
countHelper.handleCount(vaiCacheEnabled);

// check text after navigation
events.sortableTable().pagination().self().scrollIntoView();
countHelper.getCount().then((count) => {
return events.sortableTable().pagination().paginationText().then((el) => {
let pages = Math.floor(count / pageSize);

if (count % pageSize === 0) {
pages--;
}
const from = (pages * pageSize) + 1;
const to = count;

expect(el.trim()).to.eq(`${ from } - ${ to } of ${ to } Events`);
});
});

// navigate to first page - beginning button
events.sortableTable().pagination().beginningButton().click();
// navigate to first page - beginning button
countHelper.setupCount(vaiCacheEnabled, initialCount);
events.sortableTable().pagination().beginningButton().click();
countHelper.handleCount(vaiCacheEnabled);

// check text and buttons after navigation
events.sortableTable().pagination().self().scrollIntoView();
countHelper.getCount().then((count) => {
events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`1 - ${ pageSize } of ${ count } Events`);
});
});

// check text and buttons after navigation
events.sortableTable().pagination().paginationText().then((el) => {
expect(el.trim()).to.eq(`1 - 100 of ${ count } Events`);
events.sortableTable().pagination().beginningButton().isDisabled();
events.sortableTable().pagination().leftButton().isDisabled();
});
events.sortableTable().pagination().beginningButton().isDisabled();
events.sortableTable().pagination().leftButton().isDisabled();
});
});

it('filter events', () => {
Expand All @@ -138,7 +207,7 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },

events.sortableTable().checkVisible();
events.sortableTable().checkLoadingIndicatorNotVisible();
events.sortableTable().checkRowCount(false, 100);
events.sortableTable().checkRowCount(false, pageSize);

// filter by namespace
events.sortableTable().filter(nsName2);
Expand Down Expand Up @@ -201,7 +270,12 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },
});

after('clean up', () => {
cy.updateNamespaceFilter(cluster, 'none', '{"local":["all://user"]}');
cy.tableRowsPerPageAndPreferences(100, {
clusterName: cluster,
groupBy: 'none',
namespaceFilter: '{"local":["all://user"]}',
allNamespaces: 'false',
});

// delete namespace (this will also delete all pods in it)
cy.deleteRancherResource('v1', 'namespaces', nsName1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ describe('HorizontalPodAutoscalers', { testIsolation: 'off', tags: ['@explorer',
horizontalPodAutoscalersPage.waitForPage();
cy.wait('@horizontalpodautoscalerNoData');

const expectedHeaders = ['State', 'Name', 'Workload', 'Minimum Replicas', 'Maximum Replicas', 'Current Replicas', 'Age'];
const expectedHeaders = ['State', 'Name', 'Namespace', 'Workload', 'Minimum Replicas', 'Maximum Replicas', 'Current Replicas', 'Age'];

horizontalPodAutoscalersPage.list().resourceTable().sortableTable().tableHeaderRow()
.self()
.scrollIntoView();
horizontalPodAutoscalersPage.list().resourceTable().sortableTable().tableHeaderRow()
.get('.table-header-container .content')
.each((el, i) => {
Expand All @@ -39,7 +42,7 @@ describe('HorizontalPodAutoscalers', { testIsolation: 'off', tags: ['@explorer',
horizontalPodAutoscalersPage.header().selectNamespaceFilterOption('All Namespaces');

// check table headers are visible
const expectedHeaders = ['State', 'Name', 'Workload', 'Minimum Replicas', 'Maximum Replicas', 'Current Replicas', 'Age'];
const expectedHeaders = ['State', 'Name', 'Namespace', 'Workload', 'Minimum Replicas', 'Maximum Replicas', 'Current Replicas', 'Age'];

horizontalPodAutoscalersPage.list().resourceTable().sortableTable().tableHeaderRow()
.get('.table-header-container .content')
Expand All @@ -65,7 +68,7 @@ describe('HorizontalPodAutoscalers', { testIsolation: 'off', tags: ['@explorer',
horizontalPodAutoscalersPage.list().resourceTable().sortableTable().groupByButtons(1)
.click();

// check table headers are visible
// check table headers are visible (minus namespace given we're now grouped by it)
const expectedHeaders = ['State', 'Name', 'Workload', 'Minimum Replicas', 'Maximum Replicas', 'Current Replicas', 'Age'];

horizontalPodAutoscalersPage.list().resourceTable().sortableTable().tableHeaderRow()
Expand Down
8 changes: 7 additions & 1 deletion cypress/globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ declare global {
deleteRancherResource(prefix: 'v3' | 'v1' | 'k8s', resourceType: string, resourceId: string, failOnStatusCode?: boolean): Chainable;
deleteNodeTemplate(nodeTemplateId: string, timeout?: number, failOnStatusCode?: boolean)

tableRowsPerPageAndNamespaceFilter(rows: number, cluster: string, groupBy: string, namespacefilter: string, interation?: number)
tableRowsPerPageAndNamespaceFilter(rows: number, clusterName: string, groupBy: string, namespaceFilter: string)
tableRowsPerPageAndPreferences(rows: number, preferences: { clusterName: string, groupBy: string, namespaceFilter: string, allNamespaces: string}, iteration?: number)

/**
* update namespace filter
Expand Down Expand Up @@ -162,6 +163,11 @@ declare global {
* Fetch the steve `revision` / timestamp of request
*/
fetchRevision(): Chainable<string>;

/**
* Check if the vai FF is enabled
*/
isVaiCacheEnabled(): Chainable<boolean>;
}
}
}
Loading

0 comments on commit 457f117

Please sign in to comment.