pompidou
v1.0.1
Published
CLI tool to auto-generate strongly-typed Page Object Models from Angular components for multiple test frameworks
Downloads
9
Maintainers
Readme
Pompidou
A powerful CLI tool and library that auto-generates strongly-typed Page Object Models (POMs) from Angular components for multiple languages and test frameworks.
Supported Languages
| Language | Framework | File Extension |
|----------|-----------|----------------|
| TypeScript | Playwright | .po.ts |
| TypeScript | Cypress | .po.ts |
| TypeScript | WebdriverIO | .po.ts |
| Java | Selenium | .java |
| Java | Playwright | .java |
| C# | Playwright | .cs |
| C# | Selenium | .cs |
| Python | Playwright | .py |
| Python | Selenium | .py |
Features
- 🔍 Automatic Discovery: Scans your Angular project for
*.component.tsfiles - 🎯 Element Mapping: Extracts elements with
data-testidattributes from HTML templates - 🔗 Typed Transitions: Parses
@pom-returnJSDoc tags for typed navigation between POMs - 🌍 Multi-Language: Generates POMs in TypeScript, Java, C#, or Python
- 🛠️ Templating Engine: Uses Handlebars for customizable code generation
- ⚡ Fail-Fast: Strict validation with clear, actionable error messages
- 📦 Publishable Package: Structured as a valid npm package
Installation
npm install pompidou --save-dev
# or
yarn add pompidou --devQuick Start
CLI Usage
# TypeScript + Playwright (default)
npx pompidou ./src/app ./e2e/page-objects
# Java + Selenium
npx pompidou ./src/app ./src/test/java/pages -l java-selenium -p com.myapp.pages
# C# + Playwright
npx pompidou ./src/app ./Tests/Pages -l csharp-playwright -p MyApp.Tests.Pages
# Python + Selenium
npx pompidou ./src/app ./tests/pages -l python-selenium
# List all supported languages
npx pompidou list-languagesScan for missing locators
Run a static scan to verify that components are annotated correctly and that common display/input elements have the locator attribute (default data-testid):
npx pompidou scan ./src/app --locator data-testid --verboseThe scan prints a summary and per-component issues. Exit code is 0 when no issues are found, 2 when issues exist.
Programmatic Usage
import { generate, generateMultiLanguage } from 'pompidou';
// TypeScript + Playwright (default)
const summary = await generate({
sourceDir: './src/app',
outputDir: './e2e/page-objects',
generateIndex: true,
});
// Java + Selenium
const javaSummary = await generateMultiLanguage({
sourceDir: './src/app',
outputDir: './src/test/java/pages',
language: 'java-selenium',
package: 'com.myapp.pages',
});
console.log(`Generated ${summary.successCount} POMs`);How It Works
1. Element Mapping
Add data-testid attributes to your Angular templates:
<!-- login.component.html -->
<form>
<input data-testid="username-input" type="text" />
<input data-testid="password-input" type="password" />
<button data-testid="submit-btn">Login</button>
</form>2. Typed Transitions
Use the @pom-return JSDoc tag to define typed navigation:
// login.component.ts
@Component({
selector: 'app-login',
templateUrl: './login.component.html'
})
export class LoginComponent {
/**
* Performs login action
* @pom-return {DashboardPO}
*/
login(username: string, password: string): void {
this.authService.login(username, password).subscribe(() => {
this.router.navigate(['/dashboard']);
});
}
}Generated Output
TypeScript + Playwright
import { Page, Locator } from '@playwright/test';
import { DashboardPO } from './dashboard.po';
export class LoginPO {
protected readonly page: Page;
constructor(page: Page) {
this.page = page;
}
getUsernameInput(): Locator {
return this.page.locator('[data-testid="username-input"]');
}
getPasswordInput(): Locator {
return this.page.locator('[data-testid="password-input"]');
}
getSubmitBtn(): Locator {
return this.page.locator('[data-testid="submit-btn"]');
}
async login(username: string, password: string): Promise<DashboardPO> {
// TODO: Implement action logic
return new DashboardPO(this.page);
}
}Java + Selenium
package com.myapp.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPO {
protected final WebDriver driver;
@FindBy(css = "[data-testid='username-input']")
private WebElement usernameInput;
@FindBy(css = "[data-testid='password-input']")
private WebElement passwordInput;
@FindBy(css = "[data-testid='submit-btn']")
private WebElement submitBtn;
public LoginPO(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public WebElement getUsernameInput() {
return usernameInput;
}
public DashboardPO login(String username, String password) {
// TODO: Implement action logic
return new DashboardPO(driver);
}
}C# + Playwright
using Microsoft.Playwright;
namespace MyApp.Tests.Pages
{
public class LoginPO
{
protected readonly IPage Page;
public LoginPO(IPage page)
{
Page = page;
}
public ILocator GetUsernameInput() => Page.Locator("[data-testid='username-input']");
public async Task<DashboardPO> LoginAsync(string username, string password)
{
// TODO: Implement action logic
return new DashboardPO(Page);
}
}
}CLI Options
Usage: pompidou [options] <source> <output>
Arguments:
source Source directory containing Angular components
output Output directory for generated POM files
Options:
-V, --version output the version number
-l, --language <lang> Target language and framework (default: "typescript-playwright")
-p, --package <name> Package/namespace for generated code
-b, --base-class <name> Base class name for POMs
-s, --suffix <suffix> Suffix for POM class names (default: "PO")
-i, --index Generate index barrel file (default: false)
-f, --force Overwrite existing files (default: false)
--include <patterns...> File patterns to include
--exclude <patterns...> File patterns to exclude
--templates <dir> Custom templates directory
--strict Fail on unknown POM references (default: true)
--no-strict Allow unknown POM references
-v, --verbose Enable verbose logging (default: false)
-h, --help display help for command
Commands:
list-languages List all supported output languagesCustom Templates
You can provide custom Handlebars templates to customize the generated code:
pompidou ./src/app ./output --templates ./my-templatesTemplate directory structure:
my-templates/
├── typescript-playwright/
│ ├── page-object.hbs
│ └── index.hbs
├── java-selenium/
│ └── page-object.hbs
└── csharp-playwright/
└── page-object.hbsTemplate Data
Templates receive the following data:
interface TemplateData {
className: string; // POM class name
sourceClassName: string; // Angular component class name
sourceFilePath: string; // Source file path
baseClass?: string; // Base class to extend
package?: string; // Package/namespace
imports: TemplateImport[]; // Import statements
elements: TemplateElement[]; // Element getters
actions: TemplateAction[]; // Action methods
config: LanguageConfig; // Language configuration
}Available Helpers
- Naming:
pascalCase,camelCase,snakeCase,kebabCase,screamingSnakeCase - Conditionals:
eq,neq,gt,gte,lt,lte,and,or,not - Arrays:
first,last,length,isEmpty,isNotEmpty,join - Types:
javaType,csharpType,pythonType - Documentation:
javadoc,xmldoc,pydoc
Error Handling
The generator follows a fail-fast philosophy with clear, actionable error messages:
❌ Error during generation:
Validation failed with 2 error(s):
1. [UNKNOWN_POM_REFERENCE] Method 'goToProfile' in 'login.component.ts'
references unknown POM 'ProfilePO'. Available POMs: LoginPO, DashboardPO.
2. [INVALID_TEST_ID] Invalid data-testid ' ' in template 'login.component.html':
data-testid cannot be empty.Error Types
| Error | Description |
|-------|-------------|
| SourceDirectoryNotFoundError | Source directory doesn't exist |
| NoComponentsFoundError | No *.component.ts files found |
| TemplateNotFoundError | Template file referenced but missing |
| InvalidTestIdError | Invalid data-testid value |
| InvalidPomReturnTagError | Malformed @pom-return tag |
| UnknownPOMReferenceError | References non-existent POM class |
API Reference
generate(config, options?)
Main function for TypeScript + Playwright output.
generateMultiLanguage(config, options?)
Multi-language generation using templates.
getSupportedLanguages()
Returns list of supported language/framework combinations.
scanComponents(config)
Scans for Angular components without generating POMs.
TemplateEngine
Direct access to the templating engine for custom integrations.
Contributing
Contributions are welcome! To add a new language:
- Create a new directory in
src/templates/ - Add
page-object.hbstemplate - Add language config to
LANGUAGE_CONFIGSintypes.ts - Add tests
License
MIT License - see the LICENSE file for details.
