From 13436613d6a91bb2e443cdcdd28503c9635ef607 Mon Sep 17 00:00:00 2001 From: StylusFrost Date: Mon, 20 Oct 2025 14:53:43 +0200 Subject: [PATCH] test(ui): add M365 provider management E2E tests - Introduced new E2E tests for adding Microsoft 365 providers with static credentials. - Updated the ProvidersPage interface to include M365-specific fields and methods. - Enhanced the test suite to validate the complete flow of adding a new M365 provider, ensuring proper handling of credentials and provider details. - Added necessary environment variable checks and cleanup steps to maintain test integrity. --- .github/workflows/ui-e2e-tests.yml | 4 ++ ui/tests/providers/providers-page.ts | 87 +++++++++++++++++++++++---- ui/tests/providers/providers.md | 52 ++++++++++++++++ ui/tests/providers/providers.spec.ts | 90 +++++++++++++++++++++++++++- 4 files changed, 219 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ui-e2e-tests.yml b/.github/workflows/ui-e2e-tests.yml index 19ba25d69e..dfa58341b7 100644 --- a/.github/workflows/ui-e2e-tests.yml +++ b/.github/workflows/ui-e2e-tests.yml @@ -28,6 +28,10 @@ jobs: E2E_AZURE_CLIENT_ID: ${{ secrets.E2E_AZURE_CLIENT_ID }} E2E_AZURE_SECRET_ID: ${{ secrets.E2E_AZURE_SECRET_ID }} E2E_AZURE_TENANT_ID: ${{ secrets.E2E_AZURE_TENANT_ID }} + E2E_M365_DOMAIN_ID: ${{ secrets.E2E_M365_DOMAIN_ID }} + E2E_M365_CLIENT_ID: ${{ secrets.E2E_M365_CLIENT_ID }} + E2E_M365_SECRET_ID: ${{ secrets.E2E_M365_SECRET_ID }} + E2E_M365_TENANT_ID: ${{ secrets.E2E_M365_TENANT_ID }} steps: - name: Checkout repository diff --git a/ui/tests/providers/providers-page.ts b/ui/tests/providers/providers-page.ts index 9e03677f8b..f395cf5eda 100644 --- a/ui/tests/providers/providers-page.ts +++ b/ui/tests/providers/providers-page.ts @@ -13,6 +13,12 @@ export interface AZUREProviderData { alias?: string; } +// M365 provider data +export interface M365ProviderData { + domainId: string; + alias?: string; +} + // AWS credential options export const AWS_CREDENTIAL_OPTIONS = { AWS_ROLE_ARN: "role", @@ -47,6 +53,22 @@ export interface AZUREProviderCredential { tenantId:string; } +// M365 credential options +export const M365_CREDENTIAL_OPTIONS = { + M365_CREDENTIALS: "credentials" +} as const; + +// M365 credential type +type M365CredentialType = (typeof M365_CREDENTIAL_OPTIONS)[keyof typeof M365_CREDENTIAL_OPTIONS]; + +// M365 provider credential +export interface M365ProviderCredential { + type: M365CredentialType; + clientId:string; + clientSecret:string; + tenantId:string; +} + // Providers page export class ProvidersPage extends BasePage { @@ -84,10 +106,16 @@ export class ProvidersPage extends BasePage { readonly secretAccessKeyInput: Locator; // AZURE provider form elements - readonly subscriptionIdInput: Locator; - readonly clientIdInput: Locator; - readonly clientSecretInput: Locator; - readonly tenantIdInput: Locator; + readonly azureSubscriptionIdInput: Locator; + readonly azureClientIdInput: Locator; + readonly azureClientSecretInput: Locator; + readonly azureTenantIdInput: Locator; + + // M365 provider form elements + readonly m365domainIdInput: Locator; + readonly m365ClientIdInput: Locator; + readonly m365ClientSecretInput: Locator; + readonly m365TenantIdInput: Locator; // Delete button readonly deleteProviderConfirmationButton: Locator; @@ -125,10 +153,16 @@ export class ProvidersPage extends BasePage { this.accountIdInput = page.getByLabel("Account ID"); // AZURE provider form inputs - this.subscriptionIdInput = page.getByLabel("Subscription ID"); - this.clientIdInput = page.getByLabel("Client ID"); - this.clientSecretInput = page.getByLabel("Client Secret"); - this.tenantIdInput = page.getByLabel("Tenant ID"); + this.azureSubscriptionIdInput = page.getByLabel("Subscription ID"); + this.azureClientIdInput = page.getByLabel("Client ID"); + this.azureClientSecretInput = page.getByLabel("Client Secret"); + this.azureTenantIdInput = page.getByLabel("Tenant ID"); + + // M365 provider form inputs + this.m365domainIdInput = page.getByLabel("Domain ID"); + this.m365ClientIdInput = page.getByLabel("Client ID"); + this.m365ClientSecretInput = page.getByLabel("Client Secret"); + this.m365TenantIdInput = page.getByLabel("Tenant ID"); // Alias input this.aliasInput = page.getByLabel("Provider alias (optional)"); @@ -197,6 +231,12 @@ export class ProvidersPage extends BasePage { await this.waitForPageLoad(); } + async selectM365Provider(): Promise { + // Select the M365 provider + + await this.m365ProviderRadio.click({ force: true }); + await this.waitForPageLoad(); + } async fillAWSProviderDetails(data: AWSProviderData): Promise { // Fill the AWS provider details @@ -211,7 +251,17 @@ export class ProvidersPage extends BasePage { async fillAZUREProviderDetails(data: AZUREProviderData): Promise { // Fill the AWS provider details - await this.subscriptionIdInput.fill(data.subscriptionId); + await this.azureSubscriptionIdInput.fill(data.subscriptionId); + + if (data.alias) { + await this.aliasInput.fill(data.alias); + } + } + + async fillM365ProviderDetails(data: M365ProviderData): Promise { + // Fill the M365 provider details + + await this.m365domainIdInput.fill(data.domainId); if (data.alias) { await this.aliasInput.fill(data.alias); @@ -338,16 +388,29 @@ export class ProvidersPage extends BasePage { // Fill the azure credentials form if (credentials.clientId) { - await this.clientIdInput.fill(credentials.clientId); + await this.azureClientIdInput.fill(credentials.clientId); } if (credentials.clientSecret) { - await this.clientSecretInput.fill(credentials.clientSecret); + await this.azureClientSecretInput.fill(credentials.clientSecret); } if (credentials.tenantId) { - await this.tenantIdInput.fill(credentials.tenantId); + await this.azureTenantIdInput.fill(credentials.tenantId); } } + async fillM365Credentials(credentials: M365ProviderCredential): Promise { + // Fill the m365 credentials form + + if (credentials.clientId) { + await this.m365ClientIdInput.fill(credentials.clientId); + } + if (credentials.clientSecret) { + await this.m365ClientSecretInput.fill(credentials.clientSecret); + } + if (credentials.tenantId) { + await this.m365TenantIdInput.fill(credentials.tenantId); + } + } async verifyPageLoaded(): Promise { // Verify the providers page is loaded diff --git a/ui/tests/providers/providers.md b/ui/tests/providers/providers.md index 675ee167bb..2acb6305db 100644 --- a/ui/tests/providers/providers.md +++ b/ui/tests/providers/providers.md @@ -159,3 +159,55 @@ - Provider cleanup performed before each test to ensure clean state - Requires valid Azure subscription with appropriate permissions - Client credentials must have sufficient permissions for security scanning + +--- + +## Test Case: `PROVIDER-E2E-004` - Add M365 Provider with Static Credentials + +**Priority:** `critical` + +**Tags:** + +- type → @e2e, @serial +- feature → @providers +- provider → @m365 + +**Description/Objective:** Validates the complete flow of adding a new Microsoft 365 provider using static client credentials (Client ID, Client Secret, Tenant ID) tied to a Domain ID. + +**Preconditions:** + +- Admin user authentication required (admin.auth.setup setup) +- Environment variables configured: E2E_M365_DOMAIN_ID, E2E_M365_CLIENT_ID, E2E_M365_SECRET_ID, E2E_M365_TENANT_ID +- Remove any existing provider with the same Domain ID before starting the test +- This test must be run serially and never in parallel with other tests, as it requires the Domain ID not to be already registered beforehand. + +### Flow Steps: + +1. Navigate to providers page +2. Click "Add Provider" button +3. Select M365 provider type +4. Fill provider details (domain ID and alias) +5. Fill M365 credentials (client ID, client secret, tenant ID) +6. Launch initial scan +7. Verify redirect to provider management page + +### Expected Result: + +- M365 provider successfully added with static credentials +- Initial scan launched successfully +- User redirected to provider details page + +### Key verification points: + +- Provider page loads correctly +- Connect account page displays M365 option +- M365 credentials form accepts all required fields +- Launch scan page appears +- Successful redirect to provider page after scan launch + +### Notes: + +- Test uses environment variables for M365 credentials +- Provider cleanup performed before each test to ensure clean state +- Requires valid Microsoft 365 tenant with appropriate permissions +- Client credentials must have sufficient permissions for security scanning diff --git a/ui/tests/providers/providers.spec.ts b/ui/tests/providers/providers.spec.ts index 5b0e5e1cf7..39878e53b4 100644 --- a/ui/tests/providers/providers.spec.ts +++ b/ui/tests/providers/providers.spec.ts @@ -7,7 +7,10 @@ import { AWS_CREDENTIAL_OPTIONS, AZUREProviderData, AZUREProviderCredential, - AZURE_CREDENTIAL_OPTIONS + AZURE_CREDENTIAL_OPTIONS, + M365ProviderData, + M365ProviderCredential, + M365_CREDENTIAL_OPTIONS } from "./providers-page"; @@ -238,4 +241,87 @@ test.describe.serial("Add AZURE Provider", () => { await providersPage.verifyLoadProviderPageAfterNewProvider(); } ) -}); \ No newline at end of file +}); + + +test.describe.serial("Add M365 Provider", () => { + + // Providers page object + let providersPage: ProvidersPage; + + // Test data from environment variables + const domainId= process.env.E2E_M365_DOMAIN_ID; + const clientId= process.env.E2E_M365_CLIENT_ID + const clientSecret= process.env.E2E_M365_SECRET_ID + const tenantId= process.env.E2E_M365_TENANT_ID + + // Validate required environment variables + if (!domainId || !clientId || !clientSecret || !tenantId) { + throw new Error( + "E2E_M365_DOMAIN_ID, E2E_M365_CLIENT_ID, E2E_M365_SECRET_ID, and E2E_M365_TENANT_ID environment variables are not set", + ); + } + + // Setup before each test + test.beforeEach(async ({ page }) => { + providersPage = new ProvidersPage(page); + // Clean up existing provider to ensure clean test state + await helpers.deleteProviderIfExists(page, domainId); + }); + + // Use admin authentication for provider management + test.use({ storageState: "playwright/.auth/admin_user.json" }); + + + test( + "should add a new M365 provider with static credentials", + { + tag: ["@critical", "@e2e", "@providers", "@m365", "@serial", "@PROVIDER-E2E-004"], + }, + async ({ page }) => { + + // Prepare test data for M365 provider + const m365ProviderData: M365ProviderData = { + domainId:domainId, + alias: "Test E2E M365 Account - Credentials", + }; + + // Prepare static credentials + const m365Credentials: M365ProviderCredential = { + type: M365_CREDENTIAL_OPTIONS.M365_CREDENTIALS, + clientId: clientId, + clientSecret: clientSecret, + tenantId: tenantId, + }; + + // Navigate to providers page + await providersPage.goto(); + await providersPage.verifyPageLoaded(); + + // Start adding new provider + await providersPage.clickAddProvider(); + await providersPage.verifyConnectAccountPageLoaded(); + + // Select M365 provider + await providersPage.selectM365Provider(); + + // Fill provider details + await providersPage.fillM365ProviderDetails(m365ProviderData); + await providersPage.clickNext(); + + // Fill static credentials details + await providersPage.fillM365Credentials(m365Credentials); + await providersPage.clickNext(); + + // Launch scan + await providersPage.verifyLaunchScanPageLoaded(); + await providersPage.clickNext(); + + // Wait for redirect to provider page + await providersPage.verifyLoadProviderPageAfterNewProvider(); + } + ) + + +}); +