Strongly Typed Gherkin-to-Playwright Pipelines

ai-test-generator-4playwright-ts is the TypeScript sibling of my JavaScript generator. The npm package still ships as playwright-testgen-from-gherkin-ts, but the code now lives in amiya-pattnaik/ai-test-generator-4playwright-ts.

The goal stays the same: honor the scenarios product owners capture in Gherkin and produce high quality Playwright suites automatically. The TypeScript flavor adds end-to-end typing so editors surface locator names, method signatures, and data contracts.

What Sets The TS Edition Apart

  • Type-safe Page Objects: Generated classes include typed locators and return values, giving you auto-complete and compile time checks.
  • Typed pipeline utilities: Both processSteps and processTests export TypeScript definitions, so custom build scripts can rely on intellisense.
  • Scriptable watch modes: npm run watch:steps and npm run watch:tests keep the output in sync with live edits.
  • Shared AI selector engine: The same NLP logic powers selector naming, keeping parity with the JavaScript build.

Getting Started

git clone git@github.com:amiya-pattnaik/ai-test-generator-4playwright-ts.git
cd ai-test-generator-4playwright-ts
npm install
npm install -g tsx
npm link

Run the generator:

testgen steps --all
testgen tests --all
testgen run --report

Or stay local without a global link:

npm run steps
npm run tests
npm run run:all      # steps → tests → playwright report

Embed In Tooling

import { processSteps, processTests } from 'playwright-testgen-from-gherkin-ts';

await processSteps({
  featuresPath: './features',
  outputPath: './stepMaps',
  watch: false,
  force: true
});

await processTests({
  stepMapDir: './stepMaps',
  outputDir: './tests',
  dryRun: false,
  all: true
});

That snippet shows the current npm package name. The import path will change after the package is republished under the ai-test-generator naming.

End-To-End Example

Feature Input

Feature: Login

  Scenario: User signs in
    Given I am on the "login" page
    When I fill "userName" with "testuser"
    And I fill "password" with "password123"
    And I click on "login"
    Then I should see "welcomeBack"

Generated Step Map (excerpt)

{
  "scenario": "User signs in",
  "steps": [
    { "action": "open", "selectorName": "open", "note": "login" },
    { "action": "setValue", "selectorName": "userNameField", "note": "testuser" },
    { "action": "setValue", "selectorName": "passwordField", "note": "password123" },
    { "action": "click", "selectorName": "loginButton" },
    { "action": "assertVisible", "selectorName": "welcomeBack" }
  ]
}

Generated Spec Snippet

import { test, expect } from '@playwright/test';
import LoginPage from '../pageobjects/login.page';

test.describe('login feature tests', () => {
  test('user signs in', async ({ page }) => {
    const pageObj = new LoginPage(page);
    await pageObj.open('login');
    await pageObj.userNameField.fill('testuser');
    await pageObj.passwordField.fill('password123');
    await pageObj.loginButton.click();
    await expect(pageObj.welcomeBack).toBeVisible();
  });
});

Roadmap And Feedback

I am collecting requests for improved type helpers, scenario metadata, and generated Playwright fixtures. If you depend on the TypeScript output, please share the gaps you still fill by hand. The more concrete examples I see, the faster we can bake them into the generator.