Skip to content

Commit

Permalink
Add server-side pagination to home page cluster list (rancher#11663)
Browse files Browse the repository at this point in the history
* Server-side pagination for home page clusters list and side bar clusters

- Functional Changes
  - SSP now works after vue3 bump
  - Home Page Clusters list now uses server-side pagination
  - Side Bar clusters list now uses server-side pagination
  - Wire in now supported sorting / filtering by id and name used for table columns
  - Allow pagination to be enabled given a specific context
  - Call findPage without persisting to store

- New Pagination Tools
  - PaginatedResourceTable - Convenience Component, wraps ResourceTable with pagination specific props
  - PaginationWrapper - Convenience class to handle requests for resources and updates to them (avoiding store)

- Regressions
  - Side Nav menu ready state was `mgmtCluster.isReady && !pCluster?.hasError`, now ???

* Iteration

Note - prov clusters is broken (only fetches local) due to blocking pr. breals
- notPinned list

* Fix dupe inStore
- remove from resource list, put in resource-fetch (used also by pag res table)

* Two fixes
- changes namespaces kicked of side nav cluster requests (thought pinnedIds changed)
- fix generic lists re-fetching given ns filter changes (they don't have namespaced arg)

* remove comment, backport fix

* test fixes

* E2E: Ensure we wait for cluster entries to exist before clicking on them

* backport fix for local/api filtering

* Remove debug code

* Changes after review

* e2e fixes / debugging

* More e2e fixes

* More e2e fixes

* More e2e fixes

* Fix generic pages that filter on pagination

* Attempt to fix flaky vai test

* Fix after merge from master

* Updates following new indexed files

* Fix lint and test

* Changes given real cluster tests
- general fixes
- correct issue were sorting prov clusters on mgmt cluster props (issue in master as well...)
- bit the bullet, we now don't fetch all mgmt clusters on dashboard visit.
  - there could be knock on affects, but we'd need to remove it sometime in 2.11....

* Fix issues with diplaying rke1 data in home page
- includes rancher#12881

* Fix unit tests
  • Loading branch information
richard-cox authored Jan 3, 2025
1 parent 938035f commit b614082
Show file tree
Hide file tree
Showing 62 changed files with 2,065 additions and 772 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ module.exports = {
'@typescript-eslint/no-var-requires': 'off',
'vue/one-component-per-file': 'off',
'vue/no-deprecated-slot-attribute': 'off',
'vue/v-on-event-hyphenation': 'off'
'vue/v-on-event-hyphenation': 'off',
'jest/no-hooks': 'off',
},
overrides: [
{
Expand Down
5 changes: 5 additions & 0 deletions cypress/e2e/po/components/namespace-filter.po.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';

export class NamespaceFilterPo extends ComponentPo {
constructor() {
super('[data-testid="namespaces-filter"]');
Expand Down Expand Up @@ -52,6 +53,10 @@ export class NamespaceFilterPo extends ComponentPo {
return this.namespaceDropdown().find('[data-testid="namespaces-values"]');
}

allSelected() {
return this.self().find('[data-testid="namespaces-values-none"]').should('exist');
}

moreOptionsSelected() {
return this.namespaceDropdown().find('.ns-more');
}
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/chart-repositories.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ export default class ChartRepositoriesPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Apps');
sideNav.navToSideMenuEntryByLabel('Repositories');
} else {
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/charts/charts.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ export class ChartsPage extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Apps');
}

Expand Down
51 changes: 48 additions & 3 deletions cypress/e2e/po/pages/explorer/cluster-dashboard.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import CustomBadgeDialogPo from '@/cypress/e2e/po/components/custom-badge-dialog
import EventsListPo from '@/cypress/e2e/po/lists/events-list.po';
import TabbedPo from '@/cypress/e2e/po/components/tabbed.po';
import CertificatesPo from '@/cypress/e2e/po/components/certificates.po';
import { HeaderPo } from '~/cypress/e2e/po/components/header.po';
import { HeaderPo } from '@/cypress/e2e/po/components/header.po';
import { NamespaceFilterPo } from '@/cypress/e2e/po/components/namespace-filter.po';

export default class ClusterDashboardPagePo extends PagePo {
private static createPath(clusterId: string) {
Expand All @@ -15,15 +16,18 @@ export default class ClusterDashboardPagePo extends PagePo {
return super.goTo(ClusterDashboardPagePo.createPath(clusterId));
}

urlPath(clusterId = 'local') {
return ClusterDashboardPagePo.createPath(clusterId);
}

constructor(clusterId: string) {
super(ClusterDashboardPagePo.createPath(clusterId));
}

static navTo(clusterId = 'local') {
const burgerMenu = new BurgerMenuPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
}

customizeAppearanceButton() {
Expand Down Expand Up @@ -79,4 +83,45 @@ export default class ClusterDashboardPagePo extends PagePo {
controllerManagerStatus() {
return cy.get('[data-testid="k8s-service-controller-manager"]');
}

/**
* Confirm that the ns filter is set correctly before navigating to a page that will use it
* 1. nav to cluster dashboard
* 2. check ns filter values
*/
static goToAndConfirmNsValues(cluster: string, {
nsProject,
all
}: {
nsProject?: {
values: string[]
},
all?: {
is: boolean,
}
}) {
const instance = new ClusterDashboardPagePo(cluster);
const nsfilter = new NamespaceFilterPo();

instance.goTo();
instance.waitForPage();
nsfilter.checkVisible();

if (nsProject) {
for (let i = 0; i < nsProject.values.length; i++) {
nsfilter.selectedValues().contains(nsProject.values[i]);
}
} else if (all) {
nsfilter.allSelected();
} else {
throw new Error('Bad Config');
}
}

static goToAndWait(cluster: string) {
const instance = new ClusterDashboardPagePo(cluster);

instance.goTo();
instance.clusterActionsHeader().checkVisible();
}
}
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/config-map.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ export class ConfigMapPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Storage');
sideNav.navToSideMenuEntryByLabel('ConfigMaps');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ export class CustomResourceDefinitionsPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('More Resources');
sideNav.navToSideMenuGroupByLabel('API');
sideNav.navToSideMenuEntryByLabel('CustomResourceDefinitions');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ export class HorizontalPodAutoscalersPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Service Discovery');
sideNav.navToSideMenuEntryByLabel('HorizontalPodAutoscalers');
}
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/ingress.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ export class IngressPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Service Discovery');
sideNav.navToSideMenuEntryByLabel('Ingresses');
}
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/network-policy.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ export class NetworkPolicyPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Policy');
sideNav.navToSideMenuEntryByLabel('Network Policies');
}
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/persistent-volume-claims.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ export class PersistentVolumeClaimsPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Storage');
sideNav.navToSideMenuEntryByLabel('PersistentVolumeClaims');
}
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/persistent-volumes.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ export class PersistentVolumesPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Storage');
sideNav.navToSideMenuEntryByLabel('PersistentVolumes');
}
Expand Down
12 changes: 12 additions & 0 deletions cypress/e2e/po/pages/explorer/service-accounts.po.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';

export class ServiceAccountsPagePo extends PagePo {
private static createPath(clusterId: string) {
Expand All @@ -14,6 +16,16 @@ export class ServiceAccountsPagePo extends PagePo {
return super.goTo(ServiceAccountsPagePo.createPath(clusterId));
}

static navTo(clusterId = 'local') {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('More Resources');
sideNav.navToSideMenuGroupByLabel('Core');
sideNav.navToSideMenuEntryByLabel('ServiceAccount');
}

constructor(clusterId = 'local') {
super(ServiceAccountsPagePo.createPath(clusterId));
}
Expand Down
5 changes: 2 additions & 3 deletions cypress/e2e/po/pages/explorer/services.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ export class ServicesPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Service Discovery');
sideNav.navToSideMenuEntryByLabel('Ingresses');
sideNav.navToSideMenuEntryByLabel('Service');
}

constructor(clusterId = 'local') {
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/storage-classes.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ export class StorageClassesPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Storage');
sideNav.navToSideMenuEntryByLabel('StorageClasses');
}
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/po/pages/explorer/workloads-pods.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ export class WorkloadsPodsListPagePo extends PagePo {
const burgerMenu = new BurgerMenuPo();
const sideNav = new ProductNavPo();

BurgerMenuPo.toggle();
burgerMenu.clusterNotPinnedList().contains(clusterId).click();
burgerMenu.goToCluster(clusterId);
sideNav.navToSideMenuGroupByLabel('Workloads');
sideNav.navToSideMenuEntryByLabel('Pods');
}
Expand Down
8 changes: 7 additions & 1 deletion cypress/e2e/po/side-bars/burger-side-menu.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,13 @@ export default class BurgerMenuPo extends ComponentPo {
return this.self().find('.body .cluster.selector.option');
}

goToCluster(clusterId = 'local') {
goToCluster(clusterId = 'local', toggleOpen = true) {
if (toggleOpen) {
BurgerMenuPo.toggle();
}

this.self().find('.cluster-name').contains(clusterId).should('exist');

return this.self().find('.cluster-name').contains(clusterId).click();
}

Expand Down
3 changes: 3 additions & 0 deletions cypress/e2e/tests/navigation/side-nav/main-side-menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ describe('Side Menu: main', () => {
pagePoFake.navToClusterMenuEntry(fakeProvClusterId);
sideNav.navToSideMenuEntryByLabel('Projects/Namespaces');

BurgerMenuPo.burgerMenuGetNavClusterbyLabel('local').should('exist');
BurgerMenuPo.burgerMenuGetNavClusterbyLabel(fakeProvClusterId).should('exist');

// press key combo
cy.get('body').focus().type('{alt}', { release: false });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ describe('Side navigation: Cluster ', { tags: ['@navigation', '@adminUser'] }, (
cy.login();

HomePagePo.goTo();
BurgerMenuPo.toggle();
const burgerMenuPo = new BurgerMenuPo();

burgerMenuPo.goToCluster('local').click();
burgerMenuPo.goToCluster('local');
});

it('Can access to first navigation link on click', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { NodesPagePo } from '@/cypress/e2e/po/pages/explorer/nodes.po';
import { EventsPagePo } from '@/cypress/e2e/po/pages/explorer/events.po';
import * as path from 'path';
import { eventsNoDataset } from '@/cypress/e2e/blueprints/explorer/cluster/events';
import HomePagePo from '@/cypress/e2e/po/pages/home.po';

const configMapYaml = `apiVersion: v1
kind: ConfigMap
Expand Down Expand Up @@ -258,12 +257,19 @@ describe('Cluster Dashboard', { testIsolation: 'off', tags: ['@explorer', '@admi
});

it('can view events table empty if no events', { tags: ['@vai', '@adminUser'] }, () => {
const events = new EventsPagePo('local');

HomePagePo.goTo();
cy.visit(clusterDashboard.urlPath(), {
onBeforeLoad(win) {
cy.stub(win.console, 'error').as('consoleError');
cy.stub(win.console, 'warn').as('consoleWarn');
},
});

eventsNoDataset();
ClusterDashboardPagePo.navTo();
clusterDashboard.goTo();

cy.get('@consoleError').should('not.be.called'); // See error lot
cy.get('@consoleWarn').should('not.be.called'); // See warning log (there will be some....)

cy.wait('@eventsNoData');
clusterDashboard.waitForPage(undefined, 'cluster-events');

Expand All @@ -279,6 +285,8 @@ describe('Cluster Dashboard', { testIsolation: 'off', tags: ['@explorer', '@admi

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

events.waitForPage();

events.eventslist().resourceTable().sortableTable().checkRowCount(true, 1);
Expand Down
12 changes: 7 additions & 5 deletions cypress/e2e/tests/pages/explorer/dashboard/events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { generateEventsDataSmall } from '@/cypress/e2e/blueprints/explorer/clust
import LoadingPo from '@/cypress/e2e/po/components/loading.po';
import SortableTablePo from '@/cypress/e2e/po/components/sortable-table.po';

const clusterDashboard = new ClusterDashboardPagePo('local');
const events = new EventsPagePo('local');
const cluster = 'local';
const clusterDashboard = new ClusterDashboardPagePo(cluster);
const events = new EventsPagePo(cluster);

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

before('set up', () => {
cy.updateNamespaceFilter('local', 'none', '{\"local\":[]}');
cy.updateNamespaceFilter(cluster, 'none', '{\"local\":[]}');

cy.createE2EResourceName('ns1').then((ns1) => {
nsName1 = ns1;
Expand Down Expand Up @@ -54,7 +55,8 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },
});

it('pagination is visible and user is able to navigate through events data', () => {
ClusterDashboardPagePo.goTo('local');
ClusterDashboardPagePo.goToAndConfirmNsValues(cluster, { all: { is: true } });

clusterDashboard.waitForPage(undefined, 'cluster-events');
EventsPagePo.navTo();
events.waitForPage();
Expand Down Expand Up @@ -199,7 +201,7 @@ describe('Events', { testIsolation: 'off', tags: ['@explorer', '@adminUser'] },
});

after('clean up', () => {
cy.updateNamespaceFilter('local', 'none', '{"local":["all://user"]}');
cy.updateNamespaceFilter(cluster, 'none', '{"local":["all://user"]}');

// 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 @@ -2,8 +2,10 @@ import { CustomResourceDefinitionsPagePo } from '@/cypress/e2e/po/pages/explorer
import { generateCrdsDataSmall } from '@/cypress/e2e/blueprints/explorer/more-resources/api/custom-resource-definition-get';
import * as jsyaml from 'js-yaml';
import HomePagePo from '@/cypress/e2e/po/pages/home.po';
import ClusterDashboardPagePo from '@/cypress/e2e/po/pages/explorer/cluster-dashboard.po';

const crdsPage = new CustomResourceDefinitionsPagePo('local');
const cluster = 'local';
const crdsPage = new CustomResourceDefinitionsPagePo(cluster);
const crdName = `e2etests.${ +new Date() }.example.com`;
const crdGroup = `${ +new Date() }.example.com`;

Expand All @@ -14,11 +16,14 @@ describe('CustomResourceDefinitions', { testIsolation: 'off', tags: ['@explorer'

describe('List', { tags: ['@vai', '@adminUser'] }, () => {
before(() => {
cy.tableRowsPerPageAndNamespaceFilter(10, 'local', 'none', '{\"local\":[]}');
ClusterDashboardPagePo.goToAndWait(cluster); // Ensure we're at a solid state before messing with preferences (given login/load might change them)
cy.tableRowsPerPageAndNamespaceFilter(10, cluster, 'none', '{\"local\":[]}');
});

it('can create a crd and see it in list view', () => {
crdsPage.goTo();
ClusterDashboardPagePo.goToAndConfirmNsValues(cluster, { all: { is: true } } );

CustomResourceDefinitionsPagePo.navTo();
crdsPage.waitForPage();
crdsPage.create();

Expand Down
Loading

0 comments on commit b614082

Please sign in to comment.