diff --git a/packages/dashboard/playwright/tests.json b/packages/dashboard/playwright/tests.json new file mode 100644 index 000000000..3415bb6b6 --- /dev/null +++ b/packages/dashboard/playwright/tests.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://metabuilder.dev/schemas/package-playwright.schema.json", + "package": "dashboard", + "version": "1.0.0", + "description": "E2E tests for dashboard package - validates user dashboard, widgets, and data display", + "tests": [ + { + "name": "should load dashboard for authenticated user", + "tags": ["@smoke", "@dashboard"], + "steps": [ + { + "action": "navigate", + "url": "/dashboard" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Verify dashboard container", + "action": "expect", + "selector": ".dashboard-container", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should display user widgets", + "tags": ["@ui", "@widgets"], + "steps": [ + { + "action": "navigate", + "url": "/dashboard" + }, + { + "action": "waitForLoadState", + "state": "networkidle" + }, + { + "description": "Check widgets grid exists", + "action": "expect", + "selector": ".dashboard-widgets", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + } + ] +} diff --git a/packages/ui_home/playwright/README.md b/packages/ui_home/playwright/README.md new file mode 100644 index 000000000..45673386c --- /dev/null +++ b/packages/ui_home/playwright/README.md @@ -0,0 +1,85 @@ +# Playwright Tests for ui_home Package + +This folder contains declarative Playwright test definitions for the `ui_home` package, following MetaBuilder's data-driven architecture. + +## Structure + +- **tests.json** - Main test suite with JSON-defined E2E tests +- **metadata.json** - Test suite metadata and coverage information + +## Test Coverage + +The test suite validates: + +- ✅ Home page loads successfully (HTTP 200) +- ✅ Hero section with title and CTAs +- ✅ Six Levels of Power feature cards +- ✅ Navigation bar with Sign In/Admin buttons +- ✅ About MetaBuilder section +- ✅ Contact form with all fields +- ✅ No critical console errors +- ✅ Anchor link navigation + +## Running Tests + +### From Package Test Definition +```bash +# Generate .spec.ts from tests.json (future implementation) +npm run test:generate -- --package ui_home + +# Run generated tests +npm run test:e2e -- --grep @ui_home +``` + +### Run Existing E2E Tests +```bash +cd /path/to/metabuilder +npm run test:e2e -- e2e/smoke.spec.ts +``` + +## Test Schema + +Tests follow the `playwright.schema.json` schema: +- **Declarative steps**: All test actions defined in JSON +- **Selector strategies**: Support for CSS, role-based, text, and test-id selectors +- **Assertions**: Playwright expect matchers as data +- **Fixtures**: Reusable test data +- **Tags**: Filter tests by categories (@smoke, @critical, etc.) + +## Example Test + +```json +{ + "name": "should display hero section with title and CTAs", + "tags": ["@smoke", "@ui"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "expect", + "selector": ".hero-title", + "assertion": { + "matcher": "toBeVisible" + } + } + ] +} +``` + +## Meta Architecture Benefits + +- **Data-driven**: Tests are configuration, not code +- **Package-scoped**: Each package owns its test definitions +- **Schema-validated**: Tests conform to JSON schema +- **Auto-discoverable**: Test loader can find all `playwright/tests.json` files +- **Maintainable**: Update tests without touching TypeScript + +## Future Enhancements + +1. **Test Generator**: Convert `tests.json` → `.spec.ts` automatically +2. **Visual Testing**: Add screenshot comparison tests +3. **Performance**: Add lighthouse/performance assertions +4. **Accessibility**: WCAG/aria validation tests +5. **Cross-browser**: Multi-browser test matrix from single JSON diff --git a/packages/ui_home/playwright/metadata.json b/packages/ui_home/playwright/metadata.json new file mode 100644 index 000000000..1715b2308 --- /dev/null +++ b/packages/ui_home/playwright/metadata.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://metabuilder.dev/schemas/package-metadata.schema.json", + "folder": "playwright", + "description": "Playwright E2E test definitions for ui_home package", + "version": "1.0.0", + "files": { + "tests.json": "Main test suite with declarative test definitions" + }, + "testRunner": "playwright", + "coverage": { + "components": ["home_page", "hero_section", "features_section", "about_section", "contact_section"], + "interactions": ["navigation", "forms", "anchors"], + "viewports": ["desktop", "mobile"] + }, + "tags": ["@smoke", "@ui", "@critical", "@navigation", "@form", "@interaction", "@features", "@content"] +} diff --git a/packages/ui_home/playwright/tests.json b/packages/ui_home/playwright/tests.json new file mode 100644 index 000000000..799dddf18 --- /dev/null +++ b/packages/ui_home/playwright/tests.json @@ -0,0 +1,360 @@ +{ + "$schema": "https://metabuilder.dev/schemas/package-playwright.schema.json", + "package": "ui_home", + "version": "1.0.0", + "description": "E2E tests for ui_home package - validates landing page rendering, navigation, and interactions", + "baseURL": "http://localhost:3000", + "setup": { + "beforeAll": [ + { + "action": "seed", + "description": "Seed database with ui_home package data" + } + ] + }, + "fixtures": { + "heroTitle": "Build Anything, Visually", + "heroSubtitle": "A 6-level meta-architecture for creating entire applications through visual workflows, schema editors, and embedded scripting. No code required.", + "featuresSectionTitle": "Six Levels of Power", + "expectedFeatureCards": 6, + "aboutTitle": "About MetaBuilder", + "contactTitle": "Get in Touch" + }, + "tests": [ + { + "name": "should load home page successfully", + "description": "Verifies the home page loads with HTTP 200 and displays content", + "tags": ["@smoke", "@critical"], + "timeout": 10000, + "steps": [ + { + "description": "Navigate to root path", + "action": "navigate", + "url": "/" + }, + { + "description": "Wait for DOM to be ready", + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Verify page has content", + "action": "expect", + "selector": "body", + "assertion": { + "matcher": "toContainText", + "expected": "MetaBuilder" + } + } + ] + }, + { + "name": "should display hero section with title and CTAs", + "description": "Validates hero section renders with gradient title and action buttons", + "tags": ["@smoke", "@ui"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Check hero title is visible", + "action": "expect", + "selector": ".hero-title", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify hero title text", + "action": "expect", + "selector": ".hero-title", + "assertion": { + "matcher": "toContainText", + "expected": "Build Anything" + } + }, + { + "description": "Check Get Started button exists", + "action": "expect", + "role": "button", + "text": "Get Started", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Check Watch Demo button exists", + "action": "expect", + "role": "button", + "text": "Watch Demo", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should display six level feature cards", + "description": "Validates the Six Levels of Power feature grid with all 6 level cards", + "tags": ["@smoke", "@ui", "@features"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "networkidle" + }, + { + "description": "Verify features section header", + "action": "expect", + "selector": ".features-header", + "assertion": { + "matcher": "toContainText", + "expected": "Six Levels of Power" + } + }, + { + "description": "Check features grid is visible", + "action": "expect", + "selector": ".features-grid", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify exactly 6 feature cards", + "action": "expect", + "selector": ".feature-card", + "assertion": { + "matcher": "toHaveCount", + "expected": 6 + } + }, + { + "description": "Check Level 1 card is visible", + "action": "expect", + "selector": ".feature-card--level1", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Check Level 6 (Super God) card is visible", + "action": "expect", + "selector": ".feature-card--level6", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should display navigation with Sign In and Admin buttons", + "description": "Validates navigation bar with authentication links", + "tags": ["@smoke", "@navigation"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Check navigation bar exists", + "action": "expect", + "selector": ".landing-nav", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify Sign In button", + "action": "expect", + "role": "button", + "text": "Sign In", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify Admin button", + "action": "expect", + "role": "button", + "text": "Admin", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should display about section", + "description": "Validates About MetaBuilder section content", + "tags": ["@ui", "@content"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Check about section is visible", + "action": "expect", + "selector": ".about-section", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify about title", + "action": "expect", + "selector": ".about-title", + "assertion": { + "matcher": "toContainText", + "expected": "About MetaBuilder" + } + } + ] + }, + { + "name": "should display contact form", + "description": "Validates contact section with form fields", + "tags": ["@ui", "@form"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Check contact section is visible", + "action": "expect", + "selector": ".contact-section", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify contact title", + "action": "expect", + "selector": ".contact-title", + "assertion": { + "matcher": "toContainText", + "expected": "Get in Touch" + } + }, + { + "description": "Check contact form exists", + "action": "expect", + "selector": ".contact-form", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify name field", + "action": "expect", + "selector": ".contact-field--name", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify email field", + "action": "expect", + "selector": ".contact-field--email", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify message field", + "action": "expect", + "selector": ".contact-field--message", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify submit button", + "action": "expect", + "selector": ".contact-submit", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should have no critical console errors", + "description": "Ensures page loads without JavaScript errors", + "tags": ["@smoke", "@critical"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "networkidle" + }, + { + "description": "Page should load successfully without errors", + "action": "expect", + "selector": "body", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should navigate to sections via anchor links", + "description": "Tests smooth scrolling to sections via navigation links", + "tags": ["@interaction", "@navigation"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Click Features link", + "action": "click", + "selector": "a[href='#features']" + }, + { + "description": "Wait for scroll", + "action": "wait", + "timeout": 500 + }, + { + "description": "Features section should be in viewport", + "action": "expect", + "selector": "#features", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + } + ] +} diff --git a/packages/user_manager/playwright/tests.json b/packages/user_manager/playwright/tests.json new file mode 100644 index 000000000..4332d248a --- /dev/null +++ b/packages/user_manager/playwright/tests.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://metabuilder.dev/schemas/package-playwright.schema.json", + "package": "user_manager", + "version": "1.0.0", + "description": "E2E tests for user_manager package - validates user CRUD operations and admin workflows", + "tests": [ + { + "name": "should display user list", + "tags": ["@smoke", "@admin"], + "steps": [ + { + "action": "navigate", + "url": "/admin/users" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Verify user table", + "action": "expect", + "selector": ".user-table", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should create new user", + "tags": ["@crud", "@admin"], + "steps": [ + { + "action": "navigate", + "url": "/admin/users" + }, + { + "action": "click", + "role": "button", + "text": "Add User" + }, + { + "action": "waitForSelector", + "selector": ".user-form" + }, + { + "description": "Fill username", + "action": "fill", + "selector": "input[name='username']", + "value": "testuser" + }, + { + "description": "Fill email", + "action": "fill", + "selector": "input[name='email']", + "value": "test@example.com" + }, + { + "action": "click", + "role": "button", + "text": "Save" + }, + { + "description": "Verify success message", + "action": "expect", + "text": "User created successfully", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + } + ] +} diff --git a/schemas/package-schemas/PLAYWRIGHT_SCHEMA_README.md b/schemas/package-schemas/PLAYWRIGHT_SCHEMA_README.md new file mode 100644 index 000000000..099bab38b --- /dev/null +++ b/schemas/package-schemas/PLAYWRIGHT_SCHEMA_README.md @@ -0,0 +1,273 @@ +# Playwright Test Schema + +This schema defines declarative Playwright E2E tests for MetaBuilder packages, following the data-driven architecture principle. + +## Purpose + +Enable packages to define end-to-end tests as JSON data rather than TypeScript code, making tests: +- **Data-driven**: Tests are configuration +- **Package-scoped**: Each package owns its test definitions +- **Auto-discoverable**: Test loaders can find all `playwright/tests.json` files +- **Schema-validated**: Tests conform to JSON schema +- **Maintainable**: Update tests without touching code + +## Schema Location + +- **File**: `schemas/package-schemas/playwright.schema.json` +- **$id**: `https://metabuilder.dev/schemas/package-playwright.schema.json` + +## Package Structure + +``` +packages/{package_name}/ +├── playwright/ +│ ├── tests.json # Main test definitions (required) +│ ├── metadata.json # Test suite metadata (optional) +│ └── README.md # Package-specific test docs (optional) +``` + +## Test Definition Format + +```json +{ + "$schema": "https://metabuilder.dev/schemas/package-playwright.schema.json", + "package": "ui_home", + "version": "1.0.0", + "description": "E2E tests for ui_home package", + "tests": [ + { + "name": "should load home page successfully", + "tags": ["@smoke", "@critical"], + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "action": "expect", + "selector": "body", + "assertion": { + "matcher": "toContainText", + "expected": "MetaBuilder" + } + } + ] + } + ] +} +``` + +## Supported Actions + +### Navigation +- `navigate` - Navigate to URL +- `waitForNavigation` - Wait for navigation event +- `waitForLoadState` - Wait for load/domcontentloaded/networkidle + +### Interactions +- `click` - Click element +- `dblclick` - Double-click element +- `fill` - Fill input field +- `type` - Type text (simulates keyboard) +- `select` - Select dropdown option +- `check` / `uncheck` - Toggle checkboxes +- `hover` - Hover over element +- `focus` - Focus element +- `press` - Press keyboard key + +### Assertions +- `expect` - Make assertion with Playwright matchers + +### Utilities +- `wait` - Wait for timeout +- `waitForSelector` - Wait for element +- `screenshot` - Capture screenshot +- `evaluate` - Run JavaScript in browser + +## Selector Strategies + +Multiple selector types supported: + +```json +{ + "selector": ".hero-title" // CSS selector +} +``` + +```json +{ + "role": "button", // ARIA role + "text": "Get Started" +} +``` + +```json +{ + "text": "Build Anything" // Text content +} +``` + +```json +{ + "label": "Email" // Form label +} +``` + +```json +{ + "testId": "submit-button" // data-testid attribute +} +``` + +## Assertion Matchers + +All Playwright expect matchers supported: + +- **Visibility**: `toBeVisible`, `toBeHidden` +- **State**: `toBeEnabled`, `toBeDisabled`, `toBeChecked`, `toBeFocused` +- **Content**: `toHaveText`, `toContainText`, `toBeEmpty` +- **Values**: `toHaveValue`, `toHaveAttribute`, `toHaveClass`, `toHaveCSS` +- **Count**: `toHaveCount` +- **URL/Title**: `toHaveURL`, `toHaveTitle` +- **Comparison**: `toEqual`, `toContain`, `toBeGreaterThan`, `toBeLessThan` + +Use `not: true` to negate assertions: + +```json +{ + "action": "expect", + "selector": ".error-message", + "assertion": { + "matcher": "toBeVisible", + "not": true + } +} +``` + +## Test Tags + +Use tags to organize and filter tests: + +- `@smoke` - Critical smoke tests +- `@critical` - High-priority tests +- `@ui` - UI interaction tests +- `@navigation` - Navigation tests +- `@form` - Form interaction tests +- `@crud` - Create/Read/Update/Delete tests +- `@admin` - Admin-only tests +- `@slow` - Slower-running tests + +Run tests by tag: +```bash +npm run test:e2e -- --grep @smoke +npm run test:e2e -- --grep @ui +``` + +## Setup Hooks + +Define setup/teardown at test suite level: + +```json +{ + "setup": { + "beforeAll": [ + { "action": "seed", "description": "Seed database" } + ], + "beforeEach": [ + { "action": "navigate", "url": "/" } + ], + "afterEach": [ + { "action": "screenshot", "path": "test-results/{test-name}.png" } + ], + "afterAll": [ + { "action": "custom", "script": "cleanup" } + ] + } +} +``` + +## Fixtures + +Define reusable test data: + +```json +{ + "fixtures": { + "testUser": { + "username": "testuser", + "email": "test@example.com", + "password": "test123" + }, + "heroTitle": "Build Anything, Visually" + } +} +``` + +Reference fixtures in tests: +```json +{ + "action": "fill", + "selector": "input[name='username']", + "value": "{{fixtures.testUser.username}}" +} +``` + +## Test Configuration + +Per-test configuration: + +```json +{ + "name": "slow integration test", + "timeout": 30000, // 30 second timeout + "retries": 2, // Retry twice on failure + "skip": false, // Skip this test + "only": false // Run only this test +} +``` + +## Example: Complete Test Suite + +See `packages/ui_home/playwright/tests.json` for a complete example with: +- 8 declarative tests +- Multiple selector strategies +- Various assertion types +- Smoke, UI, and interaction tests +- Navigation and form testing + +## Future Enhancements + +1. **Test Generator**: Auto-generate `.spec.ts` from `tests.json` +2. **Visual Regression**: Screenshot comparison tests +3. **Performance**: Lighthouse/web vitals assertions +4. **Accessibility**: WCAG/ARIA validation +5. **API Mocking**: Declarative API mock definitions +6. **Cross-browser**: Multi-browser matrix from single JSON + +## Related Schemas + +- `storybook_schema.json` - Storybook story definitions +- `tests_schema.json` - Unit test definitions +- `component.schema.json` - Component definitions + +## Validation + +Validate test files: +```bash +cd schemas/package-schemas +./schema_validator.sh playwright.schema.json ../../packages/ui_home/playwright/tests.json +``` + +## Benefits of Data-Driven Tests + +1. **95% Configuration Rule**: Tests are data, not code +2. **Package Ownership**: Each package defines its own tests +3. **Schema Validation**: Catch errors before runtime +4. **Auto-Discovery**: Test runners can find all package tests +5. **Consistency**: Same structure across all packages +6. **Maintainability**: Change tests without TypeScript knowledge +7. **Meta Architecture**: Tests themselves are abstract/declarative diff --git a/schemas/package-schemas/playwright.schema.json b/schemas/package-schemas/playwright.schema.json new file mode 100644 index 000000000..5cf02d175 --- /dev/null +++ b/schemas/package-schemas/playwright.schema.json @@ -0,0 +1,380 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://metabuilder.dev/schemas/package-playwright.schema.json", + "title": "Package Playwright Test Configuration", + "description": "Playwright E2E test configuration for MetaBuilder packages - defines test scenarios, assertions, and page interactions", + "type": "object", + "required": ["$schema", "tests"], + "properties": { + "$schema": { + "type": "string", + "description": "JSON Schema reference", + "const": "https://metabuilder.dev/schemas/package-playwright.schema.json" + }, + "package": { + "type": "string", + "description": "Package identifier", + "pattern": "^[a-z0-9_]+$" + }, + "version": { + "type": "string", + "description": "Schema version", + "default": "1.0.0" + }, + "description": { + "type": "string", + "description": "Test suite description" + }, + "baseURL": { + "type": "string", + "description": "Base URL for tests (defaults to playwright config)", + "format": "uri" + }, + "setup": { + "type": "object", + "description": "Global test setup configuration", + "properties": { + "beforeAll": { + "type": "array", + "description": "Steps to run once before all tests", + "items": { "$ref": "#/definitions/setupStep" } + }, + "beforeEach": { + "type": "array", + "description": "Steps to run before each test", + "items": { "$ref": "#/definitions/setupStep" } + }, + "afterEach": { + "type": "array", + "description": "Steps to run after each test", + "items": { "$ref": "#/definitions/setupStep" } + }, + "afterAll": { + "type": "array", + "description": "Steps to run once after all tests", + "items": { "$ref": "#/definitions/setupStep" } + } + } + }, + "fixtures": { + "type": "object", + "description": "Test fixtures - reusable test data", + "additionalProperties": { + "type": "object", + "description": "Fixture data" + } + }, + "tests": { + "type": "array", + "description": "Test definitions", + "items": { "$ref": "#/definitions/test" } + } + }, + "definitions": { + "setupStep": { + "type": "object", + "required": ["action"], + "properties": { + "action": { + "type": "string", + "description": "Action to perform", + "enum": ["navigate", "click", "fill", "select", "wait", "eval", "mock", "seed", "custom"] + }, + "url": { + "type": "string", + "description": "URL for navigate action" + }, + "selector": { + "type": "string", + "description": "Element selector" + }, + "value": { + "description": "Value for fill/select actions" + }, + "script": { + "type": "string", + "description": "JavaScript code to evaluate" + }, + "timeout": { + "type": "number", + "description": "Timeout in milliseconds", + "minimum": 0 + } + } + }, + "test": { + "type": "object", + "required": ["name", "steps"], + "properties": { + "name": { + "type": "string", + "description": "Test name", + "minLength": 1 + }, + "description": { + "type": "string", + "description": "Detailed test description" + }, + "skip": { + "type": "boolean", + "description": "Skip this test", + "default": false + }, + "only": { + "type": "boolean", + "description": "Run only this test", + "default": false + }, + "timeout": { + "type": "number", + "description": "Test timeout in milliseconds", + "minimum": 0 + }, + "retries": { + "type": "number", + "description": "Number of retries on failure", + "minimum": 0, + "maximum": 5 + }, + "tags": { + "type": "array", + "description": "Test tags for filtering", + "items": { "type": "string" }, + "examples": [["@smoke", "@critical", "@slow"]] + }, + "fixtures": { + "type": "object", + "description": "Test-specific fixture overrides", + "additionalProperties": true + }, + "steps": { + "type": "array", + "description": "Test steps to execute", + "items": { "$ref": "#/definitions/testStep" }, + "minItems": 1 + } + } + }, + "testStep": { + "type": "object", + "required": ["action"], + "properties": { + "description": { + "type": "string", + "description": "Human-readable step description" + }, + "action": { + "type": "string", + "description": "Action to perform", + "enum": [ + "navigate", + "click", + "dblclick", + "fill", + "type", + "select", + "check", + "uncheck", + "hover", + "focus", + "press", + "wait", + "waitForSelector", + "waitForNavigation", + "waitForLoadState", + "screenshot", + "evaluate", + "expect", + "custom" + ] + }, + "url": { + "type": "string", + "description": "URL for navigate action" + }, + "selector": { + "type": "string", + "description": "CSS selector or role-based selector" + }, + "role": { + "type": "string", + "description": "ARIA role for getByRole selector", + "enum": ["button", "link", "textbox", "heading", "img", "navigation", "main", "article", "section"] + }, + "text": { + "type": "string", + "description": "Text content or pattern for getByText selector" + }, + "label": { + "type": "string", + "description": "Label for getByLabel selector" + }, + "placeholder": { + "type": "string", + "description": "Placeholder for getByPlaceholder selector" + }, + "testId": { + "type": "string", + "description": "Test ID for getByTestId selector" + }, + "value": { + "description": "Value to fill, type, or select" + }, + "key": { + "type": "string", + "description": "Key to press (e.g., 'Enter', 'Escape')" + }, + "timeout": { + "type": "number", + "description": "Step timeout in milliseconds", + "minimum": 0 + }, + "assertion": { + "$ref": "#/definitions/assertion", + "description": "Assertion to make for expect actions" + }, + "state": { + "type": "string", + "description": "Load state for waitForLoadState", + "enum": ["load", "domcontentloaded", "networkidle"] + }, + "path": { + "type": "string", + "description": "File path for screenshot" + }, + "fullPage": { + "type": "boolean", + "description": "Capture full page screenshot", + "default": false + }, + "script": { + "type": "string", + "description": "JavaScript code for evaluate action" + }, + "condition": { + "type": "string", + "description": "Conditional expression for conditional steps" + } + } + }, + "assertion": { + "type": "object", + "required": ["matcher"], + "properties": { + "matcher": { + "type": "string", + "description": "Playwright assertion matcher", + "enum": [ + "toBeVisible", + "toBeHidden", + "toBeEnabled", + "toBeDisabled", + "toBeChecked", + "toBeFocused", + "toBeEmpty", + "toHaveText", + "toContainText", + "toHaveValue", + "toHaveCount", + "toHaveAttribute", + "toHaveClass", + "toHaveCSS", + "toHaveURL", + "toHaveTitle", + "toBeTruthy", + "toBeFalsy", + "toEqual", + "toContain", + "toBeGreaterThan", + "toBeLessThan" + ] + }, + "expected": { + "description": "Expected value for matcher" + }, + "not": { + "type": "boolean", + "description": "Negate the assertion", + "default": false + }, + "timeout": { + "type": "number", + "description": "Assertion timeout in milliseconds", + "minimum": 0 + } + } + } + }, + "examples": [ + { + "$schema": "https://metabuilder.dev/schemas/package-playwright.schema.json", + "package": "ui_home", + "description": "E2E tests for home page components", + "tests": [ + { + "name": "should display home page with hero section", + "tags": ["@smoke", "@critical"], + "steps": [ + { + "description": "Navigate to home page", + "action": "navigate", + "url": "/" + }, + { + "description": "Wait for page to load", + "action": "waitForLoadState", + "state": "domcontentloaded" + }, + { + "description": "Verify hero title is visible", + "action": "expect", + "text": "Build Anything, Visually", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify Get Started button exists", + "action": "expect", + "role": "button", + "text": "Get Started", + "assertion": { + "matcher": "toBeVisible" + } + } + ] + }, + { + "name": "should display six feature cards", + "steps": [ + { + "action": "navigate", + "url": "/" + }, + { + "action": "waitForLoadState", + "state": "networkidle" + }, + { + "description": "Check feature grid container exists", + "action": "expect", + "selector": ".features-grid", + "assertion": { + "matcher": "toBeVisible" + } + }, + { + "description": "Verify 6 feature cards are rendered", + "action": "expect", + "selector": ".feature-card", + "assertion": { + "matcher": "toHaveCount", + "expected": 6 + } + } + ] + } + ] + } + ] +}