Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Canvas-Apps werden innerhalb eines iframe innerhalb des Power Apps Players ausgeführt. In diesem Leitfaden wird erläutert, wie Sie eine Canvas-App starten, Ihre Selektoren auf den richtigen Frame beschränken und mithilfe von Attributen mit data-control-name Steuerelementen interagieren.
Funktionsweise von Canvas-App-Tests
Wenn eine Canvas-App im Wiedergabemodus geladen wird, stellt die Laufzeit die App in einer iframe bereit.
iframe[name="fullscreen-app-host"]
Alle Steuerelemente in der App verfügen über ein data-control-name-Attribut, das dem steuerelementnamen entspricht, den Sie in Power Apps Studio festgelegt haben. Galerieelemente verfügen über data-control-part="gallery-item".
Sie können alle Locators auf diesen Frame beschränken, bevor Sie mit Steuerelementen interagieren:
const canvasFrame = page.frameLocator('iframe[name="fullscreen-app-host"]');
Starten einer Canvas-App
Verwenden Sie AppProvider, um die App zu starten und das CanvasAppPage Objekt zu erhalten.
import { test, expect } from '@playwright/test';
import {
AppProvider,
AppType,
AppLaunchMode,
buildCanvasAppUrlFromEnv,
} from 'power-platform-playwright-toolkit';
const CANVAS_APP_URL = buildCanvasAppUrlFromEnv();
test.beforeEach(async ({ page, context }) => {
const app = new AppProvider(page, context);
await app.launch({
app: 'Northwind Orders',
type: AppType.Canvas,
mode: AppLaunchMode.Play,
skipMakerPortal: true, // bypasses Power Apps navigation
directUrl: CANVAS_APP_URL,
});
});
Tipp
Das Festlegen von skipMakerPortal: true und Bereitstellen eines directUrl spart 10 bis 20 Sekunden pro Test, indem die Navigation in Power Apps umgangen wird.
Warten, bis die App geladen wird
Warten Sie nach dem Start, bis ein bekanntes Steuerelement angezeigt wird, bevor Sie interagieren:
const canvasFrame = page.frameLocator('iframe[name="fullscreen-app-host"]');
// Wait for gallery to confirm the app is loaded and data is present
await canvasFrame
.locator('[data-control-name="Gallery1"] [data-control-part="gallery-item"]')
.first()
.waitFor({ state: 'visible', timeout: 60000 });
Hinweis
Canvas-Apps, die von Dataverse unterstützt werden, können 30 bis 60 Sekunden dauern, um Daten in einen Katalog zu laden. Verwenden Sie ein 60-Sekunden-Timeout für Galerie-Auswähler.
Interagieren mit Steuerelementen
Die folgenden Beispiele zeigen, wie mit Steuerelementen von Canvas-Apps mithilfe von Rahmenbereich-Lokatoren interagiert wird.
Klicken Sie auf eine Schaltfläche
Suchen Sie eine Schaltfläche anhand ihres data-control-name Attributs, warten Sie, bis sie sichtbar ist, und klicken Sie dann darauf.
const addButton = canvasFrame.locator('[data-control-name="icon3"]');
await addButton.waitFor({ state: 'visible', timeout: 10000 });
await addButton.click();
Ausfüllen einer Texteingabe
Verwenden Sie die fill() Methode, um den Wert einer Texteingabe festzulegen, indem Sie sie über deren aria-label ansprechen.
const orderNumberInput = canvasFrame.locator('input[aria-label="Order Number"]');
await orderNumberInput.fill('ORD-12345');
Wählen Sie ein Galerieelement
Filtern Sie Katalogelemente nach ihren angezeigten Textinhalten, um nach einem bestimmten Datensatz zu suchen und darauf zu klicken.
const galleryItem = canvasFrame
.locator('[data-control-part="gallery-item"]')
.filter({ has: canvasFrame.locator('[data-control-name="Title1"]').getByText('Order 001') });
await galleryItem.waitFor({ state: 'visible' });
await galleryItem.click();
Zählen von Katalogelementen
Verwenden Sie die count() Methode, um zu überprüfen, ob der Katalog die erwartete Anzahl von Elementen enthält.
const galleryItems = canvasFrame.locator('[data-control-name="Gallery1"] [data-control-part="gallery-item"]');
const count = await galleryItems.count();
expect(count).toBeGreaterThan(0);
Erstellen eines Seitenobjekts für Ihre Canvas-App
Um die Wartung zu gewährleisten, kapseln Sie Selektoren und Aktionen in einer Page Object-Klasse:
// pages/my-app/MyCanvasAppPage.ts
import { Page, FrameLocator } from '@playwright/test';
export class MyCanvasAppPage {
private readonly frame: FrameLocator;
constructor(private readonly page: Page) {
this.frame = page.frameLocator('iframe[name="fullscreen-app-host"]');
}
get addButton() {
return this.frame.locator('[data-control-name="AddButton"]');
}
get gallery() {
return this.frame.locator('[data-control-name="Gallery1"]');
}
async waitForLoad(): Promise<void> {
await this.gallery
.locator('[data-control-part="gallery-item"]')
.first()
.waitFor({ state: 'visible', timeout: 60000 });
}
async clickAdd(): Promise<void> {
await this.addButton.click();
}
async getItemCount(): Promise<number> {
return this.gallery.locator('[data-control-part="gallery-item"]').count();
}
}
Vollständiges CRUD-Testbeispiel für Canvas-Apps
In diesem Beispiel werden app-Start, Katalogüberprüfung und Formularinteraktion in einer vollständigen Testsuite kombiniert.
import { test, expect, FrameLocator } from '@playwright/test';
import { AppProvider, AppType, AppLaunchMode, buildCanvasAppUrlFromEnv } from 'power-platform-playwright-toolkit';
const CANVAS_APP_URL = buildCanvasAppUrlFromEnv();
test.describe('Canvas App - Orders', () => {
let canvasFrame: FrameLocator;
test.beforeEach(async ({ page, context }) => {
const app = new AppProvider(page, context);
await app.launch({
app: 'Orders App',
type: AppType.Canvas,
mode: AppLaunchMode.Play,
skipMakerPortal: true,
directUrl: CANVAS_APP_URL,
});
canvasFrame = page.frameLocator('iframe[name="fullscreen-app-host"]');
await canvasFrame
.locator('[data-control-part="gallery-item"]')
.first()
.waitFor({ state: 'visible', timeout: 60000 });
});
test('should display orders in gallery', async () => {
const count = await canvasFrame
.locator('[data-control-part="gallery-item"]')
.count();
expect(count).toBeGreaterThan(0);
});
test('should click Add and show form', async ({ page }) => {
await canvasFrame.locator('[data-control-name="icon3"]').click();
await page.waitForTimeout(2000);
const input = canvasFrame.locator('input[type="text"]').first();
await expect(input).toBeVisible();
});
});
Ermitteln von Steuerelementnamen in Canvas-Apps
So suchen Sie die data-control-name Werte in Ihrer App:
- Öffnen Sie die App im Wiedergabemodus in einem Browser.
- Öffnen Sie Browserentwicklertools (F12).
- Verwenden Sie den Inspektor , um mit dem Mauszeiger auf Steuerelemente zu zeigen und nach
data-control-nameAttributen zu suchen.
Alternativ können Sie den Playwright MCP-Server verwenden, um einen KI-Assistenten zu bitten, das DOM zu prüfen und Selektoren für Sie zu generieren. Siehe KI-unterstützte Tests.