From 54691605a7e09f8c1062feabb5ccb56e3e3fd480 Mon Sep 17 00:00:00 2001 From: hasyed-akamai Date: Wed, 18 Dec 2024 12:35:34 +0530 Subject: [PATCH] test: [M3-8608] - Cypress test for restricted user Image non-empty landing page (#11335) * test: [M3-8608] - Cypress test for restricted user Image non-empty landing page * Move function outside describe block and use `closest()` locator to locate tables * Added changeset: Cypress test for restricted user Image non-Empty landing page * Move `checkActionMenu` function above `describe` block --- .../pr-11335-added-1732792310960.md | 5 + .../images-non-empty-landing-page.spec.ts | 136 ++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 packages/manager/.changeset/pr-11335-added-1732792310960.md create mode 100644 packages/manager/cypress/e2e/core/images/images-non-empty-landing-page.spec.ts diff --git a/packages/manager/.changeset/pr-11335-added-1732792310960.md b/packages/manager/.changeset/pr-11335-added-1732792310960.md new file mode 100644 index 00000000000..021a002b25a --- /dev/null +++ b/packages/manager/.changeset/pr-11335-added-1732792310960.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Added +--- + +Cypress test for restricted user Image non-Empty landing page ([#11335](https://github.com/linode/manager/pull/11335)) diff --git a/packages/manager/cypress/e2e/core/images/images-non-empty-landing-page.spec.ts b/packages/manager/cypress/e2e/core/images/images-non-empty-landing-page.spec.ts new file mode 100644 index 00000000000..5154138d6f8 --- /dev/null +++ b/packages/manager/cypress/e2e/core/images/images-non-empty-landing-page.spec.ts @@ -0,0 +1,136 @@ +import { imageFactory } from 'src/factories'; +import { ui } from 'support/ui'; +import { mockGetAllImages } from 'support/intercepts/images'; +import { profileFactory } from 'src/factories'; +import { randomLabel } from 'support/util/random'; +import { grantsFactory } from 'src/factories'; +import { accountUserFactory } from 'src/factories'; +import { mockGetUser } from 'support/intercepts/account'; +import { + mockGetProfile, + mockGetProfileGrants, +} from 'support/intercepts/profile'; +import { Image } from '@linode/api-v4'; + +function checkActionMenu(tableAlias: string, mockImages: any[]) { + mockImages.forEach((image) => { + cy.get(tableAlias) + .find('tbody tr') + .should('contain', image.label) + .then(($row) => { + // If the row contains the label, proceed with clicking the action menu + const actionButton = $row.find( + `button[aria-label="Action menu for Image ${image.label}"]` + ); + if (actionButton) { + cy.wrap(actionButton).click(); + + // Check that the item with text 'Deploy to New Linode' is active + cy.get('ul[role="menu"]') + .contains('Deploy to New Linode') + .should('be.visible') + .and('be.enabled'); + + // Check that all other items are disabled + cy.get('ul[role="menu"]') + .find('li') + .not(':contains("Deploy to New Linode")') + .each(($li) => { + cy.wrap($li).should('be.visible').and('be.disabled'); + }); + + // Close the action menu by clicking on Custom Image Title of the screen + cy.get('body').click(0, 0); + } + }); + }); +} + +describe('image landing checks for non-empty state with restricted user', () => { + beforeEach(() => { + const mockImages: Image[] = new Array(3).fill(null).map( + (_item: null, index: number): Image => { + return imageFactory.build({ + label: `Image ${index}`, + tags: [index % 2 == 0 ? 'even' : 'odd', 'nums'], + }); + } + ); + + // Mock setup to display the Image landing page in an non-empty state + mockGetAllImages(mockImages).as('getImages'); + + // Alias the mockImages array + cy.wrap(mockImages).as('mockImages'); + }); + + it('checks restricted user with read access has no access to create image and can see existing images', () => { + // Mock setup for user profile, account user, and user grants with restricted permissions, + const mockProfile = profileFactory.build({ + username: randomLabel(), + restricted: true, + }); + + const mockUser = accountUserFactory.build({ + username: mockProfile.username, + restricted: true, + user_type: 'default', + }); + + const mockGrants = grantsFactory.build({ + global: { + add_images: false, + }, + }); + + mockGetProfile(mockProfile); + mockGetProfileGrants(mockGrants); + mockGetUser(mockUser); + + // Login and wait for application to load + cy.visitWithLogin('/images'); + cy.wait('@getImages'); + cy.url().should('endWith', '/images'); + + cy.contains('h3', 'Custom Images') + .closest('div[data-qa-paper="true"]') + .find('[role="table"]') + .should('exist') + .as('customImageTable'); + + cy.contains('h3', 'Recovery Images') + .closest('div[data-qa-paper="true"]') + .find('[role="table"]') + .should('exist') + .as('recoveryImageTable'); + + // Assert that Create Image button is visible and disabled + ui.button + .findByTitle('Create Image') + .should('be.visible') + .and('be.disabled') + .trigger('mouseover'); + + // Assert that tooltip is visible with message + ui.tooltip + .findByText( + "You don't have permissions to create Images. Please contact your account administrator to request the necessary permissions." + ) + .should('be.visible'); + + cy.get('@mockImages').then((mockImages) => { + // Assert that the correct number of Image entries are present in the customImageTable + cy.get('@customImageTable') + .find('tbody tr') + .should('have.length', mockImages.length); + + // Assert that the correct number of Image entries are present in the recoveryImageTable + cy.get('@recoveryImageTable') + .find('tbody tr') + .should('have.length', mockImages.length); + + checkActionMenu('@customImageTable', mockImages); // For the custom image table + checkActionMenu('@recoveryImageTable', mockImages); // For the recovery image table + }); + }); +});