Skip to content

mdavidgm/co-gherkin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ₯’ Co-Gherkin

BDD Testing, Together

BDD (Behavior-Driven Development) testing with Gherkin syntax for Vitest and Playwright

npm version License: MIT TypeScript Vitest Playwright


πŸš€ What is Co-Gherkin?

Co-Gherkin brings the power of Gherkin (Given-When-Then) syntax to modern JavaScript testing frameworks: Vitest for unit/integration tests and Playwright for E2E tests.

Why "Co"?

Inspired by co-working philosophy, Co-Gherkin promotes collaborative testing where:

  • βœ… Product managers write scenarios in plain English
  • βœ… Developers implement step definitions
  • βœ… QA validates behavior automatically
  • βœ… Everyone speaks the same language

🎯 Meta-Testing: We Practice What We Preach

Co-Gherkin tests itself using Co-Gherkin! πŸ”„

That's right - we use our own BDD framework to test our own code. This means:

  • πŸ’― >99% test coverage achieved through BDD scenarios
  • πŸ§ͺ Real-world validation - if it works for us, it works for you
  • πŸ“‚ Examples - Check out our examples/ folder for a fully working Calculator project
  • πŸ“– Living documentation - our test features are usage examples
  • πŸ” Quality assurance - we trust our own tool enough to depend on it

Check out our test features to see Co-Gherkin in action testing itself!

The Problem

  • ❌ Cucumber.js doesn't work well with Vitest
  • ❌ Playwright BDD is E2E only, not for unit/integration tests
  • ❌ No native Gherkin support in Vitest ecosystem

The Solution: Co-Gherkin

Feature: User Login
  Scenario: Successful login
    Given I am on the login page
    When I enter valid credentials
    Then I should see the dashboard

πŸ“¦ Installation

npm install co-gherkin --save-dev

🎯 Quick Start

1. Create a .feature file

features/login.feature:

Feature: User Login

  Scenario: Successful login
    Given I am on the login page
    When I enter "user@example.com" and "password123"
    Then I should see the dashboard

2. Define steps

tests/login.steps.ts:

import { Given, When, Then } from "co-gherkin";
import { render, screen } from "@testing-library/react";
import { LoginPage } from "../pages/LoginPage";

Given("I am on the login page", () => {
  render(<LoginPage />);
});

When("I enter {string} and {string}", (email: string, password: string) => {
  // Your test logic
});

Then("I should see the dashboard", () => {
  expect(screen.getByText("Dashboard")).toBeInTheDocument();
});

3. Run the feature

tests/login.test.ts:

import { runFeature } from "co-gherkin";
import { resolve } from "path";
import "./login.steps";

runFeature(resolve(__dirname, "../features/login.feature"));

4. Execute with Vitest

npm run test

🎭 Playwright E2E Testing

Co-Gherkin also works with Playwright for End-to-End testing!

1. Configure Co-Gherkin for Playwright

tests/e2e/playwright-setup.ts:

import { configureGherkin } from "co-gherkin";
import { test } from "@playwright/test";

// Configure co-gherkin to use Playwright's test functions
configureGherkin({
  describe: test.describe,
  it: test,
  beforeAll: test.beforeAll,
  afterAll: test.afterAll,
  beforeEach: test.beforeEach,
  afterEach: test.afterEach,
});

2. Define E2E Steps

tests/e2e/steps/login.steps.ts:

import { Given, When, Then } from "co-gherkin";
import { expect } from "@playwright/test";
import { getPage } from "./playwright-context"; // Your context helper

Given("I am on the login page", async () => {
  const page = getPage();
  await page.goto("/login");
});

When(
  "I enter {string} and {string}",
  async (email: string, password: string) => {
    const page = getPage();
    await page.locator('input[type="email"]').fill(email);
    await page.locator('input[type="password"]').fill(password);
    await page.locator('button[type="submit"]').click();
  }
);

Then("I should see the dashboard", async () => {
  const page = getPage();
  await expect(page).toHaveURL(/.*dashboard/);
});

3. Run the Feature with Playwright

tests/e2e/login.spec.ts:

import { runFeatureSync } from "co-gherkin";
import { resolve } from "path";
import "./playwright-setup"; // Configure co-gherkin
import "./steps/login.steps"; // Import steps

// Use runFeatureSync for Playwright (synchronous test generation)
runFeatureSync(resolve(__dirname, "./features/login.feature"));

4. Execute with Playwright

npx playwright test

Key Differences: Vitest vs Playwright

Aspect Vitest Playwright
Function runFeature() runFeatureSync()
Test Generation Dynamic Synchronous
Configuration Auto-detect configureGherkin() required
Use Case Unit/Integration E2E

✨ Features

  • βœ… Multi-Framework Support - Works with Vitest AND Playwright
  • βœ… Vitest Native - Built specifically for Vitest unit/integration tests
  • βœ… Playwright E2E - Full support for Playwright E2E tests
  • βœ… TypeScript First - Full type safety and IntelliSense
  • βœ… Lightweight - Zero heavy dependencies
  • βœ… Fast - Powered by Vitest's and Playwright's speed
  • βœ… Full Gherkin Support:
    • βœ… Given, When, Then, And, But, * keywords
    • βœ… Background - Shared setup steps
    • βœ… Scenario Outline - Data-driven tests with Examples
    • βœ… Data Tables - Structured test data
  • βœ… Regex Patterns - Capture groups for dynamic values
  • βœ… Hooks - BeforeScenario and AfterScenario lifecycle
  • βœ… Unit + Integration + E2E - Complete testing solution
  • βœ… Easy Migration - From Cucumber or Playwright BDD

πŸ“š API Reference

Step Definitions

Define test steps using Gherkin keywords:

import { Given, When, Then, And } from "co-gherkin";

Given("I am on the {string} page", (pageName: string) => {
  // Setup code
});

When("I click the {string} button", (buttonName: string) => {
  // Action code
});

Then("I should see {string}", (text: string) => {
  // Assertion code
});

And("the page title is {string}", (title: string) => {
  // Additional assertion
});

Regex Patterns

Use regex for more complex matching:

Given(/^I have (\d+) items in my cart$/, (count: string) => {
  const itemCount = parseInt(count);
  // Your logic
});

Background

Share common setup steps across scenarios:

Feature: Shopping Cart

  Background:
    Given I am logged in
    And I have an empty cart

  Scenario: Add item to cart
    When I add "Product A" to cart
    Then cart should have 1 item

  Scenario: Remove item from cart
    When I add "Product A" to cart
    And I remove "Product A" from cart
    Then cart should be empty

Scenario Outline

Data-driven testing with examples:

Feature: Calculator

  Scenario Outline: Add two numbers
    Given I have entered <a> into the calculator
    And I have entered <b> into the calculator
    When I press add
    Then the result should be <result>

    Examples:
      | a  | b  | result |
      | 1  | 2  | 3      |
      | 5  | 7  | 12     |
      | 10 | 15 | 25     |

Data Tables

Pass structured data to steps:

Given the following users exist:
  | name  | email           | role  |
  | Alice | alice@test.com  | admin |
  | Bob   | bob@test.com    | user  |
Given("the following users exist:", (dataTable: string[][]) => {
  dataTable.forEach(([name, email, role]) => {
    createUser({ name, email, role });
  });
});

Hooks

Execute code before/after each scenario:

import { BeforeScenario, AfterScenario } from "co-gherkin";

BeforeScenario(() => {
  // Setup: clear database, reset state, etc.
});

AfterScenario(() => {
  // Cleanup: close connections, clear mocks, etc.
});

Feature Runner

Run a feature file with Vitest (dynamic):

import { runFeature } from "co-gherkin";
import { resolve } from "path";

runFeature(resolve(__dirname, "./features/my-feature.feature"));

Run a feature file with Playwright (synchronous):

import { runFeatureSync } from "co-gherkin";
import { resolve } from "path";

runFeatureSync(resolve(__dirname, "./features/my-feature.feature"));

Configuration

Configure co-gherkin for different test frameworks:

import { configureGherkin } from "co-gherkin";
import { test } from "@playwright/test";

configureGherkin({
  describe: test.describe,
  it: test,
  beforeAll: test.beforeAll,
  afterAll: test.afterAll,
  beforeEach: test.beforeEach,
  afterEach: test.afterEach,
});

Note: Configuration is only required for Playwright. Vitest auto-detects when globals: true is enabled.


🎨 Example Project Structure

my-project/
β”œβ”€β”€ features/
β”‚   β”œβ”€β”€ login.feature
β”‚   β”œβ”€β”€ signup.feature
β”‚   └── checkout.feature
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ steps/
β”‚   β”‚   β”œβ”€β”€ login.steps.ts
β”‚   β”‚   β”œβ”€β”€ signup.steps.ts
β”‚   β”‚   └── common.steps.ts
β”‚   β”œβ”€β”€ login.test.ts
β”‚   β”œβ”€β”€ signup.test.ts
β”‚   └── checkout.test.ts
└── vitest.config.ts

πŸ”§ Configuration

vitest.config.ts:

import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    globals: true,
    environment: "jsdom",
  },
});

πŸ†š Comparison

Feature Co-Gherkin Cucumber.js Playwright BDD
Vitest Support βœ… Native ❌ No ❌ No
TypeScript βœ… First-class ⚠️ Partial βœ… Yes
Unit Tests βœ… Yes βœ… Yes ❌ E2E only
Speed ⚑ Fast 🐒 Slow ⚑ Fast
Bundle Size πŸͺΆ Light πŸ“¦ Heavy πŸ“¦ Heavy
Background βœ… Yes βœ… Yes βœ… Yes
Scenario Outline βœ… Yes βœ… Yes βœ… Yes
Data Tables βœ… Yes βœ… Yes βœ… Yes

πŸ›£οΈ Roadmap

See our detailed roadmap for planned features.

v1.0.0 (Stable)

  • Core engine (Parser + Runner)
  • TypeScript definitions
  • Step definition system
  • Hooks (BeforeScenario, AfterScenario)
  • Background support
  • Scenario Outline with Examples
  • Data Tables
  • >99% Code Coverage

Future Ideas

  • Tags support (@smoke, @integration)
  • VS Code Extension with syntax highlighting

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“„ License

MIT Β© David GarcΓ­a


πŸ‘€ Author

David GarcΓ­a


πŸ™ Acknowledgments

Built with ❀️ for the Vitest community

"Testing, Together" - The Co-Gherkin Philosophy

About

BDD testing with Gherkin for Vitest - Testing, Together

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published