跳到正文
GitHub·· 7 天前AI 评分28

po-generator:用 AI 自动生成 Playwright Page Object 的 CLI 工具

miroslavmyrha/po-generator

AI 导读

开源 CLI 工具 po-generator 可从 Web 应用自动爬取全部 URL,通过 OpenAI 兼容 API 调用 LLM 分析页面交互元素并生成稳定的 Playwright Page Object 与测试文件。

正文

CLI tool for automated Page Object generation from web applications using AI.

Crawls your application, analyzes pages with AI (via OpenAI-compatible API), and generates Playwright Page Objects automatically.

Features

  • Automatic crawling - Discovers all URLs in your application
  • AI-powered analysis - Uses LLM to identify interactive elements and generate stable selectors
  • Multi-framework support - Vuetify, Symfony (Stimulus/Bootstrap), or generic websites
  • Modal detection - Automatically finds and analyzes modal dialogs
  • TypeScript output - Generates typed Page Objects
  • Interactive review - Decide which pages become Page Objects
  • Test generation - AI generates Playwright test files from Page Objects

Installation

Global installation (recommended)

git clone https://github.com/miroslavmyrha/po-generator.git
cd po-generator
bun install
bun link

Now you can use po-gen command anywhere:

po-gen --help
po-gen init
po-gen run

Local installation

git clone https://github.com/miroslavmyrha/po-generator.git
cd po-generator
bun install
node --import tsx bin/po-gen.ts --help

Configuration

Copy the example environment file and configure:

cp .env.example .env

Or run the interactive setup:

po-gen init

Environment Variables

# Application
PO_GEN_BASE_URL=http://localhost:5173
PO_GEN_FRAMEWORK=generic  # vuetify | symfony | generic

# Authentication (optional)
PO_GEN_AUTH_ENABLED=true
PO_GEN_LOGIN_URL=/login
PO_GEN_USERNAME=your@email.com
PO_GEN_PASSWORD=yourpassword
PO_GEN_SUCCESS_URL=/dashboard

# AI API (OpenAI-compatible, e.g., Open WebUI, Ollama)
PO_GEN_AI_URL=http://localhost:3000/api/v1
PO_GEN_AI_KEY=sk-xxx
PO_GEN_AI_MODEL=llama3

# Output
PO_GEN_OUTPUT_DIR=./output

Usage

Full workflow

po-gen run

This will:

  1. Crawl - Find all URLs in your application
  2. Scan - AI analyzes each page for interactive elements
  3. Review - Interactively decide which pages need Page Objects
  4. Generate - Create TypeScript/JavaScript Page Objects
  5. Test-gen - AI generates Playwright test files for each Page Object

Individual commands

# Initialize configuration
po-gen init

# Crawl application and create sitemap
po-gen crawl

# AI scan for elements
po-gen scan

# Interactive review of AI decisions
po-gen review

# Generate Page Objects
po-gen generate

# Generate Playwright tests from Page Objects
po-gen test-gen

Command options

# Scan with specific framework
po-gen scan --framework symfony

# Skip interactive review
po-gen run --skip-review

# Skip test generation in full workflow
po-gen run --skip-tests

# Generate TypeScript files
po-gen generate --typescript

# Scan specific page only
po-gen scan --page /dashboard

# Show help for any command
po-gen crawl --help

Output Structure

output/
├── sitemap.json        # All discovered URLs
├── scanned/            # AI analysis per page
│   ├── dashboard.json
│   └── users.json
├── decisions.json      # Page Object decisions
├── pages/              # Generated Page Objects
│   ├── dashboard-page.ts
│   ├── users-page.ts
│   └── index.ts
└── tests/              # Generated Playwright tests
    ├── dashboard.spec.ts
    └── users.spec.ts

Generated Page Object Example

import { Page, Locator } from '@playwright/test';

/**
 * Page Object for /dashboard
 * Main dashboard with user management
 *
 * @generated Automatically generated by po-generator
 */
export class DashboardPage {
  page: Page;
  url: string;

  constructor(page: Page) {
    this.page = page;
    this.url = '/dashboard';

    /** Search input field */
    this.searchField = page.locator('.v-text-field:has-text("Search") input');

    /** Add new user button */
    this.addUserBtn = page.locator('.v-btn:has-text("Add User")');

    /** Data table with users */
    this.dataTable = page.locator('.v-data-table');
  }

  async goto() {
    await this.page.goto(this.url);
    await this.page.waitForLoadState('networkidle');
  }

  async fillSearchField(value: string) {
    await this.searchField.locator('input').fill(value);
  }

  async clickAddUserBtn() {
    await this.addUserBtn.click();
  }
}

Generated Test Example

import { test, expect } from '@playwright/test';
import { DashboardPage } from '../pages/dashboard-page';

test.describe('Dashboard Page Tests', () => {
  test('should search for users', async ({ page }) => {
    const dashboardPage = new DashboardPage(page);
    await dashboardPage.goto();
    await dashboardPage.fillSearchField('John');
    await expect(page.locator('.v-data-table')).toBeVisible();
  });

  test('should open add user dialog', async ({ page }) => {
    const dashboardPage = new DashboardPage(page);
    await dashboardPage.goto();
    await dashboardPage.clickAddUserBtn();
    await expect(page.locator('.v-dialog')).toBeVisible();
  });
});

Framework Support

Vuetify

  • Recognizes all Vuetify 3 components (v-btn, v-text-field, v-select, v-dialog, etc.)
  • Proper selectors for Vuetify's DOM structure

Symfony

  • Stimulus controllers and actions (data-controller, data-action)
  • Turbo frames and streams
  • Bootstrap components
  • Embedded Vue.js components

Generic

  • Standard HTML elements (button, input, select, a)
  • Common patterns (forms, modals, tables)
  • JavaScript event handlers

AI API Compatibility

Works with any OpenAI-compatible API:

Development

# Run tests
bun run test

# Type check
bun run typecheck

License

MIT

来源:GitHub · github.com