Skip to content

Commit 39f6463

Browse files
Feature/mpt 18301 add cloud account alert tests (#364)
* Add cloud-accounts page mocks and update e2e tests Add a comprehensive cloud-accounts-page.mocks.ts providing GraphQL mock responses (organizations, allowed actions, current employee, data sources, organization features/theme/perspectives, pools, marketplace data, etc.) and update e2e test pages and specs to use the new mocks. Adjusted base-page, cloud-accounts-page/connect pages, recommendations-page, and cloud-accounts tests, plus updated expected screenshots/PDF fixtures to match the mocked output. These changes stabilize and align end-to-end tests with deterministic mock data. * Remove commented privacy-policy steps Delete commented-out test.step blocks that accepted the privacy policy in e2etests/tests/invitation-flow-tests.spec.ts. Cleans up leftover/dead code in the invitation flow tests by removing two redundant commented sections. * Add billing reimport UI and test Add billing reimport locators and actions to CloudAccountsPage (billingReimportBtn, billingReimportSideModal, billingReimportAlert, scheduleImportBtn, importDatePickerInput, datePopup, dateSetBtn) and implement clickBillingReimportBtn and scheduleImportWithDefaultDate (opens date picker, confirms default date, clicks schedule and returns selected date). Add E2E test that opens the reimport side modal, verifies the warning alert message, schedules a billing reimport using the default date, and asserts the UpdateDataSource POST response is 200. Includes debug logs for the selected date and API response status. * Update expected-data-expenses-chart-export.png
1 parent d497dce commit 39f6463

22 files changed

+1554
-46
lines changed

e2etests/mocks/cloud-accounts-page.mocks.ts

Lines changed: 1303 additions & 0 deletions
Large diffs are not rendered by default.

e2etests/pages/base-page.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ export abstract class BasePage {
398398
* @param {number} [timeout=10000] - The maximum time to wait for the loading image to disappear, in milliseconds.
399399
* @returns {Promise<void>} A promise that resolves when the loading image is no longer visible or exits early if the image is not present.
400400
*/
401-
async waitForLoadingPageImgToDisappear(timeout: number = 10000): Promise<void> {
401+
async waitForLoadingPageImgToDisappear(timeout: number = 20000): Promise<void> {
402402
try {
403403
await this.loadingPageImg.first().waitFor({ timeout: 1000 });
404404
} catch (_error) {
@@ -422,7 +422,7 @@ export abstract class BasePage {
422422
* @param {number} [timeout=10000] - The maximum time to wait for the initialisation message to disappear, in milliseconds.
423423
* @returns {Promise<void>} A promise that resolves when the initialisation message is no longer visible or exits early if the message is not present.
424424
*/
425-
async waitForInitialisationToComplete(timeout: number = 10000): Promise<void> {
425+
async waitForInitialisationToComplete(timeout: number = 20000): Promise<void> {
426426
try {
427427
await this.initialisationMessage.first().waitFor({ timeout: 1000 });
428428
} catch (_error) {

e2etests/pages/cloud-accounts-connect-page.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export class CloudAccountsConnectPage extends BasePage {
3737
readonly exportNameInput: Locator;
3838
readonly exportAmazonS3BucketNameInput: Locator;
3939
readonly exportPathPrefixInput: Locator;
40+
readonly alertMessage: Locator;
4041
//#endregion
4142

4243
//#region Azure specific
@@ -54,6 +55,7 @@ export class CloudAccountsConnectPage extends BasePage {
5455

5556
//#endregion
5657

58+
5759
/**
5860
* Initializes a new instance of the CloudAccountsConnectPage class.
5961
* @param {Page} page - The Playwright page object.
@@ -84,6 +86,7 @@ export class CloudAccountsConnectPage extends BasePage {
8486
this.exportNameInput = this.main.getByTestId('input_export_name');
8587
this.exportAmazonS3BucketNameInput = this.main.getByTestId('input_s3_bucket_name');
8688
this.exportPathPrefixInput = this.main.getByTestId('input_export_path_prefix');
89+
this.alertMessage = this.main.getByRole("alert");
8790
this.connectBtn = this.main.getByTestId('btn_connect_cloud_account');
8891
this.cancelBtn = this.main.getByTestId('btn_cancel_cloud_account');
8992
this.directoryTenantIDInput = this.main.getByTestId('input_tenant_id');
@@ -158,6 +161,10 @@ export class CloudAccountsConnectPage extends BasePage {
158161
await this.googleCloudBtn.click();
159162
}
160163

164+
async clickAccessKey(): Promise<void> {
165+
await this.btnAccessKey.click();
166+
}
167+
161168
/**
162169
* Adds an AWS Assumed Role account by filling in the required details and connecting it.
163170
*

e2etests/pages/cloud-accounts-page.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ export class CloudAccountsPage extends BasePage {
1818
readonly table: Locator;
1919
readonly allCloudAccountLinks: Locator;
2020

21+
readonly updateSideModal: Locator;
22+
readonly sideModalAccessKeyButton: Locator;
23+
readonly sideModalAssumedRoleButton: Locator;
24+
readonly sideModalPrimaryAlert: Locator;
25+
readonly sideModalSecondaryAlert: Locator;
26+
readonly updateCredentialsBtn: Locator;
27+
28+
readonly billingReimportBtn: Locator;
29+
readonly billingReimportSideModal: Locator;
30+
readonly billingReimportAlert: Locator;
31+
readonly scheduleImportBtn: Locator;
32+
readonly importDatePickerInput: Locator;
33+
private datePopup: Locator;
34+
readonly dateSetBtn: Locator;
35+
36+
2137
/**
2238
* Initializes a new instance of the CloudAccountsPage class.
2339
* @param {Page} page - The Playwright page object.
@@ -34,6 +50,20 @@ export class CloudAccountsPage extends BasePage {
3450
this.billingStatusCompletedIcon = this.getByAnyTestId('CheckCircleIcon', this.lastBillingImportStatus);
3551
this.addBtn = this.main.getByTestId('btn_add');
3652
this.allCloudAccountLinks = this.table.locator('xpath=(//td//a)');
53+
this.updateSideModal = this.page.getByTestId('smodal_update_data_source_credentials');
54+
this.sideModalAccessKeyButton = this.updateSideModal.getByTestId('btn_accessKey');
55+
this.sideModalAssumedRoleButton = this.updateSideModal.getByTestId('btn_assumedRole');
56+
this.sideModalPrimaryAlert = this.updateSideModal.locator('//div[@role="alert"]').first();
57+
this.sideModalSecondaryAlert = this.updateSideModal.locator('//div[@role="alert"]').last();
58+
this.updateCredentialsBtn = this.main.getByTestId('btn_update_data_source_credentials_modal');
59+
this.billingReimportBtn = this.main.getByTestId('btn_expenses_reimport_data_source_modal');
60+
this.billingReimportSideModal = this.page.getByTestId('smodal_reimport_data_source_expenses');
61+
this.billingReimportAlert = this.billingReimportSideModal.locator('//div[@role="alert"]');
62+
this.scheduleImportBtn = this.billingReimportSideModal.getByTestId('btn_confirm');
63+
this.importDatePickerInput = this.billingReimportSideModal.getByTestId('input_importFrom');
64+
this.datePopup = this.page.locator('//div[@id="simple-popover"]');
65+
this.dateSetBtn = this.datePopup.getByRole('button', { name: 'Set' });
66+
3767
}
3868

3969
/**
@@ -44,6 +74,45 @@ export class CloudAccountsPage extends BasePage {
4474
await this.addBtn.click();
4575
}
4676

77+
/**
78+
* Clicks the "Update Credentials" button to open the update credentials modal.
79+
* This method is typically used to initiate the process of updating
80+
* cloud account credentials (e.g., AWS access keys or assumed roles).
81+
* @returns {Promise<void>} A promise that resolves when the button is clicked.
82+
*/
83+
async clickUpdateCredentialsBtn(): Promise<void> {
84+
await this.updateCredentialsBtn.click();
85+
}
86+
87+
/**
88+
* Clicks the "Billing Reimport" button to open the billing reimport modal.
89+
* This method is used to initiate the process of re-importing billing data
90+
* for a cloud account from a specified date.
91+
* @returns {Promise<void>} A promise that resolves when the button is clicked.
92+
*/
93+
async clickBillingReimportBtn(): Promise<void> {
94+
await this.billingReimportBtn.click();
95+
}
96+
97+
/**
98+
* Schedules a billing data re-import using the default date in the date picker.
99+
* This method performs the following steps:
100+
* 1. Opens the date picker by clicking the import date input field
101+
* 2. Confirms the default date by clicking the "Set" button
102+
* 3. Initiates the import by clicking the "Schedule Import" button
103+
* 4. Logs the scheduled date for debugging purposes
104+
*
105+
* @returns {Promise<string>} A promise that resolves with the text content of the selected date.
106+
* @throws {Error} If the date picker input or buttons are not accessible.
107+
*/
108+
async scheduleImportWithDefaultDate(): Promise<string> {
109+
await this.importDatePickerInput.click();
110+
await this.dateSetBtn.click();
111+
await this.scheduleImportBtn.click();
112+
debugLog(`Scheduled billing re-import with default date: ${await this.importDatePickerInput.textContent()}`);
113+
return await this.importDatePickerInput.textContent();
114+
}
115+
47116
/**
48117
* Clicks the "Advanced" tab button on the Cloud Accounts page.
49118
* @returns {Promise<void>} A promise that resolves when the action is complete.
@@ -63,7 +132,6 @@ export class CloudAccountsPage extends BasePage {
63132
return locator.click();
64133
}
65134

66-
67135
/**
68136
* Retrieves a cloud account link by its name.
69137
*

e2etests/pages/recommendations-page.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ export class RecommendationsPage extends BasePage {
523523
{ label: 'Obsolete Snapshot Chains', locator: this.obsoleteSnapshotChainsCardSavingsValue },
524524
{ label: 'Reserved Instances Opportunities', locator: this.reservedInstancesOpportunitiesCardSavingsValue },
525525
{ label: 'Public S3 Buckets', locator: this.publicS3BucketsCardSavingsValue },
526-
{ label: 'Snapshots With Non-used Images', locator: this.snapshotsWithNonUsedImagesCardSavingsValue},
526+
{ label: 'Snapshots With Non-used Images', locator: this.snapshotsWithNonUsedImagesCardSavingsValue },
527527
{ label: 'Underutilized Instances', locator: this.underutilizedInstancesCardSavingsValue },
528528
{ label: 'Underutilized RDS Instances', locator: this.underutilizedRDSInstancesCardSavingsValue },
529529
];
@@ -671,6 +671,16 @@ export class RecommendationsPage extends BasePage {
671671
return totalSum;
672672
}
673673

674+
/**
675+
* Retrieves the numeric count value from a card element.
676+
*
677+
* This method extracts the text content from the provided card locator
678+
* and parses it as an integer. It is typically used to get count values
679+
* displayed on recommendation cards (e.g., number of resources affected).
680+
*
681+
* @param {Locator} cardLocator - The locator for the card element containing the count value.
682+
* @returns {Promise<number>} The parsed count value as an integer.
683+
*/
674684
async getCardCountValue(cardLocator: Locator): Promise<number> {
675685
const text = await cardLocator.textContent();
676686
return parseInt(text, 10);

0 commit comments

Comments
 (0)