From 12f1ff0977f9b9ccdcb1609c8399a47ea38163cb Mon Sep 17 00:00:00 2001 From: Azure Shi Date: Thu, 19 Sep 2024 12:46:10 -0400 Subject: [PATCH 1/4] Add assertions for bucket details drawer tests --- .../bucket-create-gen2.spec.ts | 108 ++++++++++++++++-- .../support/intercepts/object-storage.ts | 23 ++++ 2 files changed, 121 insertions(+), 10 deletions(-) diff --git a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts index dce48e600f3..f6e9a8e8557 100644 --- a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts @@ -5,6 +5,7 @@ import { mockGetBuckets, mockDeleteBucket, mockCreateBucket, + mockGetBucketAccess, } from 'support/intercepts/object-storage'; import { mockGetRegions } from 'support/intercepts/regions'; import { ui } from 'support/ui'; @@ -102,14 +103,72 @@ describe('Object Storage Gen2 create bucket tests', () => { }); }; + const bucketRateLimitsNotice = + 'Specifies the maximum Requests Per Second (RPS) for a bucket. To increase it to High, open a support ticket. Understand bucket rate limits.'; + const CORSNotice = + 'CORS (Cross Origin Sharing) is not available for endpoint types E2 and E3'; + + // For E0/E1, confirm CORS toggle and ACL selection are both present + // For E2/E3, confirm rate limit notice and table are present, ACL selection is present, CORS toggle is absent + const checkBucketDetailsDrawer = ( + bucketLabel: string, + endpointType: string + ) => { + ui.drawer.findByTitle(bucketLabel).within(() => { + if ( + endpointType === 'Standard (E3)' || + endpointType === 'Standard (E2)' + ) { + cy.contains(bucketRateLimitsNotice).should('be.visible'); + cy.get('[data-testid="bucket-rate-limit-table"]').should('be.visible'); + cy.contains(CORSNotice).should('be.visible'); + } else { + cy.get('[data-testid="bucket-rate-limit-table"]').should('not.exist'); + ui.toggle + .find() + .should('have.attr', 'data-qa-toggle', 'true') + .should('be.visible'); + cy.contains('CORS Enabled').should('be.visible'); + } + + // Verify that all ACL selection show up as options + cy.findByLabelText('Access Control List (ACL)') + .should('be.visible') + .should('have.value', 'Private') + .click(); + ui.autocompletePopper + .findByTitle('Public Read') + .should('be.visible') + .should('be.enabled'); + ui.autocompletePopper + .findByTitle('Authenticated Read') + .should('be.visible') + .should('be.enabled'); + ui.autocompletePopper + .findByTitle('Public Read/Write') + .should('be.visible') + .should('be.enabled'); + ui.autocompletePopper + .findByTitle('Private') + .should('be.visible') + .should('be.enabled') + .click(); + + // Close the Details drawer + cy.get('[data-qa-close-drawer="true"]').should('be.visible').click(); + }); + }; + /** * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E0 * Confirms all endpoints are displayed regardless if there's multiple of the same type * Confirms S3 endpoint hostname displayed to differentiate between identical options in the dropdown + * Confirms correct information displays in the details drawer for all endpoint types */ it('can create a bucket with E0 endpoint type', () => { const endpointTypeE0 = 'Legacy (E0)'; const bucketLabel = randomLabel(); + const bucketCluster = 'us-iad-12'; mockGetBuckets([]).as('getBuckets'); mockDeleteBucket(bucketLabel, mockRegion.id).as('deleteBucket'); @@ -125,6 +184,7 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); + mockGetBucketAccess(bucketLabel, bucketCluster).as('getBucketAccess'); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([ @@ -213,9 +273,15 @@ describe('Object Storage Gen2 create bucket tests', () => { .closest('tr') .within(() => { cy.findByText(mockRegion.label).should('be.visible'); - ui.button.findByTitle('Delete').should('be.visible').click(); + // Confirm that clicking "Details" button for the bucket opens details drawer + ui.button.findByTitle('Details').should('be.visible').click(); }); + checkBucketDetailsDrawer(bucketLabel, endpointTypeE0); + + // Delete the bucket to clean up + ui.button.findByTitle('Delete').should('be.visible').click(); + ui.dialog .findByTitle(`Delete Bucket ${bucketLabel}`) .should('be.visible') @@ -236,10 +302,12 @@ describe('Object Storage Gen2 create bucket tests', () => { /** * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E1 + * Confirms correct information displays in the details drawer for all endpoint types */ it('can create a bucket with E1 endpoint type', () => { const endpointTypeE1 = 'Standard (E1)'; const bucketLabel = randomLabel(); + const bucketCluster = 'us-iad-12'; mockGetBuckets([]).as('getBuckets'); mockDeleteBucket(bucketLabel, mockRegion.id).as('deleteBucket'); @@ -255,6 +323,7 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); + mockGetBucketAccess(bucketLabel, bucketCluster).as('getBucketAccess'); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([ @@ -328,9 +397,15 @@ describe('Object Storage Gen2 create bucket tests', () => { .closest('tr') .within(() => { cy.findByText(mockRegion.label).should('be.visible'); - ui.button.findByTitle('Delete').should('be.visible').click(); + // Confirm that clicking "Details" button for the bucket opens details drawer + ui.button.findByTitle('Details').should('be.visible').click(); }); + checkBucketDetailsDrawer(bucketLabel, endpointTypeE1); + + // Delete the bucket to clean up + ui.button.findByTitle('Delete').should('be.visible').click(); + ui.dialog .findByTitle(`Delete Bucket ${bucketLabel}`) .should('be.visible') @@ -351,10 +426,12 @@ describe('Object Storage Gen2 create bucket tests', () => { /** * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E2 + * Confirms correct information displays in the details drawer for all endpoint types */ it('can create a bucket with E2 endpoint type', () => { const endpointTypeE2 = 'Standard (E2)'; const bucketLabel = randomLabel(); + const bucketCluster = 'us-iad-12'; mockGetBuckets([]).as('getBuckets'); mockDeleteBucket(bucketLabel, mockRegion.id).as('deleteBucket'); @@ -370,6 +447,7 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); + mockGetBucketAccess(bucketLabel, bucketCluster).as('getBucketAccess'); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([ @@ -405,9 +483,7 @@ describe('Object Storage Gen2 create bucket tests', () => { // Confirm bucket rate limits text for E2 endpoint cy.findByText('Bucket Rate Limits').should('be.visible'); - cy.contains( - 'Specifies the maximum Requests Per Second (RPS) for a bucket. To increase it to High, open a support ticket. Understand bucket rate limits.' - ).should('be.visible'); + cy.contains(bucketRateLimitsNotice).should('be.visible'); // Confirm bucket rate limit table should exist when E2 endpoint is selected cy.get('[data-testid="bucket-rate-limit-table"]').should('exist'); @@ -443,9 +519,15 @@ describe('Object Storage Gen2 create bucket tests', () => { .closest('tr') .within(() => { cy.findByText(mockRegion.label).should('be.visible'); - ui.button.findByTitle('Delete').should('be.visible').click(); + // Confirm that clicking "Details" button for the bucket opens details drawer + ui.button.findByTitle('Details').should('be.visible').click(); }); + checkBucketDetailsDrawer(bucketLabel, endpointTypeE2); + + // Delete the bucket to clean up + ui.button.findByTitle('Delete').should('be.visible').click(); + ui.dialog .findByTitle(`Delete Bucket ${bucketLabel}`) .should('be.visible') @@ -466,10 +548,12 @@ describe('Object Storage Gen2 create bucket tests', () => { /** * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E3 + * Confirms correct information displays in the details drawer for all endpoint types */ it('can create a bucket with E3 endpoint type', () => { const endpointTypeE3 = 'Standard (E3)'; const bucketLabel = randomLabel(); + const bucketCluster = 'us-iad-12'; mockGetBuckets([]).as('getBuckets'); mockDeleteBucket(bucketLabel, mockRegion.id).as('deleteBucket'); @@ -485,6 +569,7 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); + mockGetBucketAccess(bucketLabel, bucketCluster).as('getBucketAccess'); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([ @@ -521,9 +606,7 @@ describe('Object Storage Gen2 create bucket tests', () => { // Confirm bucket rate limits text for E3 endpoint cy.findByText('Bucket Rate Limits').should('be.visible'); - cy.contains( - 'Specifies the maximum Requests Per Second (RPS) for a bucket. To increase it to High, open a support ticket. Understand bucket rate limits.' - ).should('be.visible'); + cy.contains(bucketRateLimitsNotice).should('be.visible'); // Confirm bucket rate limit table should exist when E3 endpoint is selected cy.get('[data-testid="bucket-rate-limit-table"]').should('exist'); @@ -559,9 +642,14 @@ describe('Object Storage Gen2 create bucket tests', () => { .closest('tr') .within(() => { cy.findByText(mockRegion.label).should('be.visible'); - ui.button.findByTitle('Delete').should('be.visible').click(); + // Confirm that clicking "Details" button for the bucket opens details drawer + ui.button.findByTitle('Details').should('be.visible').click(); }); + checkBucketDetailsDrawer(bucketLabel, endpointTypeE3); + + // Delete the bucket to clean up + ui.button.findByTitle('Delete').should('be.visible').click(); ui.dialog .findByTitle(`Delete Bucket ${bucketLabel}`) .should('be.visible') diff --git a/packages/manager/cypress/support/intercepts/object-storage.ts b/packages/manager/cypress/support/intercepts/object-storage.ts index 0515ca8266b..280601099a5 100644 --- a/packages/manager/cypress/support/intercepts/object-storage.ts +++ b/packages/manager/cypress/support/intercepts/object-storage.ts @@ -504,3 +504,26 @@ export const mockGetObjectStorageEndpoints = ( paginateResponse(endpoints) ); }; + +/** + * Intercepts GET request to fetch access information (ACL, CORS) for a given Bucket and mock the response. + * + * + * @param label - Object storage bucket label. + * @param cluster - Object storage bucket cluster. + * + * @returns Cypress chainable. + */ +export const mockGetBucketAccess = ( + label: string, + cluster: string +): Cypress.Chainable => { + return cy.intercept( + 'GET', + apiMatcher(`object-storage/buckets/${cluster}/${label}/access`), + { + body: {}, + statusCode: 200, + } + ); +}; From 8c9535f37f625fae78697800657de65138693188 Mon Sep 17 00:00:00 2001 From: Azure Shi Date: Thu, 19 Sep 2024 12:51:26 -0400 Subject: [PATCH 2/4] Added changeset: Add assertions for bucket details drawer tests --- packages/manager/.changeset/pr-10971-tests-1726764686101.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-10971-tests-1726764686101.md diff --git a/packages/manager/.changeset/pr-10971-tests-1726764686101.md b/packages/manager/.changeset/pr-10971-tests-1726764686101.md new file mode 100644 index 00000000000..b904a51b98f --- /dev/null +++ b/packages/manager/.changeset/pr-10971-tests-1726764686101.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Tests +--- + +Add assertions for bucket details drawer tests ([#10971](https://github.com/linode/manager/pull/10971)) From dd3684d6ffcac0e540cd9c114de63584e129c850 Mon Sep 17 00:00:00 2001 From: Azure Shi Date: Tue, 24 Sep 2024 09:55:34 -0400 Subject: [PATCH 3/4] Add one more assertion to check toggle is not visible for E2,E3 --- .../e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts index f6e9a8e8557..5768aa1441a 100644 --- a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts @@ -122,6 +122,7 @@ describe('Object Storage Gen2 create bucket tests', () => { cy.contains(bucketRateLimitsNotice).should('be.visible'); cy.get('[data-testid="bucket-rate-limit-table"]').should('be.visible'); cy.contains(CORSNotice).should('be.visible'); + ui.toggle.find().should('not.exist'); } else { cy.get('[data-testid="bucket-rate-limit-table"]').should('not.exist'); ui.toggle From 4f22b8239e8f75869c7ec168506044c51caee327 Mon Sep 17 00:00:00 2001 From: Azure Shi Date: Fri, 11 Oct 2024 11:44:53 -0400 Subject: [PATCH 4/4] update comments --- .../bucket-create-gen2.spec.ts | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts index baf80020160..068b97e9ccb 100644 --- a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts @@ -140,7 +140,7 @@ describe('Object Storage Gen2 create bucket tests', () => { * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E0 * Confirms all endpoints are displayed regardless if there's multiple of the same type * Confirms S3 endpoint hostname displayed to differentiate between identical options in the dropdown - * Confirms correct information displays in the details drawer for all endpoint types + * Confirms correct information displays in the details drawer for a bucket with endpoint E0 */ it('can create a bucket with E0 endpoint type', () => { const endpointTypeE0 = 'Legacy (E0)'; @@ -161,7 +161,9 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); - mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as('getBucketAccess'); + mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as( + 'getBucketAccess' + ); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([ @@ -279,7 +281,7 @@ describe('Object Storage Gen2 create bucket tests', () => { /** * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E1 - * Confirms correct information displays in the details drawer for all endpoint types + * Confirms correct information displays in the details drawer for a bucket with endpoint E1 */ it('can create a bucket with E1 endpoint type', () => { const endpointTypeE1 = 'Standard (E1)'; @@ -300,7 +302,9 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); - mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as('getBucketAccess'); + mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as( + 'getBucketAccess' + ); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([ @@ -403,7 +407,7 @@ describe('Object Storage Gen2 create bucket tests', () => { /** * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E2 - * Confirms correct information displays in the details drawer for all endpoint types + * Confirms correct information displays in the details drawer for a bucket with endpoint E2 */ it('can create a bucket with E2 endpoint type', () => { const endpointTypeE2 = 'Standard (E2)'; @@ -424,7 +428,9 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); - mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as('getBucketAccess'); + mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as( + 'getBucketAccess' + ); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([ @@ -525,7 +531,7 @@ describe('Object Storage Gen2 create bucket tests', () => { /** * Confirms UI flow for creating a gen2 Object Storage bucket with endpoint E3 - * Confirms correct information displays in the details drawer for all endpoint types + * Confirms correct information displays in the details drawer for a bucket with endpoint E3 */ it('can create a bucket with E3 endpoint type', () => { const endpointTypeE3 = 'Standard (E3)'; @@ -546,7 +552,9 @@ describe('Object Storage Gen2 create bucket tests', () => { ); mockGetRegions(mockRegions); - mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as('getBucketAccess'); + mockGetBucketAccess(bucketLabel, bucketCluster, mockAccess).as( + 'getBucketAccess' + ); cy.visitWithLogin('/object-storage/buckets/create'); cy.wait([