### Install Project Dependencies Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CONTRIBUTING.md Install Rush globally and then install all project dependencies using Rush. ```bash npm install -g @microsoft/rush rush install ``` -------------------------------- ### Clone Repository and Install Dependencies Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Steps to clone the repository, install Rush globally, install all package dependencies, build packages, and install Playwright browsers. ```bash git clone https://github.com/microsoft/power-platform-playwright-samples.git cd power-platform-playwright-samples npm install -g @microsoft/rush rush install rush build cd packages/e2e-tests npx playwright install msedge --with-deps ``` -------------------------------- ### Providing Usage Examples with @example Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Demonstrates how to use the @example tag to provide clear usage examples for a function, including variations with different options. ```typescript /** * Click a Canvas control * * @example Basic usage * ```typescript * await canvas.clickControl({ name: 'Submit Button' }); * ``` * * @example With specific control type * ```typescript * await canvas.clickControl({ * name: 'Submit', * type: CanvasControlType.Button, * timeout: 5000 * }); * ``` * * @example With exact matching * ```typescript * await canvas.clickControl({ name: 'Submit', exact: true }); * ``` */ async clickControl(options: ControlOptions): Promise { // Implementation } ``` -------------------------------- ### Start Development Server for Docs Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Navigate to the docs package and start the development server to view documentation locally. Open the provided URL in your browser. ```bash # Start development server cd packages/docs npm run dev # Open http://localhost:3000 # Navigate to Reference > API ``` -------------------------------- ### Clone Repository and Install Dependencies Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/README.md Steps to clone the repository, install Rush (monorepo manager), and install project dependencies. ```bash git clone https://github.com/microsoft/power-platform-playwright-samples.git cd power-platform-playwright-samples # Install Rush (monorepo manager) npm install -g @microsoft/rush # Install dependencies rush install # Build all packages rush build ``` -------------------------------- ### Copy and Configure Environment Variables Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/README.md Instructions to copy the example environment file and set up necessary Power Platform configuration variables. ```bash cd packages/e2e-tests cp .env.example .env ``` ```bash # ----------------------------------------------------------------------- # Power Apps / Maker Portal # ----------------------------------------------------------------------- # Base URL of the Maker Portal (leave as-is unless using a preview URL) POWER_APPS_BASE_URL=https://make.powerapps.com # Your environment GUID — find it in the Maker Portal URL: # make.powerapps.com/environments//... POWER_APPS_ENVIRONMENT_ID=Default-00000000-0000-0000-0000-000000000000 # ----------------------------------------------------------------------- # Model-Driven App # ----------------------------------------------------------------------- # Full URL of your MDA including the ?appid= parameter. # How to find: open your app in the browser and copy the URL. MODEL_DRIVEN_APP_URL=https://your-org.crm.dynamics.com/main.aspx?appid=00000000-0000-0000-0000-000000000000 # ----------------------------------------------------------------------- # Canvas App # ----------------------------------------------------------------------- # Option A — component IDs (toolkit builds the play URL automatically): # App ID: Maker Portal → select app → Details → App ID # Tenant ID: Azure Portal → Azure Active Directory → Overview → Tenant ID CANVAS_APP_ID=00000000-0000-0000-0000-000000000000 CANVAS_APP_TENANT_ID=00000000-0000-0000-0000-000000000000 # Option B — full play URL (takes precedence over IDs above if set): # CANVAS_APP_URL=https://apps.powerapps.com/play/e//a/?tenantId= ``` -------------------------------- ### Install and Build Commands Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Common rush commands for installing dependencies and building packages within the project. Use `rush install` for all dependencies or `rush build` for all packages. ```bash # Install / build rush install # Install all dependencies rush build # Build all packages rush build --to power-platform-playwright-toolkit # Build toolkit only ``` -------------------------------- ### Install and Build Monorepo Packages with Rush Source: https://context7.com/microsoft/power-platform-playwright-samples/llms.txt Installs dependencies and builds all packages in the monorepo using Rush. Configure environment variables by copying and editing the .env.example file. ```bash git clone https://github.com/microsoft/power-platform-playwright-samples.git cd power-platform-playwright-samples npm install -g @microsoft/rush rush install rush build cd packages/e2e-tests cp .env.example .env # Edit .env with your values: # POWER_APPS_BASE_URL=https://make.powerapps.com # POWER_APPS_ENVIRONMENT_ID=Default-00000000-0000-0000-0000-000000000000 # MODEL_DRIVEN_APP_URL=https://your-org.crm.dynamics.com/main.aspx?appid= # CANVAS_APP_ID=00000000-0000-0000-0000-000000000000 # CANVAS_APP_TENANT_ID=00000000-0000-0000-0000-000000000000 # MS_AUTH_EMAIL=user@contoso.com # MS_AUTH_CREDENTIAL_TYPE=password # MS_USER_PASSWORD=your-password-here # HEADLESS=true # WORKERS=1 # TEST_TIMEOUT=120000 # Authenticate (run once; re-run only when session expires) npm run auth:headful # Maker Portal (Canvas + Gen UX tests) npm run auth:mda:headful # Model-Driven App domain (MDA tests) # Run tests npx playwright test --project=model-driven-app npx playwright test --project=canvas-app npx playwright test --project=gen-ux npx playwright test --project=default ``` -------------------------------- ### Install Dependencies Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/README.md Install project dependencies using rush or npm. Rush is recommended for monorepos. ```bash rush install rush build ``` ```bash npm install ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Copy the example environment file and update the necessary Power Apps, Model-Driven App, Canvas App, and Microsoft Authentication variables for your specific environment. ```bash cd packages/e2e-tests cp .env.example .env ``` -------------------------------- ### Install Power Platform Playwright Toolkit Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/README.md Install the toolkit and Playwright test runner using npm. For accessibility testing, also install the Axe core Playwright integration. ```bash npm install power-platform-playwright-toolkit @playwright/test ``` ```bash npm install -D @axe-core/playwright ``` -------------------------------- ### Example: Well-Documented CanvasAppHelper Class Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Demonstrates JSDoc comments for a CanvasAppHelper class, including a class description, usage examples, and method documentation with parameters, return values, and exceptions. ```typescript /** * Canvas App Helper * * Provides methods for testing Canvas apps in Power Platform. * Handles app launching, control interaction, and assertions. * * @example Basic usage * ```typescript * const powerAppsPage = new PowerAppsPage(page); * await powerAppsPage.canvas.launchCanvasAppByName('My App'); * await powerAppsPage.canvas.clickControl({ name: 'Submit' }); * ``` * * @category Canvas Apps */ export class CanvasAppHelper { /** * Launch Canvas app by name * * Finds the app in the Apps list, clicks it, and waits for it to load. * Supports Play, Edit, and Preview modes. * * @param appName - Name of the Canvas app * @param findAppCallback - Callback to find the app (usually PowerAppsPage.findApp) * @param mode - Launch mode (default: Play) * @param options - Additional launch options * @param options.waitForReady - Wait for app to be ready (default: true) * @param options.timeout - Max wait time in ms (default: 30000) * * @returns Promise that resolves when app is loaded * * @throws {Error} If app is not found * @throws {Error} If app fails to load within timeout * * @example Launch in play mode * ```typescript * await canvas.launchCanvasAppByName('My App', findApp); * ``` * * @example Launch in edit mode * ```typescript * await canvas.launchCanvasAppByName( * 'My App', * findApp, * AppLaunchMode.Edit * ); * ``` * * @see {@link launchCanvasAppById} for launching by app ID * @category Canvas Apps */ async launchCanvasAppByName( appName: string, findAppCallback: (appName: string) => Promise, mode: AppLaunchMode = AppLaunchMode.Play, options: AppPlayerOptions = {} ): Promise { // Implementation } } ``` -------------------------------- ### Document Public APIs with JSDoc Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Document all exported functions, classes, methods, and properties using JSDoc comments. This example shows documentation for a class constructor. ```typescript /** * Helper class for Canvas App specific operations * * Handles launching, interacting with, and testing Canvas apps. * Use via PowerAppsPage.canvas or instantiate directly. */ export class CanvasAppHelper { /** * Creates a new CanvasAppHelper instance * * @param page - Playwright page object */ constructor(page: Page) { this.page = page; } } ``` -------------------------------- ### Create a Feature Branch Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CONTRIBUTING.md Before making changes, create a new branch for your feature starting from the 'main' branch. ```bash git checkout -b feat/my-feature ``` -------------------------------- ### CanvasAppHelper Class (Markdown Description) Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Provides a detailed description of the CanvasAppHelper class, including its features and usage examples. ```APIDOC ## Class CanvasAppHelper ### Description Canvas App Helper ## Features - Launch apps by name or ID - Interact with controls (buttons, inputs, etc.) - Work with galleries and forms - Assert control visibility and text ## Usage Access via `PowerAppsPage.canvas` or create directly: ```typescript const canvas = new CanvasAppHelper(page); await canvas.launchCanvasAppByName('My App'); ``` @see {@link PowerAppsPage} ``` -------------------------------- ### Document Async Behavior in JSDoc Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Explain the asynchronous behavior of methods, including what the method waits for and what it returns. This example details the steps involved in waiting for an app to be ready. ```typescript /** * Wait for Canvas app to be ready * * This method waits for: * 1. The app container to be visible * 2. Loading spinners to disappear * 3. A 2-second settle period * * @param timeout - Maximum time to wait in milliseconds (default: 30000) * @returns Promise that resolves when the app is ready */ private async waitForCanvasAppReady(timeout: number = 30000): Promise {} ``` -------------------------------- ### Include Type Information in JSDoc Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Provide context for TypeScript types using JSDoc tags. This example documents an interface with properties and their descriptions. ```typescript /** * Control options for locating Canvas controls * * @property name - Name or label of the control (e.g., "Submit Button") * @property type - Optional control type for more specific matching * @property timeout - Max wait time in milliseconds (default: 10000) * @property exact - Whether to match the name exactly (default: false) */ export interface ControlOptions { name: string; type?: CanvasControlType; timeout?: number; exact?: boolean; } ``` -------------------------------- ### Test a Canvas App with Playwright Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/README.md Launch and interact with a Canvas App using the AppProvider and CanvasAppPage. This example demonstrates launching the app, waiting for it to load, and interacting with specific controls. ```typescript import { test } from '@playwright/test'; import { AppProvider } from 'power-platform-playwright-toolkit'; test('canvas app test', async ({ page }) => { const appProvider = new AppProvider(page); // Launch Canvas App const canvasApp = await appProvider.launchApp({ appUrl: 'https://apps.powerapps.com/play/...', appType: 'canvas', }); await canvasApp.waitForAppToLoad(); // Interact with controls await canvasApp.clickControl('ButtonSubmit'); await canvasApp.fillTextInput('TextInputName', 'John Doe'); const result = await canvasApp.getControlText('LabelResult'); expect(result).toContain('Success'); }); ``` -------------------------------- ### Basic JSDoc Comment Structure Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Demonstrates the fundamental structure of a JSDoc comment, including a brief description, detailed explanation, parameter documentation, return value description, and an example. ```typescript /** * Brief one-line description * * Detailed description with multiple paragraphs if needed. * Can include additional context, behavior notes, etc. * * @param paramName - Parameter description * @returns Description of return value * * @example * ```typescript * // Example usage * const result = await myFunction('example'); * ``` */ ``` -------------------------------- ### Document Default Values in JSDoc Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Clearly document default values for parameters in JSDoc comments. This example shows default values for launch mode, readiness wait time, and timeout. ```typescript /** * Launch Canvas app * * @param mode - Launch mode (default: AppLaunchMode.Play) * @param options - Player options * @param options.waitForReady - Wait for app to be ready (default: true) * @param options.timeout - Max wait time in ms (default: 30000) */ async launchCanvasApp( mode: AppLaunchMode = AppLaunchMode.Play, options: AppPlayerOptions = {} ): Promise {} ``` -------------------------------- ### Test a Model-Driven App with Playwright Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/README.md Launch and interact with a Model-Driven App using the AppProvider and ModelDrivenAppPage. This example shows navigating to an entity, creating a new record, and filling form fields. ```typescript import { test } from '@playwright/test'; import { AppProvider } from 'power-platform-playwright-toolkit'; test('model-driven app test', async ({ page }) => { const appProvider = new AppProvider(page); // Launch Model-Driven App const modelApp = await appProvider.launchApp({ appUrl: 'https://yourorg.crm.dynamics.com/வுகளை', appType: 'model-driven', }); // Navigate and create record await modelApp.navigateToEntity('Accounts'); await modelApp.clickNewButton(); await modelApp.fillFormField('name', 'Contoso Ltd'); await modelApp.saveRecord(); }); ``` -------------------------------- ### Set Power Apps Base URL and Environment ID Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Configure the base URL for Power Apps (e.g., make.powerapps.com) and your specific environment's GUID. The environment ID can be found in the Maker Portal URL. ```bash POWER_APPS_BASE_URL=https://make.powerapps.com POWER_APPS_ENVIRONMENT_ID=Default-00000000-0000-0000-0000-000000000000 ``` -------------------------------- ### Generate Local Documentation Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/README.md Run these commands to generate and view the documentation site locally. Ensure you are in the correct package directories. ```bash cd packages/power-platform-playwright-toolkit npm run docs cd packages/docs npm run dev # Visit http://localhost:3000 ``` -------------------------------- ### Build Project with Rush Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CONTRIBUTING.md Build the entire project using the Rush build command. ```bash rush build ``` -------------------------------- ### Build and Publish Documentation Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Commands to build the documentation for GitHub Pages and export it as a static site. Deployment is handled by GitHub Actions. ```bash # Build for GitHub Pages cd packages/docs npm run build:github # Export static site npm run export # Deploy (handled by GitHub Actions) ``` -------------------------------- ### Quick Commands for Documentation Generation Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Provides essential npm commands for generating, watching, and serving API documentation for the toolkit. ```bash # Generate API documentation (from toolkit package) npm run docs # Watch mode - regenerate on file changes npm run docs:watch # Watch with live server npm run docs:serve ``` -------------------------------- ### FormContext API for MDA Attributes Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/mda/README.md Utilize the FormContext API to get and set entity attributes, and save the form. Ensure necessary functions are imported. ```typescript import { getFormContext, getEntityAttribute, setEntityAttribute, saveForm, } from 'power-platform-playwright-toolkit'; const ctx = await getFormContext(page); const value = await getEntityAttribute(page, 'nwind_ordernumber'); await setEntityAttribute(page, 'nwind_ordernumber', 'TEST-001'); await saveForm(page); ``` -------------------------------- ### Build and Development Commands for Docs Package Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Commands to build the documentation site and run it in development mode from the 'packages/docs' directory. ```bash # Build docs site (includes API generation) cd packages/docs npm run build # Development mode npm run dev ``` -------------------------------- ### Interact with Grid Component in MDA Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/mda/README.md Navigate to the grid view, wait for it to load, get the row count, and open a specific record by its row number. ```typescript await app.grid.navigateToGridView(); await app.grid.waitForGridLoad(); const count = await app.grid.getRowCount(); await app.grid.openRecord({ rowNumber: 0 }); ``` -------------------------------- ### Document Enums with JSDoc Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Document enums using JSDoc comments to explain their purpose and the meaning of each member. This example documents control types for Canvas apps. ```typescript /** * Canvas control types * * Used to specify the type of control when locating elements * in Canvas apps. Different control types use different locator strategies. */ export enum CanvasControlType { /** * Button control * Located using role="button" */ Button = 'Button', /** * Text input control * Located using role="textbox" */ TextInput = 'TextInput', /** * Label or text display * Located using text content */ Label = 'Label', } ``` -------------------------------- ### Launch Model-Driven App with AppProvider Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/mda/README.md Initialize and launch the Model-Driven App using the AppProvider, specifying the app name, type, and direct URL. Skip the Maker Portal if needed. ```typescript const appProvider = new AppProvider(page, context); await appProvider.launch({ app: 'Northwind Orders', type: AppType.ModelDriven, directUrl: process.env.MODEL_DRIVEN_APP_URL!, skipMakerPortal: true, }); const app = appProvider.getModelDrivenAppPage(); ``` -------------------------------- ### Perform Accessibility Testing with Playwright Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/README.md Utilize the AccessibilityTestHelper to scan a page for WCAG compliance issues. This example demonstrates scanning a page and asserting that no violations are found. ```typescript import { test } from '@playwright/test'; import { AccessibilityTestHelper, WCAGLevel } from 'power-platform-playwright-toolkit'; test('accessibility test', async ({ page }) => { await page.goto('https://your-app.com'); const a11y = new AccessibilityTestHelper(page); const results = await a11y.scanPage({ wcagLevel: WCAGLevel.AA }); await a11y.assertNoViolations(results); }); ``` -------------------------------- ### Launch Power Platform Apps with AppProvider Source: https://context7.com/microsoft/power-platform-playwright-samples/llms.txt Demonstrates launching various Power Platform app types using the AppProvider class. It supports launching by direct URL, app name through the maker portal, or by app ID. Ensure necessary environment variables are configured. ```typescript import { test, expect } from '@playwright/test'; import { AppProvider, AppType, AppLaunchMode } from 'power-platform-playwright-toolkit'; test('launch MDA by direct URL', async ({ page, context }) => { const provider = new AppProvider(page, context); // Strategy 1: Direct URL — fastest, no maker portal traversal await provider.launch({ app: 'Northwind Orders', type: AppType.ModelDriven, mode: AppLaunchMode.Play, skipMakerPortal: true, directUrl: process.env.MODEL_DRIVEN_APP_URL!, }); // Strategy 2: By app name through maker portal (opens new tab in Play mode) // await provider.launch({ // app: 'My Sales App', // type: AppType.Canvas, // mode: AppLaunchMode.Play, // baseUrl: 'https://make.powerapps.com', // context, // required — Play mode opens a new tab // }); // Strategy 3: By app ID // await provider.launch({ // app: { id: '00000000-0000-0000-0000-000000000000' }, // type: AppType.Canvas, // baseUrl: 'https://make.powerapps.com', // }); console.log('App URL:', provider.getCurrentAppUrl()); console.log('App type:', provider.getCurrentAppType()); // AppType.ModelDriven console.log('Ready:', provider.isReady()); // Generic control interactions (delegates to current app's launcher) await provider.click({ name: 'New' }); await provider.fill({ name: 'Order Number' }, 'TEST-001'); await provider.assertVisible({ name: 'Save' }); await provider.assertText({ name: 'Status' }, 'Active'); // Retrieve metadata about all launched apps const meta = provider.getLaunchedApps(); console.log(meta[0].name, meta[0].type, meta[0].url); await provider.close(); // closes new-tab if opened in Play mode }); ``` -------------------------------- ### Use Markdown in JSDoc Descriptions Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Utilize markdown formatting within JSDoc comments to enhance readability and structure. This example uses markdown for features, usage, and cross-references. ```typescript /** * Canvas App Helper * * ## Features * * - Launch apps by name or ID * - Interact with controls (buttons, inputs, etc.) * - Work with galleries and forms * - Assert control visibility and text * * ## Usage * * Access via `PowerAppsPage.canvas` or create directly: * * ```typescript * const canvas = new CanvasAppHelper(page); * await canvas.launchCanvasAppByName('My App'); * ``` * * @see {@link PowerAppsPage} */ export class CanvasAppHelper {} ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/README.md Copy the environment variable template and update with your specific Power Platform and authentication details. ```bash cp .envcopy .env ``` ```bash # Authentication MS_AUTH_EMAIL=user@contoso.com # Power Apps POWER_APPS_BASE_URL=https://make.powerapps.com POWER_APPS_ENVIRONMENT_ID=Default-00000000-0000-0000-0000-000000000000 # Canvas App (Option A: component IDs) CANVAS_APP_ID=your-canvas-app-id CANVAS_APP_TENANT_ID=your-tenant-id # Canvas App (Option B: full play URL — takes precedence over IDs) # CANVAS_APP_URL=https://apps.powerapps.com/play/e//a/?tenantId= # Model-Driven App MODEL_DRIVEN_APP_URL=https://your-org.crm.dynamics.com/main.aspx?appid=your-app-id # Gen UX (optional — defaults to POWER_APPS_BASE_URL) # MAKER_PORTAL_URL=https://make.preview.powerapps.com ``` -------------------------------- ### Run Format and Lint Checks Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CONTRIBUTING.md Execute the format check using npm and lint checks using Rush to ensure code quality and style. ```bash npm run format:check rush lint ``` -------------------------------- ### Environment Configuration Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/README.md Configure your application URLs and authentication details by creating a .env file in your project root. This file is used to store sensitive information and application-specific settings. ```env # App URLs CANVAS_APP_URL=https://apps.powerapps.com/play/... MODEL_DRIVEN_APP_URL=https://yourorg.crm.dynamics.com/... # Authentication MS_USERNAME=your.email@domain.com MS_PASSWORD=your-password AZURE_TENANT_ID=your-tenant-id # Configuration POWER_APPS_BASE_URL=https://make.powerapps.com ``` -------------------------------- ### Authenticate to Maker Portal and Model-Driven App Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/README.md Run these commands sequentially to authenticate to both the Maker Portal (for Canvas Apps and Gen UX) and the Model-Driven App domain. This is necessary for running tests across both environments. ```bash cd packages/e2e-tests # 1. Authenticate to Maker Portal (Canvas + Gen UX tests) npm run auth:headful # 2. Authenticate to the Model-Driven App domain (MDA tests) npm run auth:mda:headful ``` -------------------------------- ### Configure Microsoft Authentication Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Set up authentication credentials, including the test user's email, password or certificate details, and Azure tenant ID. The `MS_AUTH_HEADLESS` variable controls whether the sign-in process is visible. ```bash MS_AUTH_EMAIL=user@contoso.com MS_AUTH_CREDENTIAL_TYPE=password MS_AUTH_CREDENTIAL_PROVIDER=environment MS_USER_PASSWORD=your-password # MS_AUTH_CREDENTIAL_TYPE=certificate # MS_AUTH_CREDENTIAL_PROVIDER=local-file # MS_AUTH_LOCAL_FILE_PATH=../../cert/your-cert.pfx # MS_AUTH_CERTIFICATE_PASSWORD= MS_AUTH_HEADLESS=false MS_AUTH_WAIT_FOR_MSAL_TOKENS=true MS_AUTH_MSAL_TOKEN_TIMEOUT=30000 MS_AUTH_STORAGE_STATE_EXPIRATION=24 AZURE_TENANT_ID=contoso.onmicrosoft.com AUTH_ENDPOINT=https://login.microsoftonline.com ``` -------------------------------- ### Documentation Generation Workflow Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Illustrates the automated process of generating API documentation from TypeScript source code to a published Nextra-based documentation site. ```bash TypeScript Source Code (with JSDoc comments) ↓ TypeDoc CLI ↓ Markdown Files Generated ↓ Nextra Documentation Site ↓ Published Docs ``` -------------------------------- ### Perform API Testing with Playwright Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/README.md Use the ApiTestHelper to interact with Dataverse and Power Platform APIs. This example shows fetching Dataverse records with specific filters and asserting the response status. ```typescript import { test, request } from '@playwright/test'; import { ApiTestHelper } from 'power-platform-playwright-toolkit'; test('API test', async () => { const apiContext = await request.newContext({ baseURL: 'https://yourorg.crm.dynamics.com', extraHTTPHeaders: { Authorization: `Bearer ${token}`, }, }); const apiHelper = new ApiTestHelper(apiContext); // Get Dataverse records const response = await apiHelper.getDataverseRecords('accounts', { select: ['name', 'accountid'], filter: "name eq 'Contoso'", top: 10, }); await apiHelper.assertStatus(response, 200); }); ``` -------------------------------- ### Launch and Interact with a Canvas App Source: https://context7.com/microsoft/power-platform-playwright-samples/llms.txt Launches a Canvas app, waits for initialization, interacts with a gallery, adds a new record, and reloads the app. Ensure necessary environment variables or direct URLs are configured for `buildCanvasAppUrlFromEnv`. ```typescript import { test, expect } from '@playwright/test'; import { AppProvider, AppType, AppLaunchMode, CanvasAppPage, buildCanvasAppUrlFromEnv, generateUniqueOrderNumber, } from 'power-platform-playwright-toolkit'; test('Canvas App CRUD', async ({ page, context }) => { // Build the play URL from env: POWER_APPS_ENVIRONMENT_ID + CANVAS_APP_ID + CANVAS_APP_TENANT_ID // or falls back to CANVAS_APP_URL if set directly const canvasUrl = buildCanvasAppUrlFromEnv(); const provider = new AppProvider(page, context); await provider.launch({ app: 'Northwind Orders Canvas', type: AppType.Canvas, mode: AppLaunchMode.Play, skipMakerPortal: true, directUrl: canvasUrl, }); const canvasApp: CanvasAppPage = provider.getCanvasAppPage(); const canvasFrame = page.frameLocator('iframe[name="fullscreen-app-host"]'); // Wait for app to fully initialise (Canvas apps need extra time) await page.waitForTimeout(10000); await canvasFrame.locator('[data-control-name="Gallery1"] [data-control-part="gallery-item"]') .first().waitFor({ state: 'visible', timeout: 60000 }); // Count gallery items const gallery = canvasFrame.locator('[data-control-name="Gallery1"] [data-control-part="gallery-item"]'); const count = await gallery.count(); console.log(`Gallery has ${count} items`); expect(count).toBeGreaterThan(0); // Click ADD button (icon3 = plus icon in Northwind sample) const orderNumber = generateUniqueOrderNumber(); await canvasFrame.locator('[data-control-name="icon3"]').click(); await page.waitForTimeout(3000); // Fill first text input (Order Number field) const inputs = canvasFrame.locator('input[type="text"]'); if (await inputs.count() > 0) { await inputs.first().fill(orderNumber); // Save (icon5 = check mark in Northwind sample) await canvasFrame.locator('[data-control-name="icon5"]').click(); await page.waitForTimeout(3000); console.log(`Created order: ${orderNumber}`); } // Reload (icon6 = reload icon in Northwind sample) await canvasFrame.locator('[data-control-name="icon6"]').click(); await page.waitForTimeout(3000); const afterReload = await gallery.count(); console.log(`Gallery items after reload: ${afterReload}`); }); ``` -------------------------------- ### Authenticate Model-Driven App Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Run this command to authenticate for Model-Driven Apps in headful mode. Ensure you have the necessary environment variables configured. ```bash npm run auth:mda:headful ``` -------------------------------- ### Interact with Canvas Controls within an Iframe Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/canvas/README.md Use the CanvasAppPage methods to interact with controls inside the 'fullscreen-app-host' iframe. This includes clicking icons, filling text inputs, and getting gallery item counts. ```typescript await canvasApp.clickControl('IconNewItem1'); await canvasApp.fillTextInput('OrderNumber_DataCard1', 'TEST-001'); const count = await canvasApp.getGalleryItemCount('Gallery1'); ``` -------------------------------- ### Authenticate for Power Platform Apps Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/README.md Run authentication scripts for headful browser sessions. Separate storage states are used for Model-Driven Apps. ```bash npm run auth:headful ``` ```bash npm run auth:mda:headful ``` -------------------------------- ### Playwright Config for Multi-Project Setup Source: https://context7.com/microsoft/power-platform-playwright-samples/llms.txt Configure Playwright for multiple Power Platform app types, including authentication storage, timeouts, and reporters. Ensure environment variables like POWER_APPS_BASE_URL and MS_AUTH_EMAIL are set. ```typescript // packages/e2e-tests/playwright.config.ts import * as path from 'path'; import { defineConfig } from '@playwright/test'; import dotenv from 'dotenv'; import { getStorageStatePath, TimeOut, ConfigHelper } from 'power-platform-playwright-toolkit'; dotenv.config({ path: path.resolve(__dirname, '.env') }); export default defineConfig({ globalSetup: require.resolve('./globals/global-setup'), globalTeardown: require.resolve('./globals/global-teardown'), fullyParallel: !process.env.CI, forbidOnly: !!process.env.CI, retries: 0, workers: Number(process.env.WORKERS) || 1, timeout: Number(process.env.TEST_TIMEOUT) || 120_000, testDir: './tests', testMatch: ['**/*.+(spec|test|setup).+(ts|js|mjs)'], outputDir: path.join(process.env.OUTPUT_DIRECTORY || './test-results', 'artifacts'), expect: { timeout: TimeOut.DefaultWaitTime }, reporter: process.env.CI ? [['dot'], ['junit', { outputFile: './test-results/junit-results.xml' }]] : [['list'], ['html', { open: 'never' }]], use: { baseURL: ConfigHelper.getBaseUrl(), // reads POWER_APPS_URL browserName: 'chromium', headless: process.env.HEADLESS !== 'false', viewport: { width: 1920, height: 1080 }, screenshot: 'only-on-failure', video: 'on', trace: 'retain-on-failure', actionTimeout: TimeOut.OneMinuteTimeOut, navigationTimeout: TimeOut.OneMinuteTimeOut, ignoreHTTPSErrors: true, locale: 'en-US', launchOptions: { args: ['--start-maximized', '--window-size=1920,1080'] }, }, projects: [ { name: 'model-driven-app', testDir: './tests/northwind/mda', testMatch: '**/*.test.ts', use: { // MDA uses a separate storage state authenticated against the CRM domain storageState: path.join( path.dirname(getStorageStatePath(process.env.MS_AUTH_EMAIL!)), `state-mda-${process.env.MS_AUTH_EMAIL}.json` ), }, }, { name: 'canvas-app', testDir: './tests/northwind/canvas', testMatch: '**/*.test.ts', use: { storageState: getStorageStatePath(process.env.MS_AUTH_EMAIL!), }, }, { name: 'gen-ux', testDir: './tests/gen-ux', testMatch: '**/*.test.ts', use: { storageState: getStorageStatePath(process.env.MS_AUTH_EMAIL!), }, }, ], }); ``` -------------------------------- ### Clean and Rebuild Documentation Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Troubleshoot documentation not updating by cleaning the previous build artifacts and running the documentation generation script. ```bash # Clean and rebuild cd packages/power-platform-playwright-toolkit rm -rf ../docs/pages/reference npm run docs ``` -------------------------------- ### Configure Microsoft Authentication Environment Variables Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/README.md Set these environment variables to configure how the authentication process will acquire tokens. Options include password or certificate authentication, and whether to run headlessly. ```env MS_AUTH_EMAIL=user@contoso.com MS_AUTH_CREDENTIAL_TYPE=password MS_AUTH_CREDENTIAL_PROVIDER=environment MS_AUTH_ENV_VARIABLE_NAME=MS_USER_PASSWORD MS_USER_PASSWORD=your-password-here MS_AUTH_HEADLESS=true MS_AUTH_WAIT_FOR_MSAL_TOKENS=true MS_AUTH_MSAL_TOKEN_TIMEOUT=30000 AUTH_ENDPOINT=https://login.microsoftonline.com ``` ```env # Certificate authentication (recommended for CI/CD — uncomment to use): # MS_AUTH_CREDENTIAL_TYPE=certificate # MS_AUTH_CREDENTIAL_PROVIDER=local-file # MS_AUTH_LOCAL_FILE_PATH=./cert/your-cert.pfx # MS_AUTH_CERTIFICATE_PASSWORD=your-cert-password ``` -------------------------------- ### Configure Model-Driven App URL Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Provide the full URL for your Model-Driven App, including the `appid` parameter. This URL can be obtained by opening the app in the browser and copying the address bar. ```bash MODEL_DRIVEN_APP_URL=https://your-org.crm.dynamics.com/main.aspx?appid=00000000-0000-0000-0000-000000000000 ``` -------------------------------- ### Run All MDA Tests Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/mda/README.md Execute all end-to-end tests for the Model-Driven App project. ```bash npx playwright test --project=mda ``` -------------------------------- ### Run MDA Tests in Headed Mode Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/mda/README.md Execute Model-Driven App end-to-end tests with the browser visible. ```bash npx playwright test --project=mda --headed ``` -------------------------------- ### Run Specific MDA Test File Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/mda/README.md Execute a single end-to-end test file for the Model-Driven App. ```bash npx playwright test tests/northwind/mda/form-context.test.ts ``` -------------------------------- ### Configure Canvas App IDs or URL Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Set either the Canvas App ID and Tenant ID, or the full play URL for the Canvas App. The App ID and Tenant ID can be found in the Maker Portal under the app's details. ```bash CANVAS_APP_ID=00000000-0000-0000-0000-000000000000 CANVAS_APP_TENANT_ID=00000000-0000-0000-0000-000000000000 # CANVAS_APP_URL=https://apps.powerapps.com/play/e//a/?tenantId= ``` -------------------------------- ### Authenticate MDA Tests Headlessly Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/mda/README.md Run this command to authenticate the MDA tests using a separate storage state for the *.crm.dynamics.com domain. ```bash cd packages/e2e-tests npm run auth:mda:headful ``` -------------------------------- ### Launch Northwind Canvas App using AppProvider Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/canvas/README.md Initialize and launch the Northwind Orders Canvas App using the AppProvider. Ensure to set skipMakerPortal to true if not needed. ```typescript const appProvider = new AppProvider(page, context); await appProvider.launch({ app: 'Northwind Orders', type: AppType.Canvas, directUrl: process.env.CANVAS_APP_URL!, skipMakerPortal: true, }); const canvasApp = appProvider.getCanvasAppPage(); ``` -------------------------------- ### Construct Power Platform URLs with URLBuilder Source: https://context7.com/microsoft/power-platform-playwright-samples/llms.txt Use URLBuilder to programmatically construct Maker Portal URLs. It automatically injects the environment ID from environment variables or explicit arguments. ```typescript import { URLBuilder } from 'power-platform-playwright-toolkit'; // Default constructor reads POWER_APPS_BASE_URL and POWER_APPS_ENVIRONMENT_ID from env const builder = new URLBuilder(); console.log(builder.buildAppsPageUrl()); // → https://make.powerapps.com/environments//apps console.log(builder.buildSolutionsPageUrl()); // → https://make.powerapps.com/environments//solutions console.log(builder.buildHomePageUrl()); // → https://make.powerapps.com/environments//home console.log(builder.buildFlowsPageUrl()); // → https://make.powerapps.com/environments//flows console.log(builder.buildTablesPageUrl()); console.log(builder.buildConnectionsPageUrl()); // Switch environment at runtime builder.setEnvironment('new-env-guid-here'); console.log(builder.buildAppsPageUrl()); // → https://make.powerapps.com/environments/new-env-guid-here/apps // Explicit constructor values const customBuilder = new URLBuilder( 'https://make.preview.powerapps.com', 'Default-11111111-1111-1111-1111-111111111111' ); console.log(customBuilder.buildAppsPageUrl()); // → https://make.preview.powerapps.com/environments/Default-11111111-1111-1111-1111-111111111111/apps ``` -------------------------------- ### Manage Authentication State for Power Platform Source: https://context7.com/microsoft/power-platform-playwright-samples/llms.txt Use these helpers to manage browser storage state for Microsoft OAuth. Ensure environment variables MS_AUTH_EMAIL and MS_USER_PASSWORD are set before running. ```typescript import { authenticateToMicrosoft, getStorageStatePath, hasValidAuth, clearAuthState, validateAuthConfig, getAuthState, } from 'power-platform-playwright-toolkit'; import { chromium } from '@playwright/test'; // --- authentication script (run once before tests) --- async function main() { // Validate required env vars before attempting auth validateAuthConfig(); // throws if MS_AUTH_EMAIL / MS_USER_PASSWORD are missing const email = process.env.MS_AUTH_EMAIL!; // Check whether a valid cached state already exists if (hasValidAuth(email)) { console.log('Auth state exists:', getStorageStatePath(email)); } else { // Clear any stale state files first clearAuthState(email); // Authenticate — saves state to ~/.playwright-ms-auth/state-.json await authenticateToMicrosoft( 'https://make.powerapps.com/home', false // false = headful browser (use true for CI headless) ); } } // --- use in playwright.config.ts --- import { defineConfig } from '@playwright/test'; import { getStorageStatePath } from 'power-platform-playwright-toolkit'; export default defineConfig({ projects: [ { name: 'canvas-app', use: { storageState: getStorageStatePath(process.env.MS_AUTH_EMAIL!), }, }, { name: 'model-driven-app', use: { // MDA tests use a separate state file authenticated against the CRM domain storageState: `.playwright-ms-auth/state-mda-${process.env.MS_AUTH_EMAIL}.json`, }, }, ], }); // --- retrieve state object at runtime --- async function getStateForContext() { const { storageState } = await getAuthState(); // throws if state file missing const browser = await chromium.launch(); const ctx = await browser.newContext({ storageState }); // ctx is now pre-authenticated return ctx; } ``` -------------------------------- ### Navigate Power Platform Maker Portal Source: https://context7.com/microsoft/power-platform-playwright-samples/llms.txt Orchestrates full navigation to Maker Portal sections using URLBuilder and PageWaiter. Supports default timeouts, custom timeouts, and skipping page load waits. ```typescript import { Page } from '@playwright/test'; import { PowerPlatformNavigator, PowerAppsPageLocators, } from 'power-platform-playwright-toolkit'; async function navigateExample(page: Page) { const locators = new PowerAppsPageLocators(page); const navigator = new PowerPlatformNavigator(page, locators, { baseUrl: 'https://make.powerapps.com', environmentId: process.env.POWER_APPS_ENVIRONMENT_ID, }); // Navigate with default 60s timeout + intelligent page-load detection await navigator.navigateToApps(); await navigator.navigateToSolutions({ timeout: 30000 }); await navigator.navigateToHome({ waitForLoad: false }); // skip wait await navigator.navigateToFlows(); await navigator.navigateToTables(); await navigator.navigateToConnections(); // Switch environment for subsequent navigations navigator.setEnvironment('new-env-guid'); await navigator.navigateToApps(); // uses new env in the URL // Check if already on a page const onApps = await navigator.isOnPage('apps'); console.log('Currently on Apps page:', onApps); // Access the underlying URL builder const urlBuilder = navigator.getURLBuilder(); console.log('Apps URL:', urlBuilder.buildAppsPageUrl()); } ``` -------------------------------- ### Authenticate for Northwind Canvas App Tests Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/tests/northwind/canvas/README.md Navigate to the e2e-tests directory and run the authentication command for headful testing. ```bash cd packages/e2e-tests npm run auth:headful ``` -------------------------------- ### Navigate MDA Views with waitForURL Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/CLAUDE.md Use `waitForURL` instead of `waitForTimeout` for navigation in Model-Driven Apps. This ensures the page has fully loaded and the URL has updated, preventing flaky tests. ```typescript await modelDrivenApp.grid.openRecord({ rowNumber: 0 }); await page.waitForURL(/pagetype=entityrecord/, { timeout: 30000 }); ``` -------------------------------- ### Documenting Parameters with @param Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Shows how to use the @param tag to document function parameters, including optional parameters and object properties. ```typescript /** * Navigate to Power Apps home page * * @param baseUrl - Optional base URL to navigate to. If not provided, uses ConfigHelper.getBaseUrl() */ async navigateToHome(baseUrl?: string): Promise { // Implementation } ``` ```typescript /** * @param options - Control options * @param options.name - Name or label of the control * @param options.type - Type of control (Button, TextInput, etc.) * @param options.timeout - Maximum time to wait in milliseconds * @param options.exact - Whether to match the name exactly */ getControl(options: ControlOptions): Locator { // Implementation } ``` -------------------------------- ### Run All Playwright Tests Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/e2e-tests/README.md Execute all Playwright tests in the project. ```bash npx playwright test ``` -------------------------------- ### CanvasAppHelper Class Source: https://github.com/microsoft/power-platform-playwright-samples/blob/main/packages/power-platform-playwright-toolkit/DOCUMENTATION.md Helper class for Canvas App specific operations. Handles launching, interacting with, and testing Canvas apps. Use via PowerAppsPage.canvas or instantiate directly. ```APIDOC ## Class CanvasAppHelper ### Description Helper class for Canvas App specific operations. Handles launching, interacting with, and testing Canvas apps. Use via PowerAppsPage.canvas or instantiate directly. ### Constructor ```typescript constructor(page: Page) ``` #### Parameters * **page** (Page) - Playwright page object ```