Playwright Infrastructure in the PPUX Repository#

This chapter explores the Playwright testing infrastructure used in the Power Platform UX (PPUX) repository, providing a comprehensive understanding of enterprise-level test automation setup.

Repository Overview#

The PPUX repository uses a monorepo approach to manage multiple applications and shared packages:

power-platform-ux/
├── apps/                    # Power Platform applications
│   ├── make-powerapps-com/
│   ├── admin-powerplatform-microsoft-com/
│   └── [other-power-platform-apps]/
├── packages/                # Shared npm packages
│   ├── playwright-integration-tests/  # Centralized test framework
│   └── [other-packages]/
└── package.json            # Root configuration

This structure allows for:

  • Centralized testing infrastructure

  • Shared components and utilities

  • Independent app development with shared resources

  • Standardized testing approaches across teams

For a detailed breakdown of the recommended folder structure for Playwright tests, see the Folder Structure page.

Playwright Configuration#

The PPUX repository uses a comprehensive playwright.config.ts file to control test execution. This configuration provides flexibility through environment variables and utility functions. For detailed information on how the configuration works and how to customize it, see the Playwright Configuration page.

Playwright Integration Tests Package#

The playwright-integration-tests package serves as the central testing framework for all Power Platform applications. Let’s examine its structure:

playwright-integration-tests/
├── src/
│   ├── config/                     # Test configurations
│   │   └── config.json
│   │
│   ├── apps/                       # Custom test fixtures for different apps
│   │   └── <app_name>/             # App-specific test module
│   │       ├── pages/              # Page Object Models (POMs)
│   │       ├── tests/              # Test cases for the app
│   │       └── utils/              # App-specific utilities
│   │           ├── fixtures.ts     # Fixtures like login, environment setup
│   │           └── testUtils.ts    # Helpers used across tests
│   │
├── playwright.config.ts           # Playwright config (projects, baseURL, tracing, etc.)
├── package.json                   # Dependencies and scripts
└── README.md                      # Setup, usage, and contribution guidelines

Key Configuration Files#

The package.json file defines essential scripts for the testing workflow:

{
  "scripts": {
    "record": "playwright codegen",
    "login-tms": "node ./src/loginTMS.mjs",
    "int-test": "playwright test",
    "int-test:config": "playwright test --config=./playwright.config.ts",
    "show-trace": "playwright show-trace"
  }
}

These scripts enable:

  • Recording test interactions with Playwright Codegen

  • Authentication with Test Management System (TMS)

  • Running integration tests with different configurations

  • Debugging test failures with trace viewer

Core Testing Dependencies#

The package utilizes several specialized Playwright extensions:

{
  "dependencies": {
    "@axe-core/playwright": "4.9.1",
    "@paeng/playwright-auth": "2.0.2",
    "@paeng/playwright-solution": "3.3.3",
    "@paeng/playwright-teams-info": "0.36.0",
    "@paeng/playwright-test-reporter": "1.3.18",
    "@paeng/playwright-tms": "1.4.10",
    "@playwright/test": "1.52.0"
  }
}

Each package serves a specific purpose:

  • @axe-core/playwright: Accessibility testing integration

  • @paeng/playwright-auth: Authentication helpers for Microsoft identity

  • @paeng/playwright-solution: Solution deployment testing utilities

  • @paeng/playwright-teams-info: Team ownership tracking for tests

  • @paeng/playwright-test-reporter: Custom enterprise reporting

  • @paeng/playwright-tms: Test Management System integration

The Heart of Testing: playwright.config.ts#

The playwright.config.ts file configures the testing environment:

export default defineConfig<AuthOptions>({
  name: "Playwright Integration Tests",
  globalSetup: require.resolve("./src/globals/global-setup"),
  globalTeardown: require.resolve("./src/globals/global-teardown"),
  use: {
    authDir: path.join(__dirname, "./playwright/.auth/"),
    browserName: ProcessEnvironmentConfig().browserType as BrowserTypes,
    baseURL: getBaseUrl(),
    headless: ProcessEnvironmentConfig().headless,
    viewport: { width: 1920, height: 1080 },
    ignoreHTTPSErrors: true,
    acceptDownloads: true,
    permissions: ["clipboard-read", "clipboard-write"],
    actionTimeout: TimeOut.OneMinuteTimeOut,
    navigationTimeout: TimeOut.OneMinuteTimeOut,
    storageState:
      !isDevEnvironment() && !isTMS ? storageStatePath() : undefined,
  },
  testDir: ProcessEnvironmentConfig().testDirectory,
  timeout: ProcessEnvironmentConfig().testTimeout,
  workers: ProcessEnvironmentConfig().workers,
  retries: ProcessEnvironmentConfig().retries,
});

Key configuration aspects include:

  • Global setup and teardown hooks for test environment preparation

  • Authentication directory for storing credentials

  • Dynamic base URL selection based on environment

  • Viewport standardization for consistent testing

  • Permission management for clipboard operations

  • Timeout configurations to prevent flaky tests

  • Storage state management for session persistence

Built-in Failure Analysis#

The configuration includes comprehensive failure analysis tools:

use: {
  screenshot: 'only-on-failure',
  video: 'retain-on-failure',
  trace: 'retain-on-failure',
  viewport: { width: 1920, height: 1080 },
  actionTimeout: TimeOut.OneMinuteTimeOut,
  navigationTimeout: TimeOut.OneMinuteTimeOut,
}

This ensures:

  • Screenshots capture the exact state when tests fail

  • Video recordings show the sequence leading to failure

  • Trace files provide detailed technical information for debugging

  • Consistent viewport dimensions eliminate responsive design issues

  • Adequate timeouts accommodate application performance variations

Enterprise Test Reporting#

The PPUX repository implements advanced test reporting capabilities:

reporter: [
  [
    "@paeng/playwright-test-reporter",
    {
      testRunName: ProcessEnvironmentConfig().playwrightTestRunName,
      testDirectory: ProcessEnvironmentConfig().testDirectory,
      sendEmail: ProcessEnvironmentConfig().sendEmailNotification,
      sendFailureEmail: ProcessEnvironmentConfig().sendFailureEmailNotification,
      emailHandlebarPath: handlebarPath,
      pushToTelemetry: ProcessEnvironmentConfig().pushFailuresToTelemetry,
      createBug: ProcessEnvironmentConfig().createBugForFailures,
      fireIcm: ProcessEnvironmentConfig().fireIcmForFailures,
    },
  ],
];

This custom reporter provides:

  • Email notifications for test results and failures

  • Telemetry data collection for performance analysis

  • Automatic bug creation in tracking systems

  • Incident Management (ICM) integration for critical failures

  • Customizable email templates using Handlebars

Page Object Model Implementation#

The PPUX repository follows the Page Object Model (POM) pattern to create maintainable tests:

// Example Page Object for the PowerApps studio
export class StudioPage {
  readonly page: Page;
  readonly headerControls: Locator;
  readonly saveButton: Locator;
  readonly previewButton: Locator;

  constructor(page: Page) {
    this.page = page;
    this.headerControls = page.locator(".studio-header-controls");
    this.saveButton = page.getByRole("button", { name: "Save" });
    this.previewButton = page.getByRole("button", { name: "Preview" });
  }

  async saveApp() {
    await this.saveButton.click();
    await this.page.waitForSelector(".save-success-notification", {
      state: "visible",
    });
  }

  async previewApp() {
    await this.previewButton.click();
    await this.page.waitForLoadState("networkidle");
  }
}

The POM pattern:

  • Encapsulates page elements and interactions

  • Improves test readability and maintenance

  • Simplifies test authoring through reusable components

  • Provides a clear separation between test logic and page interactions

Test Fixtures for Application State#

Custom fixtures handle complex test prerequisites:

// Custom fixture for logged-in PowerApps session
const powerAppsTest = test.extend<PowerAppsFixtures>({
  appStudioPage: async ({ page }, use) => {
    // Authenticate and navigate to app studio
    await page.goto("/");
    await login(page);
    await page.goto("/studio");
    await page.waitForLoadState("networkidle");

    // Create a new page object and pass it to the test
    const studioPage = new StudioPage(page);
    await use(studioPage);
  },
});

These fixtures enable:

  • Pre-authenticated test sessions

  • Standard app states for testing

  • Reduced test setup duplication

  • Consistent starting points for different test scenarios

Integration Test Wrapper#

The PPUX repository uses a custom integrationTest wrapper function to organize tests with specific configurations. This wrapper is so important that it has its own dedicated page in this book.

The wrapper function provides:

  • Consistent test organization

  • Environment-specific configurations

  • Team ownership tracking

  • Test Management System (TMS) integration

Test Tenant Management System (TMS)#

For managing complex test environments and user scenarios, the PPUX repository integrates with the Test Tenant Management System (TMS). This system is so important for enterprise testing that we’ve created a dedicated page about TMS integration.

TMS provides:

  • Centralized management of test environments and scenarios

  • User management for different testing roles

  • Authentication automation

  • Access to scenario details in tests

Test Environment Configuration#

The PPUX repository uses a robust environment configuration system to manage URLs and settings for different environments and geographical regions. This configuration is managed through the config.json file and is essential for running tests across multiple environments. Learn more in our test environments configuration guide.

Environment-Specific Configuration#

The PPUX repo uses a dynamic configuration approach:

function ProcessEnvironmentConfig() {
  return {
    browserType: process.env.BROWSER || "chromium",
    headless: process.env.HEADLESS !== "false",
    testDirectory: process.env.TEST_DIR || "./src/apps/**/*.spec.ts",
    testTimeout: parseInt(process.env.TIMEOUT || "60000"),
    workers: process.env.WORKERS ? parseInt(process.env.WORKERS) : undefined,
    retries: process.env.CI ? 2 : 0,
    environment: process.env.ENV || "dev",
    // Additional environment variables...
  };
}

This allows:

  • Dynamic configuration based on environment variables

  • Different settings for CI/CD versus local development

  • Customizable test execution based on context

  • Simplified command-line overrides for specific test runs

Key Takeaways#

The PPUX repository’s Playwright infrastructure demonstrates enterprise-level test automation with:

  1. Centralized Framework: Shared testing resources across multiple applications

  2. Structured Organization: Clear separation of page objects, tests, and utilities

  3. Advanced Reporting: Enterprise-grade reporting with notifications and bug tracking

  4. Comprehensive Failure Analysis: Multi-faceted approach to debugging test failures

  5. Environment Flexibility: Dynamic configuration for different testing contexts

  6. Authentication Management: Specialized handling of Microsoft identity services

This approach can be adapted to other enterprise testing needs by implementing similar patterns and practices.