Skip to content

Commit

Permalink
Merge pull request #2745 from ppadti/test-pagination
Browse files Browse the repository at this point in the history
Cypress test for pagination
  • Loading branch information
openshift-merge-bot[bot] authored Apr 30, 2024
2 parents ab0d1b5 + c150dcb commit 9fde61f
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AcceleratorProfileModel } from '~/__tests__/cypress/cypress/utils/model
import { mockK8sResourceList } from '~/__mocks__';
import { be } from '~/__tests__/cypress/cypress/utils/should';
import { asProductAdminUser } from '~/__tests__/cypress/cypress/utils/users';
import { testPagination } from '~/__tests__/cypress/cypress/utils/pagination';

type HandlersProps = {
isEmpty?: boolean;
Expand Down Expand Up @@ -45,15 +46,35 @@ describe('Accelerator Profile', () => {
acceleratorProfile.findAddButton().should('be.enabled');
});

it('list accelerator profiles and Table filtering, sorting, searching', () => {
initIntercepts({});
it('list accelerator profiles and Table filtering, sorting, searching and pagination', () => {
const totalItems = 50;
cy.interceptK8sList(
{ model: AcceleratorProfileModel, ns: 'opendatahub' },
mockK8sResourceList(
Array.from({ length: totalItems }, (_, i) =>
mockAcceleratorProfile({
displayName: `Test Accelerator - ${i}`,
identifier: 'tensor.com/gpu',
description: `accelerator profile ${i}`,
}),
),
),
);
acceleratorProfile.visit();
const tableRow = acceleratorProfile.getRow('TensorRT');
tableRow
.findDescription()
.contains('Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe, quis');
const tableRow = acceleratorProfile.getRow('Test Accelerator - 0');
tableRow.findDescription().contains('accelerator profile 0');
tableRow.shouldHaveIdentifier('tensor.com/gpu');

// top pagination
testPagination({ totalItems, firstElement: 'Test Accelerator - 0', paginationVariant: 'top' });

// bottom pagination
testPagination({
totalItems,
firstElement: 'Test Accelerator - 0',
paginationVariant: 'bottom',
});

//sort by Name
acceleratorProfile.findTableHeaderButton('Name').click();
acceleratorProfile.findTableHeaderButton('Name').should(be.sortDescending);
Expand Down Expand Up @@ -83,7 +104,7 @@ describe('Accelerator Profile', () => {
const acceleratorTableToolbar = acceleratorProfile.getTableToolbar();
acceleratorTableToolbar.findFilterMenuOption('filter-dropdown-select', 'Name').click();
acceleratorTableToolbar.findSearchInput().fill('Test');
acceleratorProfile.getRow('Test Accelerator').shouldHaveIdentifier('nvidia.com/gpu');
acceleratorProfile.getRow('Test Accelerator - 0').shouldHaveIdentifier('tensor.com/gpu');

acceleratorTableToolbar.findFilterMenuOption('filter-dropdown-select', 'Identifier').click();
acceleratorTableToolbar.findResetButton().click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
} from '~/__tests__/cypress/cypress/pages/administration';
import { be } from '~/__tests__/cypress/cypress/utils/should';
import { asProductAdminUser, asProjectEditUser } from '~/__tests__/cypress/cypress/utils/users';
import { AllowedUser } from '~/pages/notebookController/screens/admin/types';
import { testPagination } from '~/__tests__/cypress/cypress/utils/pagination';

const groupSubjects: RoleBindingSubject[] = [
{
Expand All @@ -18,11 +20,14 @@ const groupSubjects: RoleBindingSubject[] = [
},
];

const initIntercepts = () => {
cy.interceptOdh('GET /api/status/openshift-ai-notebooks/allowedUsers', [
mockAllowedUsers({}),
mockAllowedUsers({ username: 'regularuser1' }),
]);
type HandlersProps = {
allowedUser?: AllowedUser[];
};

const initIntercepts = ({
allowedUser = [mockAllowedUsers({}), mockAllowedUsers({ username: 'regularuser1' })],
}: HandlersProps) => {
cy.interceptOdh('GET /api/status/openshift-ai-notebooks/allowedUsers', allowedUser);
cy.interceptOdh(
'GET /api/rolebindings/opendatahub/openshift-ai-notebooks-image-pullers',
mockK8sResourceList([
Expand All @@ -36,8 +41,8 @@ const initIntercepts = () => {
cy.interceptOdh('GET /api/images/:type', { path: { type: 'jupyter' } }, mockNotebookImageInfo());
};

it('Administartion tab should not be accessible for non-project admins', () => {
initIntercepts();
it('Administration tab should not be accessible for non-project admins', () => {
initIntercepts({});
asProjectEditUser();
notebookController.visit();
notebookController.findAdministrationTab().should('not.exist');
Expand All @@ -47,13 +52,13 @@ it('Administartion tab should not be accessible for non-project admins', () => {

describe('Administration Tab', () => {
beforeEach(() => {
initIntercepts();
asProductAdminUser();
notebookController.visit();
notebookController.findAdministrationTab().click();
});

it('Check table with users details', () => {
initIntercepts({});
notebookController.visit();
notebookController.findAdministrationTab().click();
administration.shouldHaveManageUsersAlert();
administration.findStopAllServersButton().should('be.disabled');
const userRow = administration.getRow('test-user');
Expand All @@ -63,6 +68,9 @@ describe('Administration Tab', () => {
});

it('Users table sorting', () => {
initIntercepts({});
notebookController.visit();
notebookController.findAdministrationTab().click();
// By user
administration.findTableHeaderButton('User').click();
administration.findTableHeaderButton('User').should(be.sortDescending);
Expand All @@ -88,7 +96,27 @@ describe('Administration Tab', () => {
administration.findTableHeaderButton('Server status').should(be.sortDescending);
});

it('Validate pagination', () => {
const totalItems = 50;
const mockAllowedUser: AllowedUser[] = Array.from({ length: totalItems }, (_, i) =>
mockAllowedUsers({
username: `Test user-${i}`,
}),
);
initIntercepts({ allowedUser: mockAllowedUser });
notebookController.visit();
notebookController.findAdministrationTab().click();
// top pagination
testPagination({ totalItems, firstElement: 'Test user-0', paginationVariant: 'top' });

// bottom pagination
testPagination({ totalItems, firstElement: 'Test user-0', paginationVariant: 'bottom' });
});

it('Validate that clicking on "Start server" button will open a form in administartion tab and "Start your server" button will navigate to notebook server tab', () => {
initIntercepts({});
notebookController.visit();
notebookController.findAdministrationTab().click();
let userRow = administration.getRow('regularuser1');

// open a form in administartion tab with impersonate alert
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { InferenceServiceKind, ServingRuntimeKind } from '~/k8sTypes';
import { ServingRuntimePlatform } from '~/types';
import { be } from '~/__tests__/cypress/cypress/utils/should';
import { asClusterAdminUser } from '~/__tests__/cypress/cypress/utils/users';
import { testPagination } from '~/__tests__/cypress/cypress/utils/pagination';

type HandlersProps = {
disableKServeConfig?: boolean;
Expand Down Expand Up @@ -472,7 +473,7 @@ describe('Model Serving Global', () => {
cy.findByText('Error creating model server').should('not.exist');
});

describe('Table filter', () => {
describe('Table filter and pagination', () => {
it('filter by name', () => {
initIntercepts({});
modelServingGlobal.visit('test-project');
Expand Down Expand Up @@ -526,5 +527,32 @@ describe('Model Serving Global', () => {
// Verify no results were found
modelServingGlobal.findEmptyResults().should('exist');
});

it('Validate pagination', () => {
const totalItems = 50;
const mockInferenceService: InferenceServiceKind[] = Array.from(
{ length: totalItems },
(_, i) =>
mockInferenceServiceK8sResource({
displayName: `Test Inference Service-${i}`,
}),
);
initIntercepts({ inferenceServices: mockInferenceService });
modelServingGlobal.visit('test-project');

// top pagination
testPagination({
totalItems,
firstElement: 'Test Inference Service-0',
paginationVariant: 'top',
});

// bottom pagination
testPagination({
totalItems,
firstElement: 'Test Inference Service-0',
paginationVariant: 'bottom',
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { mockByon } from '~/__mocks__/mockByon';
import { deleteModal } from '~/__tests__/cypress/cypress/pages/components/DeleteModal';
import { tablePagination } from '~/__tests__/cypress/cypress/pages/components/Pagination';
import {
importNotebookImageModal,
notebookImageDeleteModal,
Expand All @@ -11,6 +10,7 @@ import { pageNotfound } from '~/__tests__/cypress/cypress/pages/pageNotFound';
import { projectListPage } from '~/__tests__/cypress/cypress/pages/projects';
import { be } from '~/__tests__/cypress/cypress/utils/should';
import { asProductAdminUser, asProjectAdminUser } from '~/__tests__/cypress/cypress/utils/users';
import { testPagination } from '~/__tests__/cypress/cypress/utils/pagination';

it('Notebook image settings should not be available for non product admins', () => {
asProjectAdminUser();
Expand All @@ -24,11 +24,12 @@ describe('Notebook image settings', () => {
asProductAdminUser();
});

it('Table filtering, sorting, searching', () => {
it('Table filtering, sorting, searching and pagination', () => {
const totalItems = 1000;
cy.interceptOdh(
'GET /api/images/byon',
Array.from(
{ length: 1000 },
{ length: totalItems },
(_, i) =>
mockByon([
{
Expand Down Expand Up @@ -73,25 +74,11 @@ describe('Notebook image settings', () => {
notebookImageSettings.findTableHeaderButton('Enable').should(be.sortDescending);
notebookImageSettings.findTableHeaderButton('Name').click();

// test pagination
// test next page
tablePagination.top.findNextButton().click();
tablePagination.top.findNextButton().click();
tablePagination.top.findNextButton().click();
tablePagination.top.findNextButton().click();
notebookImageSettings.getRow('image-136').find().should('exist');

// test type page
tablePagination.top.findInput().clear();
tablePagination.top.findInput().type('50{enter}');
notebookImageSettings.getRow('image-542').find().should('exist');

// test last and first page
tablePagination.top.findLastButton().click();
notebookImageSettings.getRow('image-999').find().should('exist');

tablePagination.top.findFirstButton().click();
notebookImageSettings.getRow('image-0').find().should('exist');
// top pagination
testPagination({ totalItems, firstElement: 'image-0', paginationVariant: 'top' });

// bottom pagination
testPagination({ totalItems, firstElement: 'image-0', paginationVariant: 'bottom' });

// test filtering
// by name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { incrementResourceVersion } from '~/__mocks__/mockUtils';
import { ProjectModel, ProjectRequestModel } from '~/__tests__/cypress/cypress/utils/models';
import { mock200Status } from '~/__mocks__/mockK8sStatus';
import { asProjectAdminUser } from '~/__tests__/cypress/cypress/utils/users';
import { testPagination } from '~/__tests__/cypress/cypress/utils/pagination';

describe('Data science projects details', () => {
it('should not have option to create new project', () => {
Expand Down Expand Up @@ -80,6 +81,30 @@ describe('Data science projects details', () => {
projectListPage.shouldBeEmpty();
});

it('validate pagination', () => {
const totalItems = 50;
const mockProject: ProjectKind[] = Array.from({ length: totalItems }, (_, i) =>
mockProjectK8sResource({
k8sName: `ds-project-${i}`,
displayName: `DS Project ${i}`,
isDSProject: true,
}),
);
mockProjectK8sResource({});
cy.interceptK8sList(ProjectModel, mockK8sResourceList(mockProject));
projectListPage.visit();

// top pagination
testPagination({ totalItems, firstElement: 'DS Project 0', paginationVariant: 'top' });

// bottom pagination
testPagination({
totalItems,
firstElement: 'DS Project 0',
paginationVariant: 'bottom',
});
});

it('should react to updates through web sockets', () => {
const projectsMock = mockProjectsK8sList();
const projects = projectsMock.items;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ class Pagination {
findInput() {
return this.find().findByRole('spinbutton', { name: 'Current page' });
}

private findMenuToggleButton() {
return this.find()
.find(this.top ? '#table-pagination-top-toggle' : '#table-pagination-bottom-toggle')
.click();
}

selectToggleOption(name: string) {
return this.findMenuToggleButton().parents().findByRole('menuitem', { name }).click();
}
}

export const tablePagination = {
Expand Down
47 changes: 47 additions & 0 deletions frontend/src/__tests__/cypress/cypress/utils/pagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { tablePagination } from '~/__tests__/cypress/cypress/pages/components/Pagination';

type PaginationProp = {
totalItems: number;
firstElement: string;
paginationVariant: 'top' | 'bottom';
};

export const testPagination = ({
totalItems,
firstElement,
paginationVariant,
}: PaginationProp): void => {
const pagination = paginationVariant === 'top' ? tablePagination.top : tablePagination.bottom;

// check for 10 per page
pagination.findFirstButton().should('be.disabled');
pagination.findLastButton().click();
pagination.findInput().should('have.value', Math.ceil(totalItems / 10));
pagination.findLastButton().should('be.disabled');
pagination.findFirstButton().click();
pagination.findInput().should('have.value', '1');
pagination.findFirstButton().should('be.disabled');

pagination.findNextButton().click();
pagination.findInput().should('have.value', '2');
pagination.findNextButton().click();
pagination.findInput().should('have.value', '3');

pagination.findPreviousButton().click();
pagination.findInput().should('have.value', '2');
pagination.findPreviousButton().click();
pagination.findInput().should('have.value', '1');

// 20 per page
pagination.selectToggleOption('20 per page');
pagination.findFirstButton().should('be.disabled');
cy.findByText(firstElement).should('exist');
pagination.findLastButton().click();
cy.findByText(firstElement).should('not.exist');
pagination.findInput().should('have.value', Math.ceil(totalItems / 20));
pagination.findLastButton().should('be.disabled');
pagination.findFirstButton().click();
pagination.findInput().should('have.value', '1');
pagination.findFirstButton().should('be.disabled');
pagination.selectToggleOption('10 per page');
};

0 comments on commit 9fde61f

Please sign in to comment.