Skip to content
Security
Skill

/prowler-test-ui

E2E testing patterns for Prowler UI (Playwright). Trigger: When writing Playwright E2E tests under ui/tests in the Prowler UI (Prowler-specific base page/helpers, tags, flows).

From plugin
prowler
15k39 skills1 MCP

Claude Code

$ npx -y skills add prowler-cloud/prowler --skill prowler-test-ui --agent claude-code

SKILL.md

prowler-test-ui.SKILL.md
name: prowler-test-ui
description: >
  E2E testing patterns for Prowler UI (Playwright).
  Trigger: When writing Playwright E2E tests under ui/tests in the Prowler UI (Prowler-specific base page/helpers, tags, flows).
license: Apache-2.0
metadata:
  author: prowler-cloud
  version: "1.1"
  scope: [root, ui]
  auto_invoke:
    - "Writing Prowler UI E2E tests"
    - "Working with Prowler UI test helpers/pages"
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task

> **Generic Patterns**: For base Playwright patterns (Page Object Model, selectors, helpers), see the `playwright` skill. > This skill covers **Prowler-specific** conventions only.

Prowler UI Test Structure

ui/
├── playwright.base.ts            # Shared config (testDir ./tests, expect timeout 20s, CI retries 2)
├── playwright.config.ts          # Main projects + webServer (pnpm dev / pnpm start in CI)
├── playwright.registry.config.ts # Registry suite: own fixture API (:4300) and UI servers
└── tests/
    ├── base-page.ts              # abstract BasePage (shared locators/verifications)
    ├── helpers.ts                # makeSuffix, getSession, addAWSProvider, deleteProviderIfExists, TEST_CREDENTIALS...
    ├── setups/*.auth.setup.ts    # Auth setup projects -> playwright/.auth/*.json storage states
    └── {page-name}/
        ├── {page-name}-page.ts   # Page Object Model
        ├── {page-name}.spec.ts   # Tests (one spec per feature by default)
        └── {page-name}.md        # Test documentation (MANDATORY - sync with spec.ts)

Playwright Projects (`ui/playwright.config.ts`)

| Project | Specs | Depends on | |---------|-------|-----------| | `admin.auth.setup` (+ `manage-scans`, `manage-integrations`, `manage-account`, `manage-cloud-providers`, `unlimited-visibility`, `invite-and-manage-users`) | `tests/setups/*.auth.setup.ts` | - | | `sign-in-base`, `auth`, `invitation-accept`, `runtime-config` | `tests/{name}/*.spec.ts` | - (unauthenticated) | | `sign-up` | `sign-up.spec.ts` | - | | `scans`, `providers`, `invitations` | `{name}.spec.ts` | `admin.auth.setup` | | `navigation` | `tests/navigation/*.spec.ts` (Pixel 5, 390x844) | `admin.auth.setup` |

A new test folder needs a new project entry here (and in the `test:e2e*` scripts in `ui/package.json` if it should run by default). `pnpm run test:e2e` runs only `auth, sign-up, providers, invitations, scans, runtime-config, navigation`; `sign-in-base` and `invitation-accept` must be run with `--project`.

Authenticated suites reuse storage state instead of logging in:

test.use({ storageState: "playwright/.auth/admin_user.json" });

Data-dependent flows use `test.describe.serial(...)` and the `@serial` tag; clean up first (e.g. `deleteProviderIfExists`) and `test.skip(!process.env.E2E_..., "...")` when required env vars are missing. Credentials and provider identifiers come only from `E2E_*` env vars (see `docs/developer-guide/end2end-testing.mdx`).

---

MANDATORY Checklist (Create or Modify Tests)

**⚠️ ALWAYS verify BEFORE completing any E2E task:**

When CREATING new tests

  • [ ] `{page-name}-page.ts` - Page Object created/updated
  • [ ] `{page-name}.spec.ts` - Tests added with correct tags (@TEST-ID)
  • [ ] `{page-name}.md` - Documentation created with ALL test cases
  • [ ] Test IDs in `.md` match tags in `.spec.ts`

When MODIFYING existing tests

  • [ ] `{page-name}.md` MUST be updated if:
  • Test cases were added/removed
  • Test flow changed (steps)
  • Preconditions or expected results changed
  • Tags or priorities changed
  • [ ] Test IDs synchronized between `.md` and `.spec.ts`

Quick validation

# Verify .md exists for each test folder
ls ui/tests/{feature}/{feature}.md

# Verify test IDs match
grep -oE "@[A-Z-]+-E2E-[0-9]+" ui/tests/{feature}/*.spec.ts | sed 's/.*@//' | sort -u
grep -oE "\`[A-Z-]+-E2E-[0-9]+\`" ui/tests/{feature}/{feature}.md | tr -d '\`' | sort -u

> [!IMPORTANT] > ❌ An E2E change is NOT considered complete without updating the corresponding `.md` file.

---

MCP Workflow - CRITICAL

**⚠️ MANDATORY: If Playwright MCP tools are available, ALWAYS use them BEFORE creating tests.**

1. **Navigate** to target page 2. **Take snapshot** to see actual DOM structure 3. **Interact** with forms/elements to verify real flow 4. **Document actual selectors** from snapshots 5. **Only then** write test code

**Why**: Prevents tests based on assumptions. Real exploration = stable tests.

---

Wait Strategies (CRITICAL)

**⚠️ NEVER use `networkidle` - it causes flaky tests!**

| Strategy | Use Case | |----------|----------| | ❌ `networkidle` | NEVER - flaky with polling/WebSockets | | ⚠️ `load` | Only when absolutely necessary | | ✅ `expect(element).toBeVisible()` | PREFERRED - wait for specific UI state | | ✅ `page.waitForURL()` | Wait for navigation | | ✅ `pageObject.verifyPageLoaded()` | BEST - encapsulated verification |

**GOOD:**

await homePage.verifyPageLoaded();
await expect(page).toHaveURL("/dashboard");
await expect(page.getByRole("heading", { name: "Overview" })).toBeVisible();

**BAD:**

await page.waitForLoadState("networkidle"); // ❌ FLAKY
await page.waitForTimeout(2000);            // ❌ ARBITRARY WAIT

---

Prowler Base Page (`ui/tests/base-page.ts`)

`BasePage` is `abstract`; extend it and reuse its helpers instead of re-implementing them:

| Member | Purpose | |--------|---------| | `title`, `loadingIndicator`, `themeToggle` | Shared locators | | `goto(url)`, `gotoFresh(url)` (`waitUntil: "commit"`, after clearing cookies), `refresh()`, `goBack()` | Navigation | | `skipFirstRunRedirect()` | Prevents the empty-tenant redirect to the add-provider wizard | | `verifyElementVisible/NotVisible/Text/ContainsText`, `verifyPageTitle`, `verifyNoErrors`, `verifyKeyboardNavigation`, `verifyAriaLabels` | Verifications | | `waitForElement`, `waitForElementToDisappear`, `waitForUrl` | Waits (5s default) |

import { Pa
Read more
@prowler-cloud
Ships withprowler

Prowler is the world’s most widely used Open-Source Cloud Security Platform that automates security and compliance across any cloud environment.

15k39 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
15.2k
Star history of prowler-cloud/prowler on GitHub, a chart by star-history.com

Other skills on prowler.

ai-sdk-5

ai-sdk-5

Vercel AI SDK patterns for the installed major (ui/package.json: `ai` 6.x, `@ai-sdk/react` 3.x). The skill name is historical;…

django-drf

django-drf

Django REST Framework patterns. Trigger: When implementing generic DRF APIs (ViewSets, serializers, routers, permissions,…

gh-aw

gh-aw

Create and maintain GitHub Agentic Workflows (gh-aw) for Prowler. Trigger: When creating agentic workflows, modifying gh-aw…

jsonapi

jsonapi

Strict JSON:API v1.1 specification compliance. Trigger: When creating or modifying API endpoints, reviewing API responses, or…

More skills from other plugins.

api-security

api-security

Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…

@zhaoxuya520@zhaoxuya520Install Skill
nemoclaw-user-guide

nemoclaw-user-guide

Find official NemoClaw documentation for installation, configuration, operation, or troubleshooting. Also handles requested docs…

nemoclaw10d23k
@nvidia@nvidiaInstall Skill

Questions about prowler-test-ui.

Which coding agents can use prowler-test-ui?
prowler-test-ui installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.