ArchitectureUsage Patterns

Usage Patterns

This page explains when and how to use each pattern in the toolkit.

Tip: Not sure which pattern to use? Check the Decision Tree at the bottom of this page.

Best for: Testing existing apps by ID or name

Code Example

import { AppProvider, AppType, AppLaunchMode } from 'playwright-power-platform-toolkit';
 
test('Test with AppProvider', async ({ page }) => {
  const provider = new AppProvider(page);
 
  // Launch app by ID (fastest)
  await provider.launch({
    app: { id: 'app-id' },
    type: AppType.Canvas,
    mode: AppLaunchMode.Play
  });
 
  // Interact with controls
  await provider.click({ name: 'Submit' });
  await provider.fill({ name: 'Email' }, 'test@example.com');
 
  // Assert results
  await provider.assertVisible({ name: 'Success' });
  await provider.assertText({ name: 'Status' }, 'Submitted');
 
  // Clean up
  await provider.close();
});

When to Use

  • Testing existing apps
  • You have the app ID or name
  • You want the simplest API
  • Running tests in CI/CD

Advantages

  • Simplest API
  • Automatic factory management
  • State tracking for multiple apps
  • Built-in assertions

Pattern 2: Factory for Advanced Scenarios

Best for: Custom launcher logic and advanced control

Code Example

import { AppLauncherFactory, AppType, AppLaunchMode } from 'playwright-power-platform-toolkit';
 
test('Test with Factory', async ({ page }) => {
  // Get launcher directly
  const launcher = AppLauncherFactory.getCanvasLauncher(page);
 
  // Launch app
  await launcher.launchById('app-id', 'https://make.powerapps.com', AppLaunchMode.Play);
 
  // Direct control interactions
  await launcher.clickControl({ name: 'Submit' });
  await launcher.fillControl({ name: 'Email' }, 'test@example.com');
 
  // Check state
  const isReady = launcher.isAppReady();
  const appId = launcher.getAppId();
 
  // Clean up
  await launcher.closeApp();
});

When to Use

  • Need direct launcher access
  • Custom wrapper around launcher
  • Advanced caching scenarios
  • Performance-critical operations

Advantages

  • Direct launcher access
  • Manual cache control
  • Lower-level control
  • Reusable launcher instances

Pattern 3: PowerAppsPage for App Creation

Best for: Creating new apps and studio operations

Code Example

import { PowerAppsPage } from 'playwright-power-platform-toolkit';
 
test('Create and test app', async ({ page }) => {
  const powerApps = new PowerAppsPage(page);
 
  // Navigate to apps page
  await powerApps.navigateToApps();
 
  // Create Canvas app
  await powerApps.canvas.createBlankCanvasApp('TestApp');
  await powerApps.canvas.addButton();
  await powerApps.canvas.saveApp();
  await powerApps.canvas.publishApp();
 
  // Create Model-Driven app
  await powerApps.modelDriven.createBlankModelDrivenApp('SalesApp');
  await powerApps.modelDriven.addNavigationGroup('Sales');
  await powerApps.modelDriven.publishApp();
});

When to Use

  • Creating new apps
  • Studio operations
  • App management (delete, publish)
  • Navigation and search

Advantages

  • App creation capabilities
  • Studio automation
  • Navigation helpers
  • Unified Power Apps Portal access

Component Interaction Matrix

State Management

AppProvider State Lifecycle

Launcher Caching Flow

Decision Tree

Need help choosing? Follow this decision tree to find the right pattern.

Quick Decision Guide

Need to test existing app by ID? → Use AppProvider ✅
Need to test existing app by name? → Use AppProvider ✅
Need to create new app? → Use PowerAppsPage ✅
Need custom launcher logic? → Use AppLauncherFactory ✅
Need maximum control? → Use Page Objects directly ✅

Next Steps