Skip to content

Commit

Permalink
Cypress e2e Project Permissions Tests (#3460)
Browse files Browse the repository at this point in the history
* Jira Task - RHOAIENG-14369. Migrated  ODS-2194 to Cypress

* Abstracted project checker logic, changed fixture file names and contents

---------

Co-authored-by: Noam Manos <[email protected]>
  • Loading branch information
antowaddle and manosnoam authored Nov 13, 2024
1 parent 4ce7e5b commit 6b06634
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 21 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# testProjectAdminPermissions.cy.ts Test Data #
projectPermissionResourceName: "cypress-user-perm-test"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# testProjectContributorPermissions.cy.ts Test Data #
projectContributorResourceName: "cypress-user-perm-contr-test"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# testProjectCreation.cy.ts Test Data #
projectDisplayName: "Cypress Test Project"
projectDescription: "Cypress Test project description."
projectResourceName: "cypress-test-project"
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { DataScienceProjectData } from '~/__tests__/cypress/cypress/types';
import { projectDetails, projectListPage } from '~/__tests__/cypress/cypress/pages/projects';
import { permissions } from '~/__tests__/cypress/cypress/pages/permissions';
import { ADMIN_USER, TEST_USER } from '~/__tests__/cypress/cypress/utils/e2eUsers';
import { loadFixture } from '~/__tests__/cypress/cypress/utils/dataLoader';
import { createCleanProject } from '~/__tests__/cypress/cypress/utils/projectChecker';
import { deleteOpenShiftProject } from '~/__tests__/cypress/cypress/utils/oc_commands/project';

describe('Verify that users can provide admin project permissions to non-admin users', () => {
let testData: DataScienceProjectData;
let projectName: string;

// Setup: Load test data and ensure clean state
before(() => {
return loadFixture('e2e/dataScienceProjects/testProjectAdminPermissions.yaml')
.then((fixtureData: DataScienceProjectData) => {
testData = fixtureData;
projectName = testData.projectPermissionResourceName;
if (!projectName) {
throw new Error('Project name is undefined or empty in the loaded fixture');
}
cy.log(`Loaded project name: ${projectName}`);
return createCleanProject(projectName);
})
.then(() => {
cy.log(`Project ${projectName} confirmed to be created and verified successfully`);
});
});
after(() => {
// Delete provisioned Project
if (projectName) {
cy.log(`Deleting Project ${projectName} after the test has finished.`);
deleteOpenShiftProject(projectName);
}
});

it('Verify that user can be added as an Admin for a Project', () => {
// Authentication and navigation
cy.step('Log into the application');
cy.visitWithLogin('/', ADMIN_USER);

// Project navigation, add user and provide admin permissions
cy.step(
`Navigate to the Project list tab and search for ${testData.projectPermissionResourceName}`,
);
projectListPage.navigate();
projectListPage.filterProjectByName(testData.projectPermissionResourceName);
projectListPage.findProjectLink(testData.projectPermissionResourceName).click();
projectDetails.findSectionTab('permissions').click();

cy.step('Assign admin user Project Permissions');
permissions.findAddUserButton().click();
permissions.getUserTable().findAddInput().type(TEST_USER.USERNAME);
permissions
.getUserTable()
.selectPermission(TEST_USER.USERNAME, 'Admin Edit the project and manage user access');

cy.step(
`Save the user and validate that ${TEST_USER.USERNAME} has been saved with admin permissions`,
);
permissions.getUserTable().findSaveNewButton().should('exist').and('be.visible').click();
cy.contains(TEST_USER.USERNAME).should('exist');
});
it('Verify that user can access the created project with Admin rights', () => {
// Authentication and navigation
cy.step(`Log into the application with ${TEST_USER.USERNAME}`);
cy.visitWithLogin('/', TEST_USER);

// Project navigation and validate permissions tab is accessible
cy.step('Verify that the user has access to the created project and can access Permissions');
projectListPage.navigate();
projectListPage.filterProjectByName(testData.projectPermissionResourceName);
projectListPage.findProjectLink(testData.projectPermissionResourceName).click();
projectDetails.findSectionTab('permissions').click();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { deleteOpenShiftProject } from '~/__tests__/cypress/cypress/utils/oc_commands/project';
import { projectDetails, projectListPage } from '~/__tests__/cypress/cypress/pages/projects';
import type { DataScienceProjectData } from '~/__tests__/cypress/cypress/types';
import { permissions } from '~/__tests__/cypress/cypress/pages/permissions';
import { ADMIN_USER, TEST_USER } from '~/__tests__/cypress/cypress/utils/e2eUsers';
import { loadFixture } from '~/__tests__/cypress/cypress/utils/dataLoader';
import { createCleanProject } from '~/__tests__/cypress/cypress/utils/projectChecker';

describe('Verify that users can provide contributor project permissions to non-admin users', () => {
let testData: DataScienceProjectData;
let projectName: string;

// Setup: Load test data and ensure clean state
before(() => {
return loadFixture('e2e/dataScienceProjects/testProjectContributorPermissions.yaml')
.then((fixtureData: DataScienceProjectData) => {
testData = fixtureData;
projectName = testData.projectContributorResourceName;
if (!projectName) {
throw new Error('Project name is undefined or empty in the loaded fixture');
}
cy.log(`Loaded project name: ${projectName}`);
return createCleanProject(projectName);
})
.then(() => {
cy.log(`Project ${projectName} confirmed to be created and verified successfully`);
});
});
after(() => {
// Delete provisioned Project
if (projectName) {
cy.log(`Deleting Project ${projectName} after the test has finished.`);
deleteOpenShiftProject(projectName);
}
});

it('Verify that user can be added as a Contributor for a Project', () => {
// Authentication and navigation
cy.step('Log into the application');
cy.visitWithLogin('/', ADMIN_USER);

// Project navigation, add user and provide contributor permissions
cy.step(
`Navigate to the Project list tab and search for ${testData.projectContributorResourceName}`,
);
projectListPage.navigate();
projectListPage.filterProjectByName(testData.projectContributorResourceName);
projectListPage.findProjectLink(testData.projectContributorResourceName).click();
projectDetails.findSectionTab('permissions').click();

cy.step('Assign contributor user Project Permissions');
permissions.findAddUserButton().click();
permissions.getUserTable().findAddInput().type(TEST_USER.USERNAME);
cy.debug();
permissions
.getUserTable()
.selectPermission(TEST_USER.USERNAME, 'Contributor View and edit the project components');

cy.step(
`Save the user and validate that ${TEST_USER.USERNAME} has been saved with Contributor permissions`,
);
permissions.getUserTable().findSaveNewButton().should('exist').and('be.visible').click();
cy.contains(TEST_USER.USERNAME).should('exist');
});
it('Verify that user can access the created project as a Contributor', () => {
// Authentication and navigation
cy.step(`Log into the application with ${TEST_USER.USERNAME}`);
cy.visitWithLogin('/', TEST_USER);

// Project navigation and validate permissions tab is accessible
cy.step('Verify that the user has access to the created project but cannot access Permissions');
projectListPage.navigate();
projectListPage.filterProjectByName(testData.projectContributorResourceName);
projectListPage.findProjectLink(testData.projectContributorResourceName).click();
cy.log('Attempting to find permissions tab which should not be visible');
projectDetails.findSectionTab('permissions').should('not.exist');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ describe('Verify Data Science Project - Creation and Deletion', () => {
// Setup: Load test data and ensure clean state
before(() => {
return cy
.fixture('e2e/dataScienceProjects/dataScienceProject.yaml', 'utf8')
.fixture('e2e/dataScienceProjects/testProjectCreation.yaml', 'utf8')
.then((yamlContent: string) => {
testData = yaml.load(yamlContent) as DataScienceProjectData;
const projectName = testData.dsOCProjectName;
const projectName = testData.projectResourceName;

if (!projectName) {
throw new Error('Project name is undefined or empty');
Expand All @@ -30,7 +30,7 @@ describe('Verify Data Science Project - Creation and Deletion', () => {
return verifyOpenShiftProjectExists(projectName);
})
.then((exists: boolean) => {
const projectName = testData.dsOCProjectName;
const projectName = testData.projectResourceName;
// Clean up existing project if it exists
if (exists) {
cy.log(`Project ${projectName} exists. Deleting before test.`);
Expand All @@ -55,20 +55,18 @@ describe('Verify Data Science Project - Creation and Deletion', () => {

// Input project details
cy.step('Enter valid project information');
createProjectModal.k8sNameDescription.findDisplayNameInput().type(testData.dsProjectName);
createProjectModal.k8sNameDescription
.findDescriptionInput()
.type(testData.dsProjectDescription);
createProjectModal.k8sNameDescription.findDisplayNameInput().type(testData.projectDisplayName);
createProjectModal.k8sNameDescription.findDescriptionInput().type(testData.projectDescription);

// Submit project creation
cy.step('Save the project');
createProjectModal.findSubmitButton().click();

// Verify project creation
cy.step(`Verify that the project ${testData.dsProjectName} has been created`);
cy.url().should('include', `/projects/${testData.dsOCProjectName}`);
projectDetails.verifyProjectName(testData.dsProjectName);
projectDetails.verifyProjectDescription(testData.dsProjectDescription);
cy.step(`Verify that the project ${testData.projectDisplayName} has been created`);
cy.url().should('include', `/projects/${testData.projectResourceName}`);
projectDetails.verifyProjectName(testData.projectDisplayName);
projectDetails.verifyProjectDescription(testData.projectDescription);

// Initiate project deletion
cy.step('Deleting the project - clicking actions');
Expand All @@ -78,12 +76,12 @@ describe('Verify Data Science Project - Creation and Deletion', () => {
// Confirm project deletion
cy.step('Entering project details for deletion');
deleteModal.shouldBeOpen();
deleteModal.findInput().type(testData.dsProjectName);
deleteModal.findInput().type(testData.projectDisplayName);
deleteModal.findSubmitButton().should('be.enabled').click();

// Verify project deletion
cy.step(`Verify that the project ${testData.dsProjectName} has been deleted`);
projectListPage.filterProjectByName(testData.dsProjectName);
cy.step(`Verify that the project ${testData.projectDisplayName} has been deleted`);
projectListPage.filterProjectByName(testData.projectDisplayName);
projectListPage.findEmptyResults();
});
});
8 changes: 5 additions & 3 deletions frontend/src/__tests__/cypress/cypress/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ export type TestConfig = {
};

export type DataScienceProjectData = {
dsProjectName: string;
dsProjectDescription: string;
dsOCProjectName: string;
projectDisplayName: string;
projectDescription: string;
projectResourceName: string;
projectPermissionResourceName: string;
projectContributorResourceName: string;
};

export type NimServingResponse = {
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/__tests__/cypress/cypress/utils/dataLoader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import yaml from 'js-yaml';
import type { DataScienceProjectData } from '~/__tests__/cypress/cypress/types';

// Load fixture function that returns a specific type
export const loadFixture = (fixturePath: string): Cypress.Chainable<DataScienceProjectData> => {
return cy.fixture(fixturePath, 'utf8').then((yamlContent: string) => {
const data = yaml.load(yamlContent) as DataScienceProjectData;

return data;
});
};
28 changes: 28 additions & 0 deletions frontend/src/__tests__/cypress/cypress/utils/projectChecker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
verifyOpenShiftProjectExists,
deleteOpenShiftProject,
createOpenShiftProject,
} from '~/__tests__/cypress/cypress/utils/oc_commands/project';

export const createAndVerifyProject = (projectName: string): void => {
createOpenShiftProject(projectName).then((result) => {
expect(result.code).to.equal(0);
});

verifyOpenShiftProjectExists(projectName).then((exists) => {
if (!exists) {
throw new Error(`Expected project ${projectName} to exist, but it does not.`);
}
});
};

export const createCleanProject = (projectName: string): void => {
verifyOpenShiftProjectExists(projectName).then((exists) => {
if (exists) {
cy.log(`Project ${projectName} already exists. Deleting it.`);
deleteOpenShiftProject(projectName);
}
cy.log(`Creating project ${projectName}`);
createAndVerifyProject(projectName);
});
};

0 comments on commit 6b06634

Please sign in to comment.