From daca134b53a6dc3569dbc174d177cc609270c183 Mon Sep 17 00:00:00 2001 From: Cody Jackson Date: Thu, 27 Feb 2025 19:28:28 -0700 Subject: [PATCH] Resolving a reference to an undefined `lockedExist` and adding tests for project memberships with custom permissions Fixes https://github.com/rancher/dashboard/issues/12828 --- .../explorer/cluster-project-members.po.ts | 34 +++++++++++++++++ .../explorer2/cluster-project-members.spec.ts | 37 ++++++++++++++++++- shell/components/ExplorerMembers.vue | 3 +- shell/components/form/ProjectMemberEditor.vue | 9 +++-- 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/cypress/e2e/po/pages/explorer/cluster-project-members.po.ts b/cypress/e2e/po/pages/explorer/cluster-project-members.po.ts index 7e2d625e051..98ede8f0aca 100644 --- a/cypress/e2e/po/pages/explorer/cluster-project-members.po.ts +++ b/cypress/e2e/po/pages/explorer/cluster-project-members.po.ts @@ -2,6 +2,9 @@ import PagePo from '@/cypress/e2e/po/pages/page.po'; import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po'; import SelectPrincipalPo from '@/cypress/e2e/po/components/select-principal.po'; import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po'; +import RadioGroupInputPo from '@/cypress/e2e/po/components/radio-group-input.po'; +import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po'; +import SortableTablePo from '@/cypress/e2e/po/components/sortable-table.po'; export default class ClusterProjectMembersPo extends PagePo { private static createPath(clusterId: string, tabId: string) { @@ -20,6 +23,12 @@ export default class ClusterProjectMembersPo extends PagePo { return cy.get('.btn.role-primary.pull-right').click(); } + triggerAddProjectMemberAction(projectLabel: string) { + const cleanLabel = projectLabel.replace(' ', '').toLowerCase(); + + return cy.get(`[data-testid="add-project-member-${ cleanLabel }"]`).click(); + } + selectClusterOrProjectMember(name: string) { const selectClusterOrProjectMember = new SelectPrincipalPo(`[data-testid="cluster-member-select"]`, this.self()); @@ -28,6 +37,27 @@ export default class ClusterProjectMembersPo extends PagePo { selectClusterOrProjectMember.clickOptionWithLabel(name); } + selectProjectCustomPermission() { + const permissionOptions = new RadioGroupInputPo('[data-testid="permission-options"]'); + + permissionOptions.checkExists(); + + permissionOptions.set(3); + } + + checkTheseProjectCustomPermissions(permissionIndices: number[]) { + permissionIndices.forEach((permissionIndex) => { + const checkbox = new CheckboxInputPo(`[data-testid="custom-permission-${ permissionIndex }"]`); + + checkbox.checkExists(); + checkbox.set(); + }); + } + + submitProjectCreateButton() { + return cy.get('[data-testid="card-actions-slot"] button.role-primary').click(); + } + saveCreateForm(): AsyncButtonPo { return new AsyncButtonPo('[data-testid="form-save"]', this.self()); } @@ -47,4 +77,8 @@ export default class ClusterProjectMembersPo extends PagePo { listElementWithName(name:string) { return this.sortableTable().rowElementWithName(name); } + + projectTable() { + return new SortableTablePo('#project-membership [data-testid="sortable-table-list-container"]'); + } } diff --git a/cypress/e2e/tests/pages/explorer2/cluster-project-members.spec.ts b/cypress/e2e/tests/pages/explorer2/cluster-project-members.spec.ts index a9a42f32351..1207f043718 100644 --- a/cypress/e2e/tests/pages/explorer2/cluster-project-members.spec.ts +++ b/cypress/e2e/tests/pages/explorer2/cluster-project-members.spec.ts @@ -12,7 +12,8 @@ describe('Cluster Project and Members', { tags: ['@explorer2', '@adminUser'] }, beforeEach(() => { cy.login(); }); - it('Members added to both Cluster Membership should not show "Loading..." next to their names', () => { + + it('Should create a new user', () => { const usersAdmin = new UsersPo('_'); const userCreate = usersAdmin.createEdit(); @@ -25,6 +26,10 @@ describe('Cluster Project and Members', { tags: ['@explorer2', '@adminUser'] }, userCreate.confirmNewPass().set(standardPassword); userCreate.saveCreateWithErrorRetry(); usersAdmin.waitForPageWithExactUrl(); + }); + + it('Members added to both Cluster Membership should not show "Loading..." next to their names', () => { + HomePagePo.goTo(); // add user to Cluster membership const clusterMembership = new ClusterProjectMembersPo('local', 'cluster-membership'); @@ -34,6 +39,7 @@ describe('Cluster Project and Members', { tags: ['@explorer2', '@adminUser'] }, clusterMembership.waitForPageWithSpecificUrl('/c/local/explorer'); clusterMembership.navToSideMenuEntryByLabel('Cluster and Project Members'); clusterMembership.triggerAddClusterOrProjectMemberAction(); + clusterMembership.selectClusterOrProjectMember(username); cy.intercept('POST', '/v3/clusterroletemplatebindings').as('createClusterMembership'); clusterMembership.saveCreateForm().click(); @@ -67,4 +73,33 @@ describe('Cluster Project and Members', { tags: ['@explorer2', '@adminUser'] }, clusterMembership.cancelCreateForm().click(); clusterMembership.waitForPageWithExactUrl(); }); + it('Can create a member with custom permissions', () => { + // add user to Cluster membership + const projectMembership = new ClusterProjectMembersPo('local', 'project-membership'); + + projectMembership.goTo(); + projectMembership.waitForPageWithSpecificUrl('/c/local/explorer/members#project-membership'); + projectMembership.triggerAddProjectMemberAction('system'); + projectMembership.selectProjectCustomPermission(); + projectMembership.selectClusterOrProjectMember(username); + projectMembership.checkTheseProjectCustomPermissions([0, 1]); + + cy.intercept('POST', '/v3/projectroletemplatebindings').as('createProjectMembership'); + projectMembership.submitProjectCreateButton(); + cy.wait('@createProjectMembership'); + cy.get('.modal-overlay').should('not.exist'); + + cy.get('body tbody').then((el) => { + if (el.find('tr.no-rows').is(':visible')) { + cy.reload(); + } + + projectMembership.projectTable().rowElementWithName(username).should('have.length', 1); + projectMembership.projectTable().rowElementWithName(username).find('td:nth-of-type(3)').invoke('text') + .then((t) => { + expect(t).to.include('Create Namespaces'); + expect(t).to.include('Manage Config Maps'); + }); + }); + }); }); diff --git a/shell/components/ExplorerMembers.vue b/shell/components/ExplorerMembers.vue index 527c660a4bf..75a7e5bdc66 100644 --- a/shell/components/ExplorerMembers.vue +++ b/shell/components/ExplorerMembers.vue @@ -355,7 +355,8 @@ export default {