Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This Power Platform Playwright toolkit API reference documents public classes, methods, and types you can use to automate end-to-end testing of canvas and model-driven apps.
AppProvider
Entry point for launching Power Platform apps. Instantiate once per test, then call launch().
class AppProvider {
constructor(page: Page, context: BrowserContext)
launch(options: AppLaunchOptions): Promise<void>
getModelDrivenAppPage(): ModelDrivenAppPage
getCanvasAppPage(): CanvasAppPage
getGenUxPage(): GenUxPage
}
AppLaunchOptions
Options passed to AppProvider.launch() to configure which app to open and how.
interface AppLaunchOptions {
app: string; // Display name of the app
type: AppType; // Canvas | ModelDriven
mode: AppLaunchMode; // Play | Edit
skipMakerPortal?: boolean; // true: use directUrl, skip make.powerapps.com navigation
directUrl?: string; // Full URL when skipMakerPortal is true
}
AppType
Specifies the type of Power Platform app to launch.
enum AppType {
Canvas = 'canvas',
ModelDriven = 'model-driven',
}
AppLaunchMode
Determines whether the app opens in play mode or edit mode.
enum AppLaunchMode {
Play = 'play',
Edit = 'edit',
}
ModelDrivenAppPage
Returned by AppProvider.getModelDrivenAppPage(). Provides navigation and component access.
class ModelDrivenAppPage {
readonly grid: GridComponent
readonly form: FormComponent
readonly commanding: CommandingComponent
navigateToGridView(entityLogicalName: string): Promise<void>
navigateToFormView(entityLogicalName: string): Promise<void>
}
GridComponent
Wraps the AG Grid used in model-driven list views. Accessed via ModelDrivenAppPage.grid.
class GridComponent {
waitForGridLoad(): Promise<void>
filterByKeyword(keyword: string): Promise<void>
filterByColumn(columnName: string, value: string): Promise<void>
getCellValue(rowIndex: number, columnName: string): Promise<string | null>
getRowCount(): Promise<number>
isGridEmpty(): Promise<boolean>
openRecord(options: OpenRecordOptions): Promise<void>
selectRow(rowIndex: number): Promise<void>
selectRows(rowIndexes: number[]): Promise<void>
}
OpenRecordOptions
Options for identifying which record to open from the grid.
interface OpenRecordOptions {
rowNumber?: number; // 0-based row index
columnName?: string; // column to match (display name or schema name)
columnValue?: string; // value to match in the column
}
FormComponent
Wraps the Dynamics 365 form runtime. Accessed via ModelDrivenAppPage.form.
class FormComponent {
getAttribute(fieldName: string): Promise<string | null>
setAttribute(fieldName: string, value: string): Promise<void>
save(): Promise<void>
isDirty(): Promise<boolean>
isValid(): Promise<boolean>
navigateToTab(tabName: string): Promise<void>
setFieldVisibility(fieldName: string, visible: boolean): Promise<void>
setFieldDisabled(fieldName: string, disabled: boolean): Promise<void>
setFieldRequiredLevel(
fieldName: string,
level: 'none' | 'recommended' | 'required'
): Promise<void>
execute<T>(
fn: (formContext: Xrm.FormContext) => T | Promise<T>
): Promise<T>
}
FormComponent.execute()
Runs arbitrary code in the browser's form context with full access to the Xrm Client API:
const value = await mda.form.execute(
(ctx) => ctx.getAttribute('nwind_ordernumber')?.getValue()
);
See API testing through form context for detailed usage.
CommandingComponent
Wraps the model-driven app command bar. Accessed via ModelDrivenAppPage.commanding.
class CommandingComponent {
clickButton(ariaLabel: string): Promise<void>
clickMoreCommands(): Promise<void>
}
CanvasAppPage
Returned by AppProvider.getCanvasAppPage(). Provides the canvas iframe frame locator.
class CanvasAppPage {
getFrame(): FrameLocator
waitForLoad(controlName?: string): Promise<void>
}
GenUxPage
Returned by AppProvider.getGenUxPage(). Provides interactions with the Power Apps Maker Portal GenUX AI designer for creating, generating, inspecting, and publishing model-driven apps from AI prompts.
class GenUxPage {
readonly previewFrame: FrameLocator // UCI Preview iframe locator
// Power Apps navigation
goToAppsPage(): Promise<void>
navigateToStartWithPageDesign(): Promise<void>
createAppWithName(appName: string): Promise<void>
addNewPage(): Promise<void>
// AI generation
waitForUCIPreviewFrameAndFillPrompt(prompt: string): Promise<void>
waitForUCIPreviewFrameAndSelectTemplate(templateText: string): Promise<void>
verifyThoughtStreaming(): Promise<void>
verifyCodeAndPreviewTabsAvailable(): Promise<void>
verifyCodeStreaming(): Promise<void>
// Inspection
clickPreviewTab(): Promise<void>
clickCodeTab(): Promise<void>
waitForGeneratedContent(): Promise<void>
waitForCodeTabContent(): Promise<void>
getPreviewTabDom(): Promise<string>
getCodeTabContent(): Promise<string>
// Publishing
publishApp(): Promise<void>
buildCanvasPlayUrl(): string
// Form interaction
submitForm(): Promise<void>
waitForSubmitSuccess(timeout?: number): Promise<void>
// App management
getAppIdFromUrl(): string
searchAndPlayApp(appName: string, context: BrowserContext): Promise<Page | null>
deleteAppsMatchingPrefix(prefix: string): Promise<void>
deleteAppFromAppListIfFound(appName: string): Promise<void>
}
GenUxPage.previewFrame
Exposes the FrameLocator for the UCI Preview iframe. Use this property to query generated form elements directly:
const input = genUxPage.previewFrame.getByRole('textbox', { name: 'First Name' });
await expect(input).toBeVisible();
GenUxPage.verifyThoughtStreaming()
Checks for transient GenUX streaming indicators, such as thought text, Stop button, and Agent Thoughts. Each check is best-effort - generation might complete before all indicators appear. The only hard assertion is that either streaming is in progress or "Your page is now generated" is visible.
GenUxPage.searchAndPlayApp()
Returns null when Play is disabled (app isn't yet published) rather than throwing an error. Use test.skip() on a null return:
const appPage = await genUxPage.searchAndPlayApp(appName, context);
if (!appPage) test.skip();
Utility functions
Standalone helper functions for common setup and configuration tasks.
buildCanvasAppUrlFromEnv
Reads CANVAS_APP_URL from the environment:
function buildCanvasAppUrlFromEnv(): string
getStorageStatePath
Returns the path to the Power Apps storage state file for the given email:
function getStorageStatePath(email: string): string
// Returns: packages/e2e-tests/.playwright-ms-auth/state-<email>.json
ConfigHelper
Provides configuration helpers, such as checking whether the cached storage state expired.
class ConfigHelper {
static checkStorageStateExpiration(
statePath: string
): { expired: boolean; expiresOn?: number }
}
Locator utilities
Helper methods for locating Power Apps controls within iframes.
LocatorUtils
Static methods for finding canvas app controls and gallery items by name.
class LocatorUtils {
static getByControlName(frame: FrameLocator, controlName: string): Locator
static getGalleryItem(frame: FrameLocator, titleText: string): Locator
}
Type exports
Export all types from the package root:
import {
AppProvider,
AppType,
AppLaunchMode,
AppLaunchOptions,
ModelDrivenAppPage,
GridComponent,
FormComponent,
CommandingComponent,
CanvasAppPage,
GenUxPage,
buildCanvasAppUrlFromEnv,
getStorageStatePath,
ConfigHelper,
LocatorUtils,
} from 'power-platform-playwright-toolkit';