Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: [M3-8447] - Add cypress integration test for OBJ gen 2 Bucket Details Properties tab #11002

Merged
merged 25 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
65b6273
skeleton tests
coliu-akamai Sep 23, 2024
3ca3c1a
test for E0 endpoint
coliu-akamai Sep 23, 2024
7b930b0
finish other tests, now time to cleanup
coliu-akamai Sep 24, 2024
c6b18c3
remove duplication
coliu-akamai Sep 24, 2024
2df76a5
update description
coliu-akamai Sep 24, 2024
278c657
Added changeset: Add cypress integration test for OBJ gen 2 bucket de…
coliu-akamai Sep 24, 2024
21915be
update test descriptions
coliu-akamai Sep 24, 2024
328418a
Merge branch 'develop' into m3-8440
coliu-akamai Sep 24, 2024
014b6c1
Merge branch 'develop' into m3-8440
coliu-akamai Sep 24, 2024
7dc731c
rearranging some things
coliu-akamai Sep 24, 2024
cf73bc8
skeleton tests
coliu-akamai Sep 24, 2024
7ee3147
need to cleanup
coliu-akamai Sep 24, 2024
9ab3a38
cleanup: use contains instead of find by text
coliu-akamai Sep 24, 2024
24b7559
why are the create tests also running without the .only??
coliu-akamai Sep 24, 2024
eba3736
update abstraction
coliu-akamai Sep 24, 2024
fa9422f
parameterize tests based on feedback @jdamore-linode
coliu-akamai Sep 26, 2024
67565f8
confirm testing AC and update tests/fix bug
coliu-akamai Oct 1, 2024
56ab65d
Merge branch 'develop' into m3-8440
coliu-akamai Oct 1, 2024
494cb40
Merge branch 'm3-8440' into m3-8447
coliu-akamai Oct 1, 2024
f623755
updated tests based on confirmed AC
coliu-akamai Oct 1, 2024
72f7046
remove .only
coliu-akamai Oct 1, 2024
82c085d
utils file
coliu-akamai Oct 1, 2024
c092c0b
changeset + add comment
coliu-akamai Oct 1, 2024
0caa417
update comment
coliu-akamai Oct 1, 2024
45875c8
Merge branch 'develop' into m3-8447
coliu-akamai Oct 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11002-tests-1727812216912.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tests
---

Add integration test for Object Storage Gen2 Properties tab ([#11002](https://github.com/linode/manager/pull/11002))
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from 'support/intercepts/object-storage';
import { mockGetRegions } from 'support/intercepts/regions';
import { ui } from 'support/ui';
import { checkRateLimitsTable } from 'support/util/object-storage-gen2';
import { randomLabel } from 'support/util/random';
import {
accountFactory,
Expand All @@ -16,10 +17,7 @@ import {
regionFactory,
} from 'src/factories';
import { chooseRegion } from 'support/util/regions';
import type {
ObjectStorageEndpoint,
ObjectStorageEndpointTypes,
} from '@linode/api-v4';
import type { ObjectStorageEndpoint } from '@linode/api-v4';

describe('Object Storage Gen2 create bucket tests', () => {
beforeEach(() => {
Expand Down Expand Up @@ -72,36 +70,6 @@ describe('Object Storage Gen2 create bucket tests', () => {
}),
];

const checkRateLimitsTable = (endpointType: ObjectStorageEndpointTypes) => {
const expectedHeaders = ['Limits', 'GET', 'PUT', 'LIST', 'DELETE', 'OTHER'];
const expectedBasicValues = ['Basic', '2,000', '500', '100', '200', '400'];
const expectedHighValues =
endpointType === 'E3'
? ['High', '20,000', '2,000', '400', '400', '1,000']
: ['High', '5,000', '1,000', '200', '200', '800'];

cy.get('[data-testid="bucket-rate-limit-table"]').within(() => {
expectedHeaders.forEach((header, index) => {
cy.get('th').eq(index).should('contain.text', header);
});

cy.contains('tr', 'Basic').within(() => {
expectedBasicValues.forEach((value, index) => {
cy.get('td').eq(index).should('contain.text', value);
});
});

cy.contains('tr', 'High').within(() => {
expectedHighValues.forEach((value, index) => {
cy.get('td').eq(index).should('contain.text', value);
});
});

// Check that Basic radio button is checked
cy.findByLabelText('Basic').should('be.checked');
});
};

/**
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
mockGetObjectStorageEndpoints,
mockGetBucketAccess,
} from 'support/intercepts/object-storage';
import { checkRateLimitsTable } from 'support/util/object-storage-gen2';
import { ui } from 'support/ui';
import {
accountFactory,
objectStorageBucketFactoryGen2,
Expand All @@ -13,7 +15,7 @@ import {
} from 'src/factories';
import { ACLType, ObjectStorageEndpointTypes } from '@linode/api-v4';

describe('Object Storage Gen 2 bucket details Access and SSL/TLS tabs', () => {
describe('Object Storage Gen 2 bucket details tabs', () => {
beforeEach(() => {
mockAppendFeatureFlags({
objMultiCluster: true,
Expand Down Expand Up @@ -56,87 +58,181 @@ describe('Object Storage Gen 2 bucket details Access and SSL/TLS tabs', () => {
return { mockBucket, mockEndpoint };
};

['E0', 'E1'].forEach((endpoint: ObjectStorageEndpointTypes) => {
/**
* Parameterized test for object storage endpoint types E0 and E1
* - Confirms the CORS toggle still appears
* - Confirms the SSL/TLS tab appears
*/
it(`does not hide the CORS toggle and SSL/TLS tab for buckets with an ${endpoint} endpoint`, () => {
const { mockBucket, mockEndpoint } = createMocksBasedOnEndpointType(
endpoint
);
const { cluster, label } = mockBucket;

mockGetBucketAccess(label, cluster, mockAccess).as('getBucketAccess');
mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as(
'getBucketsForRegion'
);
mockGetObjectStorageEndpoints([mockEndpoint]).as(
'getObjectStorageEndpoints'
);

cy.visitWithLogin(`/object-storage/buckets/${cluster}/${label}/access`);
cy.wait([
'@getFeatureFlags',
'@getAccount',
'@getObjectStorageEndpoints',
'@getBucketsForRegion',
'@getBucketAccess',
]);

cy.findByText('Bucket Access').should('be.visible');
cy.findByLabelText('Access Control List (ACL)').should('be.visible');
// confirm CORS is visible
cy.findByText('CORS Enabled').should('be.visible');
cy.contains(
'Whether Cross-Origin Resource Sharing is enabled for all origins. For more fine-grained control of CORS, please use another S3-compatible tool.'
).should('be.visible');

// Confirm SSL/TLS tab is not hidden and is clickable
cy.findByText('SSL/TLS').should('be.visible').click();
cy.url().should('endWith', '/ssl');
describe('Access and SSL/TLS tabs', () => {
['E0', 'E1'].forEach((endpoint: ObjectStorageEndpointTypes) => {
/**
* Parameterized test for object storage endpoint types E0 and E1
* - Confirms the CORS toggle still appears
* - Confirms the SSL/TLS tab appears
*/
it(`does not hide the CORS toggle and SSL/TLS tab for buckets with an ${endpoint} endpoint`, () => {
const { mockBucket, mockEndpoint } = createMocksBasedOnEndpointType(
endpoint
);
const { cluster, label } = mockBucket;

mockGetBucketAccess(label, cluster, mockAccess).as('getBucketAccess');
mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as(
'getBucketsForRegion'
);
mockGetObjectStorageEndpoints([mockEndpoint]).as(
'getObjectStorageEndpoints'
);

cy.visitWithLogin(`/object-storage/buckets/${cluster}/${label}/access`);
cy.wait([
'@getFeatureFlags',
'@getAccount',
'@getObjectStorageEndpoints',
'@getBucketsForRegion',
'@getBucketAccess',
]);

cy.findByText('Bucket Access').should('be.visible');
cy.findByLabelText('Access Control List (ACL)').should('be.visible');
// confirm CORS is visible
cy.findByText('CORS Enabled').should('be.visible');
cy.contains(
'Whether Cross-Origin Resource Sharing is enabled for all origins. For more fine-grained control of CORS, please use another S3-compatible tool.'
).should('be.visible');

// Confirm SSL/TLS tab is not hidden and is clickable
cy.findByText('SSL/TLS').should('be.visible').click();
cy.url().should('endWith', '/ssl');
});
});

['E2', 'E3'].forEach((endpoint: ObjectStorageEndpointTypes) => {
/**
* Parameterized test for object storage endpoint types E2 and E3
* - Confirms the CORS toggle is hidden
* - Confirms the SSL/TLS tab is hidden
*/
it(`hides the CORS toggle and SSL/TLS tab for for buckets with an ${endpoint} endpoint`, () => {
const { mockBucket, mockEndpoint } = createMocksBasedOnEndpointType(
endpoint
);
const { cluster, label } = mockBucket;

mockGetBucketAccess(label, cluster, mockAccess).as('getBucketAccess');
mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as(
'getBucketsForRegion'
);
mockGetObjectStorageEndpoints([mockEndpoint]).as(
'getObjectStorageEndpoints'
);

cy.visitWithLogin(`/object-storage/buckets/${cluster}/${label}/access`);
cy.wait([
'@getFeatureFlags',
'@getAccount',
'@getObjectStorageEndpoints',
'@getBucketsForRegion',
'@getBucketAccess',
]);

cy.findByText('Bucket Access').should('be.visible');
cy.findByLabelText('Access Control List (ACL)').should('be.visible');
// confirm CORS is not visible
cy.contains(
'CORS (Cross Origin Sharing) is not available for endpoint types E2 and E3'
).should('be.visible');

// confirms the SSL/TLS tab is not present
cy.findByText('SSL/TLS').should('not.exist');
});
});
});

['E2', 'E3'].forEach((endpoint: ObjectStorageEndpointTypes) => {
/**
* Parameterized test for object storage endpoint types E2 and E3
* - Confirms the CORS toggle is hidden
* - Confirms the SSL/TLS tab is hidden
*/
it(`hides the CORS toggle and SSL/TLS tab for for buckets with an ${endpoint} endpoint`, () => {
const { mockBucket, mockEndpoint } = createMocksBasedOnEndpointType(
endpoint
);
const { cluster, label } = mockBucket;

mockGetBucketAccess(label, cluster, mockAccess).as('getBucketAccess');
mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as(
'getBucketsForRegion'
);
mockGetObjectStorageEndpoints([mockEndpoint]).as(
'getObjectStorageEndpoints'
);

cy.visitWithLogin(`/object-storage/buckets/${cluster}/${label}/access`);
cy.wait([
'@getFeatureFlags',
'@getAccount',
'@getObjectStorageEndpoints',
'@getBucketsForRegion',
'@getBucketAccess',
]);

cy.findByText('Bucket Access').should('be.visible');
cy.findByLabelText('Access Control List (ACL)').should('be.visible');
// confirm CORS is not visible
cy.contains(
'CORS (Cross Origin Sharing) is not available for endpoint types E2 and E3'
).should('be.visible');

// confirms the SSL/TLS tab is not present
cy.findByText('SSL/TLS').should('not.exist');
describe('Properties tab', () => {
coliu-akamai marked this conversation as resolved.
Show resolved Hide resolved
['E0', 'E1'].forEach((endpoint: ObjectStorageEndpointTypes) => {
/**
* Parameterized test for buckets with endpoint types of E0 and E1
* - Confirms the Properties tab is visible
* - Confirms there is no bucket rate limits table
*/
it(`confirms the Properties tab does not have a rate limits table for buckets with endpoint type ${endpoint}`, () => {
const { mockBucket, mockEndpoint } = createMocksBasedOnEndpointType(
endpoint
);
const { cluster, label } = mockBucket;

mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as(
'getBucketsForRegion'
);
mockGetObjectStorageEndpoints([mockEndpoint]).as(
'getObjectStorageEndpoints'
);

cy.visitWithLogin(
`/object-storage/buckets/${cluster}/${label}/properties`
);
cy.wait([
'@getFeatureFlags',
'@getAccount',
'@getObjectStorageEndpoints',
'@getBucketsForRegion',
]);

cy.findByText('Bucket Rate Limits').should('be.visible');
// confirms helper text
cy.contains(
'This endpoint type supports up to 750 Requests Per Second (RPS). Understand bucket rate limits'
).should('be.visible');

// confirm bucket rate limit table should not exist
cy.get('[data-testid="bucket-rate-limit-table"]').should('not.exist');

// confirm 'Save' button is disabled (for now)
ui.button
.findByAttribute('label', 'Save')
.should('be.visible')
.should('be.disabled');
});
});

['E2', 'E3'].forEach((endpoint: ObjectStorageEndpointTypes) => {
/**
* Parameterized test for buckets with endpoint types of E2 and E3
* - Confirms the Properties tab is visible
* - Confirms bucket rates limit table exists
*/
it(`confirms the Properties tab and rate limits table for buckets with endpoint type ${endpoint}`, () => {
const { mockBucket, mockEndpoint } = createMocksBasedOnEndpointType(
endpoint
);
const { cluster, label } = mockBucket;

mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as(
'getBucketsForRegion'
);
mockGetObjectStorageEndpoints([mockEndpoint]).as(
'getObjectStorageEndpoints'
);

cy.visitWithLogin(
`/object-storage/buckets/${cluster}/${label}/properties`
);
cy.wait([
'@getFeatureFlags',
'@getAccount',
'@getObjectStorageEndpoints',
'@getBucketsForRegion',
]);

cy.findByText('Bucket Rate Limits');
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');
// Confirm bucket rate limits table exists with correct values
checkRateLimitsTable(endpoint);

// confirm 'Save' button is disabled (for now)
ui.button
.findByAttribute('label', 'Save')
.should('be.visible')
.should('be.disabled');
});
});
});
});
33 changes: 33 additions & 0 deletions packages/manager/cypress/support/util/object-storage-gen2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { ObjectStorageEndpointTypes } from '@linode/api-v4';

export const checkRateLimitsTable = (
endpointType: ObjectStorageEndpointTypes
) => {
const expectedHeaders = ['Limits', 'GET', 'PUT', 'LIST', 'DELETE', 'OTHER'];
const expectedBasicValues = ['Basic', '2,000', '500', '100', '200', '400'];
const expectedHighValues =
endpointType === 'E3'
? ['High', '20,000', '2,000', '400', '400', '1,000']
: ['High', '5,000', '1,000', '200', '200', '800'];

cy.get('[data-testid="bucket-rate-limit-table"]').within(() => {
expectedHeaders.forEach((header, index) => {
cy.get('th').eq(index).should('contain.text', header);
});

cy.contains('tr', 'Basic').within(() => {
expectedBasicValues.forEach((value, index) => {
cy.get('td').eq(index).should('contain.text', value);
});
});

cy.contains('tr', 'High').within(() => {
expectedHighValues.forEach((value, index) => {
cy.get('td').eq(index).should('contain.text', value);
});
});

// Check that Basic radio button is checked
cy.findByLabelText('Basic').should('be.checked');
});
};
6 changes: 4 additions & 2 deletions packages/validation/src/vpcs.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ export const createSubnetSchema = object().shape(
{
label: labelValidation.required(LABEL_REQUIRED),
ipv4: string().when('ipv6', {
is: (value: unknown) => value === '' || value === null || value === undefined,
is: (value: unknown) =>
Copy link
Contributor Author

@coliu-akamai coliu-akamai Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?? (hmm lemme see when this file got into the mix)
edit - seems like it happened during a merge - since this is just eslint changes, I'll keep this file as is

value === '' || value === null || value === undefined,
then: string()
.required(IP_EITHER_BOTH_NOT_NEITHER)
.test({
Expand Down Expand Up @@ -163,7 +164,8 @@ export const createSubnetSchema = object().shape(
}),
}),
ipv6: string().when('ipv4', {
is: (value: unknown) => value === '' || value === null || value === undefined,
is: (value: unknown) =>
value === '' || value === null || value === undefined,
then: string()
.required(IP_EITHER_BOTH_NOT_NEITHER)
.test({
Expand Down