Web Application Testing
anthropics/skills
Tests local web applications with Python Playwright scripts, checking frontend behavior, capturing screenshots and reading browser console logs.
Guides writing and maintaining Playwright E2E tests for the bootc Podman Desktop extension.
$ npx skills add podman-desktop/extension-bootc --skill playwright-testing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install podman-desktop/extension-bootc playwright-testing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/podman-desktop/extension-bootc.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/playwright-testing .claude/skills/playwright-testing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "playwright-testing" agent skill from https://github.com/podman-desktop/extension-bootc/tree/main/.agents/skills/playwright-testing into .claude/skills/playwright-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "playwright-testing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/podman-desktop/extension-bootc/tree/main/.agents/skills/playwright-testingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add podman-desktop/extension-bootc --skill playwright-testing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install podman-desktop/extension-bootc playwright-testing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/podman-desktop/extension-bootc.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/playwright-testing .agents/skills/playwright-testing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "playwright-testing" agent skill from https://github.com/podman-desktop/extension-bootc/tree/main/.agents/skills/playwright-testing into .agents/skills/playwright-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "playwright-testing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add podman-desktop/extension-bootc --skill playwright-testing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install podman-desktop/extension-bootc playwright-testing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/podman-desktop/extension-bootc.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/playwright-testing .cursor/skills/playwright-testing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "playwright-testing" agent skill from https://github.com/podman-desktop/extension-bootc/tree/main/.agents/skills/playwright-testing into .cursor/skills/playwright-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "playwright-testing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/podman-desktop/extension-bootc.git --path .agents/skills/playwright-testing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add podman-desktop/extension-bootc --skill playwright-testing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install podman-desktop/extension-bootc playwright-testing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/podman-desktop/extension-bootc.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/playwright-testing .gemini/skills/playwright-testing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "playwright-testing" agent skill from https://github.com/podman-desktop/extension-bootc/tree/main/.agents/skills/playwright-testing into .gemini/skills/playwright-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "playwright-testing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install podman-desktop/extension-bootc playwright-testingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add podman-desktop/extension-bootc --skill playwright-testing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/podman-desktop/extension-bootc.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/playwright-testing .github/skills/playwright-testing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "playwright-testing" agent skill from https://github.com/podman-desktop/extension-bootc/tree/main/.agents/skills/playwright-testing into .github/skills/playwright-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "playwright-testing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add podman-desktop/extension-bootc --skill playwright-testing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install podman-desktop/extension-bootc playwright-testing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/podman-desktop/extension-bootc.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/playwright-testing .opencode/skills/playwright-testing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "playwright-testing" agent skill from https://github.com/podman-desktop/extension-bootc/tree/main/.agents/skills/playwright-testing into .opencode/skills/playwright-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "playwright-testing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
playwright-testingGuides writing and maintaining Playwright E2E tests for the bootc Podman Desktop extension.
Playwright Testing is an agent skill from podman-desktop/extension-bootc. Guides writing and maintaining Playwright E2E tests for the bootc Podman Desktop extension. Covers the webview-aware test framework, extension lifecycle management, Page Object Models, and spec file patterns. Triggers when creating or modifying E2E spec files, building page object models, debugging Playwright failures, or asking about the test framework.
Its SKILL.md is about 2.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering Browser testing and End-to-end testing. It works with Playwright. The repository describes itself as: Support for bootable OS containers (bootc) and generating disk images. The licence is Apache-2.0.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 4230bcf. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pnpmFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use pnpm, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Playwright Testing loads about 2.6k tokens when it runs. Until then it costs about 94 tokens; SKILL.md has 585 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from podman-desktop/extension-bootc at commit 4230bcf, republished under its Apache-2.0 licence (© podman-desktop). 585 words, ~2,632 tokens.
.claude/skills/playwright-testing/SKILL.md (or your agent's skills folder).This extension runs inside Podman Desktop as a webview. E2E tests launch Podman Desktop via Electron, install the extension from an OCI image, then interact with the extension's webview UI. This is fundamentally different from testing Podman Desktop itself — every test must handle the webview boundary.
Tests live in tests/playwright/. Key directories:
src/*.spec.ts — test spec filessrc/model/ — Page Object Models (webview-aware, take both page and webview)src/utility/ — test helpers (webview handling, extension lifecycle, cleanup)# See the full structure
find tests/playwright/src -type f -name '*.ts' | sortExtensions render in a webview (a separate Electron BrowserWindow). You must get BOTH the main page and the webview page to interact with extension UI:
import { handleWebview } from './utility/bootc-test-utils';
// Returns [mainPage, webViewPage] — use webViewPage for extension UI locators
const [page, webview] = await handleWebview(runner);How handleWebview() works:
runner.getWindows()[mainPage, webViewPage]All extension Page Object Models take both page and webview parameters.
Use webview for extension-specific locators, page for Podman Desktop dialogs.
Import test, expect, and utilities from @podman-desktop/tests-playwright:
import {
test,
expect as playExpect,
RunnerOptions,
removeFolderIfExists,
waitForPodmanMachineStartup,
NavigationBar,
waitUntil,
} from '@podman-desktop/tests-playwright';
import type { Page } from '@playwright/test';Import extension-specific models and utilities locally:
import { BootcNavigationBar } from './model/bootc-navigationbar';
import {
handleWebview,
installBootcExtensionIfNeeded,
removeBootcExtensionIfNeeded,
cleanupRawVideoFiles,
} from './utility/bootc-test-utils';
import { markTestFileComplete } from './utility/extension-lifecycle';The extension is installed once before the first spec file and removed after the last one completes. This is managed by a file-based counter:
global-setup.ts counts spec files and writes the total to a temp fileafterAll calls markTestFileComplete(fileId) which decrementsextension-reporter.ts handles fully-skipped files (their afterAll never runs)Every spec file MUST include this in its outer test.afterAll:
import { fileURLToPath } from 'node:url';
import { markTestFileComplete } from './utility/extension-lifecycle';
const __filename = fileURLToPath(import.meta.url);
test.afterAll(async ({ navigationBar }) => {
if (markTestFileComplete(__filename)) {
await removeBootcExtensionIfNeeded(navigationBar);
}
});Unlike upstream Podman Desktop POMs (which take only page), bootc POMs take
both page and webview:
export class BootcDashboardPage {
readonly page: Page;
readonly webview: Page;
readonly heading: Locator;
constructor(page: Page, webview: Page) {
this.page = page;
this.webview = webview;
// Extension UI locators use webview
this.heading = webview.getByText('Welcome to bootable containers');
}
}POMs are in tests/playwright/src/model/. Read them for current methods and locators:
ls tests/playwright/src/model/The navigation bar POM navigates within the extension's webview. Other POMs wrap specific pages (build, dashboard, disk images, examples, etc.).
Build completion shows a dialog on the main page (not webview). Always
use this.page (not this.webview) for Podman Desktop dialogs.
import type { Page } from '@playwright/test';
import {
removeFolderIfExists,
waitForPodmanMachineStartup,
test,
expect as playExpect,
RunnerOptions,
isLinux,
} from '@podman-desktop/tests-playwright';
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';
import { BootcNavigationBar } from './model/bootc-navigationbar';
import {
removeBootcExtensionIfNeeded,
handleWebview,
installBootcExtensionIfNeeded,
cleanupRawVideoFiles,
} from './utility/bootc-test-utils';
import { markTestFileComplete } from './utility/extension-lifecycle';
let page: Page;
let webview: Page;
const __filename = fileURLToPath(import.meta.url);
test.use({
runnerOptions: new RunnerOptions({
customFolder: 'bootc-tests-pd',
customOutputFolder: 'tests/output',
autoUpdate: false,
autoCheckUpdates: false,
}),
});
test.beforeAll(async ({ runner, welcomePage, page }) => {
await removeFolderIfExists('tests/output/images');
runner.setVideoAndTraceName('my-feature-name');
await welcomePage.handleWelcomePage(true);
await waitForPodmanMachineStartup(page);
});
test.afterAll(async ({ runner }) => {
test.setTimeout(320_000);
const videoAndTraceName = runner.getVideoAndTraceName();
try {
await removeFolderIfExists('tests/output/images');
} finally {
await runner.close(200_000);
cleanupRawVideoFiles('tests/output', videoAndTraceName);
}
});
test.describe('My Feature', () => {
test.skip(isLinux); // building bootable images not supported on Linux
test.beforeAll(async ({ navigationBar }) => {
test.setTimeout(200_000);
await installBootcExtensionIfNeeded(navigationBar);
});
test.describe.serial('Feature flow', () => {
test('Navigate to extension', async ({ runner }) => {
test.setTimeout(60_000);
[page, webview] = await handleWebview(runner);
const bootcNav = new BootcNavigationBar(page, webview);
const dashboard = await bootcNav.openBootcDashboard();
await playExpect(dashboard.heading).toBeVisible();
});
test('Perform action', async ({ runner }) => {
test.setTimeout(300_000);
[page, webview] = await handleWebview(runner);
// ... test body
});
});
test.afterAll(async ({ navigationBar }) => {
if (markTestFileComplete(__filename)) {
await removeBootcExtensionIfNeeded(navigationBar);
}
});
});handleWebview(runner) at the start of each test that interacts with the extensiontest.describe.serial() — tests share Electron state and must run in ordertest.skip(isLinux) — building bootable images is not supported on LinuxcleanupRawVideoFiles() in afterAll to handle orphaned webview recordingscustomFolder: 'bootc-tests-pd' — all specs use this folder name for consistent profile isolationimport { isLinux, isMac, isWindows } from '@podman-desktop/tests-playwright';
test.skip(isLinux); // no bootable image building on Linux
test.skip(isMac && arch === ArchitectureType.AMD64, 'amd64 not supported on macOS');
test.skip(isWindows && arch === ArchitectureType.ARM64, 'arm64 not supported on Windows');The extension is installed from an OCI image. The URL is configurable:
// Default: ghcr.io/podman-desktop/extension-bootc:next
// Override: set OCI_IMAGE env var
const extensionURL = process.env.OCI_IMAGE ?? 'ghcr.io/podman-desktop/extension-bootc:next';Set SKIP_INSTALLATION=true to skip install/remove (when testing with a pre-installed extension).
# From the repo root
pnpm test:e2e
# From tests/playwright directly
pnpm --dir tests/playwright test:e2e
# Run a single spec
pnpm --dir tests/playwright exec playwright test src/bootc-dashboard.spec.ts
# With custom extension image
OCI_IMAGE=ghcr.io/podman-desktop/extension-bootc:v1.15.0 \
pnpm --dir tests/playwright exec playwright test src/
# Skip extension install/remove (pre-installed)
SKIP_INSTALLATION=true \
pnpm --dir tests/playwright exec playwright test src/| Variable | Purpose |
|---|---|
PODMAN_DESKTOP_BINARY | Path to Podman Desktop binary |
PODMAN_DESKTOP_ARGS | Path to Podman Desktop repo (dev mode) |
OCI_IMAGE | Extension OCI image URL (default: next tag) |
SKIP_INSTALLATION | Skip extension install/remove lifecycle |
BUILD_ISO_IMAGE | Enable ISO build tests (disabled by default) |
# List all spec files and their test descriptions
ls tests/playwright/src/*.spec.ts
grep -h "test.describe\|test('" tests/playwright/src/*.spec.tsIf handleWebview() times out waiting for the second window, the extension may
not have loaded. Check that the extension is installed and in ACTIVE state.
BootcPage.refreshPageWhileInCreatingState() navigates away and back to force
a UI refresh. The waitUntil wrapper retries until the state changes.
Webview windows generate orphaned raw video files (32-char hex names).
cleanupRawVideoFiles() handles this — always call it in afterAll.
Read the actual Page Object Models to see current locators and methods:
# List all POMs
ls tests/playwright/src/model/
# Read a specific POM for its locators and methods
cat tests/playwright/src/model/bootc-page.ts
# List all test utilities
cat tests/playwright/src/utility/bootc-test-utils.ts© podman-desktop, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/playwright-testing of podman-desktop/extension-bootc.
Open the folder on GitHubat commit 4230bcf
Playwright Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Playwright Testing this skillpodman-desktop/extension-bootc | 474 | — | ~2.6k | Automated safety check: Pass | Apache-2.0 | |
| Web Application Testinganthropics/skills | 180k | 51 repos | ~966 | Automated safety check: Pass | Apache-2.0 | |
| playwright-cli Browser Automationgithub/gh-aw | 5.4k | 24 repos | ~2.8k | Automated safety check: Pass | MIT | |
| Write and Verify Playwright Testsappsmithorg/appsmith | 41k | — | ~2.9k | Automated safety check: Notes | Apache-2.0 | |
| Cucumber and Playwright E2E Testslanggenius/dify | 158k | — | ~682 | Automated safety check: Pass | Custom licence | |
| E2E Testinglangflow-ai/langflow | 156k | — | ~3.3k | Automated safety check: Pass | MIT |
anthropics/skills
Tests local web applications with Python Playwright scripts, checking frontend behavior, capturing screenshots and reading browser console logs.
github/gh-aw
Drives a real browser from the command line with playwright-cli to open pages, interact, mock requests, save state and work with Playwright tests.
appsmithorg/appsmith
Writes a Playwright end-to-end test from a prompt, runs it against a live Appsmith deployment and retries with fixes up to three times until it passes.
langgenius/dify
Guides changes and reviews of the Cucumber and Playwright end-to-end suite under `e2e/`: feature files, step definitions, support code, tags, locators and assertions.
langflow-ai/langflow
Write and review Playwright E2E tests for Langflow. An agent skill from langflow-ai/langflow.
handsontable/handsontable
Guides writing and changing Playwright end-to-end tests for Handsontable using page objects, data-testid hooks and deterministic waits.
podman-desktop/extension-bootc
Guides backend development with @podman-desktop/api and the bootc extension's RPC system.
podman-desktop/extension-bootc
Guides end-to-end feature development in the bootc Podman Desktop extension.
podman-desktop/extension-bootc
Guides designing and building Svelte 5 UI components in the bootc extension.
podman-desktop/extension-bootc
Guides writing and maintaining Vitest unit tests for the bootc extension's backend, frontend, and shared packages.
Works with
Categories
Guides writing and maintaining Playwright E2E tests for the bootc Podman Desktop extension. Playwright Testing is an agent skill from podman-desktop/extension-bootc. Guides writing and maintaining Playwright E2E tests for the bootc Podman Desktop extension.
Playwright Testing fits situations like: modifying E2E spec files; building page object models; debugging Playwright failures; asking about the test framework.
Run `npx skills add podman-desktop/extension-bootc --skill playwright-testing -a claude-code`. Or copy the skill folder (.agents/skills/playwright-testing in podman-desktop/extension-bootc) into .claude/skills/playwright-testing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add podman-desktop/extension-bootc --skill playwright-testing -a codex`. Or copy the skill folder (.agents/skills/playwright-testing in podman-desktop/extension-bootc) into .agents/skills/playwright-testing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add podman-desktop/extension-bootc --skill playwright-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/playwright-testing, .gemini/skills/playwright-testing, .github/skills/playwright-testing and .opencode/skills/playwright-testing in your project.
Going by SKILL.md and its folder, Playwright Testing needs the command-line tools its instructions call (pnpm).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Playwright Testing is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.6k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Playwright Testing: Web Application Testing (anthropics/skills, 180k stars), playwright-cli Browser Automation (github/gh-aw, 5.4k stars), Write and Verify Playwright Tests (appsmithorg/appsmith, 41k stars) and Cucumber and Playwright E2E Tests (langgenius/dify, 158k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
podman-desktop (a GitHub organization) maintains it in podman-desktop/extension-bootc, which has 474 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on October 8, 2026.
Source: podman-desktop/extension-bootc on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.