npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

k6-cucumber-steps

v2.1.1

Published

Generate k6 test scripts from Cucumber feature files

Readme

k6-cucumber-steps 🥒🧪 - K6 Performance Testing with Cucumber BDD

k6-cucumber-steps is a powerful CLI tool that enables you to run k6 performance and load tests using Cucumber BDD (Behavior-Driven Development) syntax. Write performance tests in natural language Gherkin and execute them at scale with k6.

npm version npm downloads npm downloads license Cucumber Node.js TypeScript Sponsor Build Status Documentation


📚 Step Definitions Documentation

All step definitions are fully documented and available in multiple formats:

1. TypeDoc API Documentation

Interactive HTML documentation with search and navigation:

Online: View TypeDoc Documentation

🚀 Auto-Deployed: Documentation is automatically generated and deployed to GitHub Pages on every push to the main branch.

Locally:

# Generate documentation
npm run docs

# View in browser
npm run docs:serve

2. Step Metadata (JSON)

When you initialize a project, a steps/metadata.json file is generated containing:

  • All available step patterns
  • Function names and parameters
  • Categories (HTTP, Browser, Assertions, etc.)
  • Descriptions for each step

3. TypeScript Type Definitions

The src/steps.d.ts file provides:

  • Full TypeScript type definitions
  • JSDoc comments with examples
  • IntelliSense support in IDEs

4. README Reference

See the Step Definitions Reference section below for common usage examples.


✨ Features

  • ✅ Cucumber + Gherkin for writing k6 tests to generate JSON and HTML reports.
  • ✅ Flexible configuration through Cucumber data tables.
  • ✅ Support for JSON body parsing and escaping
  • ✅ Environment Variable Support: Dynamic request body generation using {{VARIABLE_NAME}} placeholders
  • ✅ Enhanced Auth Storage: Store tokens with aliases for cross-scenario reuse
  • ✅ .env + K6.env-style variable resolution ({{API_KEY}})
  • ✅ Support for headers, query params, stages
  • ✅ Supports multiple authentication types: API key, Bearer token, Basic Auth, and No Auth.
  • ✅ Extended HTTP Methods: GET, POST, PUT, PATCH with body support
  • ✅ Response Time Assertions: Validate API performance with millisecond/second thresholds
  • ✅ Property Validation: Deep nested property checks, boolean assertions, empty checks
  • ✅ Alias System: Store and compare response values across scenarios
  • ✅ Clean-up of temporary k6 files after execution
  • ✅ Built-in support for distributed load testing with stages
  • ✅ TypeScript-first 🧡

✨ Key Enhancements

  • 🚀 One-Command Setup: Use init to scaffold a full k6 project with sample features and steps.
  • 📂 Centralized Reporting: Automatically generates HTML and JSON reports in a dedicated reports/ folder.
  • 🔑 Dynamic Auth Storage: Store tokens from one scenario and reuse them in another via globalThis memory.
  • 🛠 JS & TS Support: Generate your project in pure JavaScript or TypeScript.
  • 📊 Metric Segmentation: Scenarios are wrapped in k6 group() blocks for cleaner reporting.

🆕 What's New in v2.1.1

🚨 BREAKING CHANGES for existing projects (v2.0.x)

If you are upgrading an existing project that you initialized with v2.0.x, there are two breaking changes:

  1. Removed Default k6 Prefix: The k6 prefix has been removed from all default step definitions. If you remove the k6 prefix from your existing .feature files, the generated steps will no longer match your older sample.steps.ts exports.
  2. Import Path Change: The CLI now generates code that imports steps from ../steps/index.ts instead of ../steps/sample.steps.ts.

How to upgrade: Run npx k6-cucumber-steps init <your-project-dir> again to scaffold the new steps/index.ts and steps/hooks.ts architecture (this will safely merge with your package.json and will not delete your existing files). Then, update your .feature files to remove the k6 prefix, or pass --add-prefix k6 during initialization if you want to keep your existing syntax.

Natural Language Default & Configurable Prefixes

We removed the forced k6 prefix! Step definitions now use pure, natural BDD language by default.

Default:

Given the base URL is "{{API_BASE_URL}}"
When I make a GET request to "/users/1"

If you use k6-cucumber-steps in the same VSCode workspace as another Cucumber testing tool (like Playwright), you might experience autocomplete clashes. You can now use the --add-prefix flag to safely namespace your steps without breaking natural language:

npx k6-cucumber-steps init my-project --add-prefix "load test"

With --add-prefix "load test":

Given the load test base URL is "{{API_BASE_URL}}"
When I load test make a GET request to "/users/1"

Custom Steps made easier

When you run init, a steps/index.ts file is now generated. This is the new entry point for all steps, making it incredibly easy to write and export your own custom steps alongside the built-in ones. Values are resolved from:

  • __ENV (k6 environment variables)
  • K6_* prefixed variables
  • Global context variables

⚙️ Configuration File (k6-cucumber.json)

You no longer have to pass flags like -f or -o every time you run the generate command. Running init will now generate a k6-cucumber.json config file at the root of your project:

{
  "features": "./features",
  "output": "./generated",
  "lang": "ts"
}

The CLI automatically picks this up when you run npx k6-cucumber-steps generate.

🔄 Cucumber Hooks (before, after)

We now support lifecycle hooks for your scenarios! The init command generates a steps/hooks.ts file. You can export beforeAll, before, after, and afterAll functions to run custom JavaScript/TypeScript code before and after your scenarios or entire test suites.

🚀 CI/CD Pipeline Generator

You can now automatically scaffold a ready-to-use CI/CD load testing pipeline for your repository by simply passing the --ci flag during initialization:

# Generates .github/workflows/k6.yml
npx k6-cucumber-steps init my-project --ci github

# Generates .gitlab-ci.yml
npx k6-cucumber-steps init my-project --ci gitlab

🌍 Environment Variable Support

Replace placeholders in your tests using {{VARIABLE_NAME}} syntax. Values are resolved from:

  • __ENV (k6 environment variables)
  • K6_* prefixed variables
  • Global context variables
Background:
  Given the base URL is "{{API_BASE_URL}}"

Scenario: Login with environment credentials
  When I authenticate with the following url and request body as "user":
    | endpoint | userName            | password            |
    | /login   | {{TEST_USER_USERNAME}} | {{TEST_USER_PASSWORD}} |

🔐 Enhanced Alias System

Store response data with custom aliases and reuse across scenarios:

Scenario: Store and reuse values
  When I make a POST request to "/login"
  And I store response "data.accessToken" as "authToken"
  Then the alias "authToken" should not be empty

Scenario: Compare against stored values
  Then the response property "userName" should be alias "expectedUsername"
  And the response property "message" should contain alias "expectedMessage"

📝 New Assertion Steps

| Step | Description | Example | |------|-------------|---------| | theResponsePropertyShouldNotBeEmpty | Validate property has a value | Then the response property "data.token" should not be empty | | theResponsePropertyShouldBeTrue/False | Boolean assertions | Then the response property "success" should be true | | theResponsePropertyShouldHaveProperty | Check nested properties | Then the response property "data" should have property "user" | | theResponseTimeShouldBeLessThan... | Performance assertions | Then the response time should be less than "500" milliseconds | | theAliasShouldNotBeEmpty | Validate stored aliases | Then the alias "authToken" should not be empty | | theAliasShouldBeEqualTo | Compare alias to value | Then the alias "username" should be equal to "test_user" |

🌐 Extended HTTP Support

  • PUT requests: When I make a PUT request to "/users/1"
  • PUT with body: When I make a PUT request to "/users/1" with body:
  • PATCH requests: When I make a PATCH request to "/api/settings"
  • PATCH with body: When I make a PATCH request to "/api/settings" with body:

🖨️ Debug Helpers

And I print alias "authToken"      # Print a specific alias
And I print all aliases            # Print all stored aliases

🧹 Utility Steps

Given I clear auth token           # Remove Authorization header

🆕 What's New in v2.0.10

🛡️ Critical Bug Fixes & Architecture Overhaul

  • Native k6 Execution Environment: Removed all internal usages of Node.js modules (fs, path) from generated execution scripts, fully aligning step definitions with the restricted k6 Goja runtime.
  • Dynamic Payload Loading: Support for .json file payloads has been rewritten to utilize native k6 open() binding injections, allowing fully compliant memory-based data handling within Virtual Users (VUs) without crashes.
  • Robust Argument Parsing: Fixed a critical bug in k6-script.generator.ts where quoted arguments containing commas (e.g. JSON strings or DataTables) would be incorrectly split.
  • Reliable Gherkin Expansion: Improved parsing in feature.parser.ts to correctly handle Scenario Outline placeholder replacements when values reside within or outside quotes, preventing generation of malformed code.
  • Accurate Tag Filtering: Fixed CLI and runtime tag matching issues where tags provided with @ prefixes would fail to match successfully.
  • Command Path Escaping: Script execution now properly escapes output paths, preventing runner crashes when file directories contain spaces.

🆕 What's New in v2.0.9

🔍 Recursive Feature File Search

The feature parser now automatically searches subdirectories for .feature files.

Example:

npx k6-cucumber-steps generate -f ./features
# Finds: ./features/login.feature
#        ./features/api/users.feature
#        ./features/api/orders.feature
#        ./features/ui/dashboard.feature

Excluded directories: node_modules/, hidden directories (.git/, .github/, etc.)

🗑️ DELETE Request Support (NEW!)

Full DELETE request support with environment variables and alias replacement:

# Basic DELETE
When I make a DELETE request to "/users/1"

# DELETE with env vars
When I make a DELETE request to "/users/{{USER_ID}}"

# DELETE with custom headers
When I make a DELETE request to "/api/items/1" with headers:
  | Authorization       |
  | Bearer {{authToken}} |

# DELETE with payload file
When I make a DELETE request to "/api/bulk" with payload from "data/delete-payload.json"

Supports:

  • {{VARIABLE_NAME}} for environment variables
  • {{alias:NAME}} for stored aliases in payload files

📁 Multiple Feature Paths

Specify multiple directories or files using comma-separated paths.

# Search multiple directories
npx k6-cucumber-steps generate -f "./features/api,./features/ui,./tests/regression"

# Mix directories and single files
npx k6-cucumber-steps generate -f "./features,./tests/smoke.feature"

🏷️ Enhanced Tag Filtering

Better tag filtering with detailed feedback on what's being included/excluded.

# Include only @smoke tests
npx k6-cucumber-steps generate --tags @smoke

# Include multiple tags (OR logic)
npx k6-cucumber-steps generate --tags "@smoke,@regression"

# Exclude specific tags
npx k6-cucumber-steps generate --exclude-tags "@wip,@broken"

# Combine include and exclude
npx k6-cucumber-steps generate --tags "@smoke" --exclude-tags "@known-issue"

New CLI Output:

🏷️  Including scenarios with tags: @smoke
   Filtered: 23 → 8 scenarios

🚫 Excluding scenarios with tags: @wip
   Filtered: 8 → 6 scenarios

📄 Single Feature File Support

Target individual feature files directly.

# Run single feature file
npx k6-cucumber-steps generate -f ./features/login.feature

# Generate specific test suite
npx k6-cucumber-steps generate -f ./tests/regression/payment-flow.feature

📊 Improved CLI Feedback

Enhanced command-line output with detailed progress information:

$ npx k6-cucumber-steps generate -f ./features --tags @smoke

Generating k6 scripts from feature files...
📂 Searching for feature files in: ./features
✅ Found 5 feature file(s)
📋 Total scenarios found: 23
🏷️  Including scenarios with tags: @smoke
   Filtered: 23 → 8 scenarios
📝 Processing 8 scenario(s) for script generation...
✅ Generated k6 script: ./generated/test.generated.ts
📋 Scenarios processed: 8

✨ New: Hybrid Performance Testing

You can now combine Protocol-level (HTTP) load testing and Browser-level (Web Vitals) testing in a single Gherkin suite.

  • API Testing: High-concurrency stress testing at the protocol layer.
  • Browser Testing: Real browser rendering metrics (LCP, CLS, FID) using k6 browser (Chromium).


🚀 Quick Start (Scaffolding a New Project)

🧪 Usage Examples

Initialize in current directory:

# Initialize a new project with natural language steps
npx k6-cucumber-steps init k6-tests

# OR initialize with a custom prefix to avoid autocomplete clashes (e.g., with Playwright)
npx k6-cucumber-steps init k6-tests --add-prefix "load test"

→ Creates features/, steps/, generated/, etc. in your current folder

Initialize in a new subdirectory:

# Initialize in current dir with TypeScript (default)
npx k6-cucumber-steps init

# Initialize in current dir with JavaScript
npx k6-cucumber-steps init -l js

# Initialize in subdirectory with JS
npx k6-cucumber-steps init my-project -l js

→ Creates my-project/ with full structure


🛠️ Project Structure

The init command creates a clean, industry-standard directory structure:

.
├── data/                 # User credentials and seed data
├── features/             # Gherkin .feature files
├── steps/                # Step definitions (logic)
├── generated/            # Compiled k6 scripts (auto-generated)
├── reports/              # HTML & JSON test results
└── package.json          # Test scripts and dependencies

🛠️ CLI Reference

Enable Autocomplete in VSCode

For autocomplete to work in your feature files:

  1. Install the Cucumber extension: Cucumber (Gherkin) Full Support

  2. Create .vscode/settings.json in your project root:

{
  "cucumber.features": ["features/**/*.feature"],
  "cucumber.stepDefinitions": ["steps/**/*.ts", "steps/**/*.js"],
  "cucumber.autocomplete.snippets": true
}
  1. Reload VSCode - Autocomplete will show all 69 step definitions!

📖 Full setup guide: VSCode Autocomplete Setup

Options

The npx k6-cucumber-steps command accepts the following options:

init

Scaffolds a new project.

  • --lang <js|ts>: Choose the project language (default: ts).
  • --force: Overwrite existing files in the current directory.
  • .command("init") description: "Initialize a new k6-cucumber project
  • .argument "[path]": "Output directory path", "./k6-test-project"
  • -f, --feature <path>: "Path to feature files", "./features"
  • -t, --tags <string>: Cucumber tags to filter scenarios (e.g., @smoke and not @regression).

generate

Parses your .feature files and creates the k6-compatible execution scripts in the generated/ folder.

  • .command("generate")
  • .description: ("Generate k6 scripts from feature files")
  • --lang <js|ts>: Choose the project language (default: ts).

run (Direct Execution)

For projects where you prefer to run single features directly.

  • -f, --feature <path>: Path to specific feature.

🧼 Clean-up & Maintenance

  • npm run clean: Wipes the reports/ and generated/ folders.
  • npm run report: Opens the latest HTML report in your default browser.

🔐 Environment Variables Support

The generated project includes dotenv-cli for easy environment variable management.

Using .env file

  1. Create a .env file in your project root:
API_BASE_URL=https://api.example.com
AUTH_BASE_URL=https://auth.example.com
TEST_USER_USERNAME=myuser
TEST_USER_PASSWORD=mypassword
POST_TITLE=My Test Post
CLIENT_ID=my-client-id
CLIENT_SECRET=my-secret
  1. Run tests with environment variables:
# Using dotenv-cli to load .env file
npx dotenv-cli -- k6 run generated/test.generated.ts

# Or add to your package.json scripts:
"test:env": "dotenv-cli -- k6 run generated/test.generated.ts"

Using K6_ prefixed variables

You can also use K6_ prefixed environment variables directly:

K6_API_BASE_URL=https://api.example.com k6 run generated/test.generated.ts

In your feature files

Use {{VARIABLE_NAME}} syntax to reference environment variables:

Background:
  Given the k6 base URL is "{{API_BASE_URL}}"

Scenario: Login with environment credentials
  When I k6 authenticate with the following url and request body as "user":
    | endpoint | userName            | password            |
    | /login   | {{TEST_USER_USERNAME}} | {{TEST_USER_PASSWORD}} |

🔑 Advanced Authentication Flow

We now support Dynamic Handshake Authentication. You can log in once in an initial scenario, store the token, and all subsequent scenarios will automatically be authenticated.

Step 1: Login and Capture

Scenario: Authenticate and Store Token
  When I authenticate with the following url and request body as "standard_user":
    | endpoint | username      | password    |
    | /login   | paschal_qa    | pass123     |
  And I store "data.token" in "data/standard_user.json"

Step 2: Reuse Token

Background:
  And I am authenticated as a "standard_user" # Lookups token from memory

🚀 Usage

Browser Testing (@browser)

Simply tag your scenario with @browser. The generator will automatically launch a Chromium instance, manage the page lifecycle, and inject the page object into your steps.

@browser
Scenario: Verify Homepage UI and Web Vitals
  Given the base URL is "https://test.k6.io"
  When I navigate to the "/" page
  Then I see the text on the page "Collection of simple web-pages"

Dynamic Auth & Storage

Log in via API and reuse the token across any scenario (including Browser scenarios).

Scenario: Login and Save Session
  When I authenticate with the following url and request body as "admin":
    | endpoint | username | password |
    | /login   | admin    | p@ss123  |
  And I store "token" in "data/admin.json"

🧼 Step Definitions Reference

| Step Example | Layer | Description | | ------------------------------------- | ------- | ---------------------------- | | When I k6 make a GET request to "/api" | API | Standard HTTP request. | | When I k6 make a POST request to "/api" | API | Create resource with stored body | | When I k6 make a PUT request to "/api" | API | Update resource with stored body | | When I k6 make a PATCH request to "/api" | API | Partial update with stored body | | When I k6 navigate to the "/home" page | Browser | Opens URL in Chromium. | | And I k6 click the button ".submit" | Browser | Interacts with DOM elements. | | And I k6 store "path" in "file.json" | Both | Dynamic data persistence. | | And I k6 store response "data.token" as "authToken" | API | Store response with alias | | Then the k6 response property "id" should be "123" | API | Validate property value | | Then the k6 response property "success" should be true | API | Boolean assertion | | Then the k6 response time should be less than "500" milliseconds | API | Performance check | | Then the k6 alias "authToken" should not be empty | API | Validate stored alias |


📊 Automated Reporting

Every test run now produces a rich HTML dashboard. Your scenarios are grouped naturally, making it easy to identify which specific Gherkin scenario is causing performance bottlenecks.

Find your reports at:

  • reports/summary.html: Interactive dashboard.
  • reports/results.json: Full k6 metric data.
  • reports/tokens_debug.json: View captured tokens during the run.

Step Definitions

Authentication Steps

When I k6 authenticate with the following url and request body as "standard_user":
| endpoint | username      | password    |
    | /login   | paschal_qa    | pass123     |
And I k6 am authenticated as a "standard_user" # Lookups token from memory

Environment Variable Steps

Background:
  Given the k6 base URL is "{{API_BASE_URL}}"  # Resolves from __ENV or .env

Scenario: Use environment variables in request body
  Given I k6 have the following post data:
    """
    {
      "username": "{{TEST_USER_USERNAME}}",
      "password": "{{TEST_USER_PASSWORD}}"
    }
    """

Payload JSON File Steps

Load request body from a JSON file with support for both environment variables and aliases.

Scenario: Use payload.json file with env vars and aliases
  # First, store a token as an alias
  When I k6 authenticate with the following url and request body as "user":
    | endpoint | username | password |
    | /login   | testuser | pass123  |
  And I k6 store response "accessToken" as "authToken"
  
  # Load payload from file (supports {{VARIABLE_NAME}} and {{alias:NAME}})
  Given I k6 use payload json from file "payload.json"
  When I k6 make a POST request to "/api/users"
  
  # Or combine loading and request in one step
  When I k6 make a POST request to "/api/users" with payload from "data/create-user.json"

File Resolution Order:

  1. data/{fileName} if exists
  2. {fileName} in project root if exists
  3. payload.json in project root as fallback

Template Syntax:

  • {{VARIABLE_NAME}} - Replaced with environment variable value
  • {{alias:NAME}} - Replaced with stored alias value

Example payload.json:

{
  "title": "{{POST_TITLE}}",
  "author": "{{alias:username}}",
  "token": "{{alias:authToken}}",
  "body": "Content with {{VARIABLE_NAME}} support"
}

Alias & Storage Steps

Scenario: Store and reuse values
  When I k6 make a POST request to "/login"
  And I k6 store response "data.accessToken" as "authToken"
  Then the k6 alias "authToken" should not be empty

  # Compare response against stored alias
  Then the k6 response property "userName" should be alias "expectedUsername"

  # Debug: print stored values
  And I k6 print alias "authToken"
  And I k6 print all aliases

  # Write alias to JSON file (NEW!)
  And I k6 write "authToken" to "data/tokens.json"
  And I k6 write "userId" to "data/user.json" as "id"

Write to File Features:

  • ✅ Creates file if it doesn't exist
  • ✅ Creates directory structure if needed
  • ✅ Supports custom key names with as
  • ✅ Adds timestamp to written data
  • ✅ Reads from stored aliases only

Response Assertion Steps

# Property validation
Then the k6 response property "data.id" should be "123"
Then the k6 response property "data.token" should not be empty
Then the k6 response property "success" should be true
Then the k6 response property "deleted" should be false
Then the k6 response property "user" should have property "email"
Then the k6 response property "message" should contain "success"

# Performance assertions
Then the k6 response time should be less than "500" milliseconds
Then the k6 response time should be less than "2" seconds

# Alias comparisons
Then the k6 alias "authToken" should not be empty
Then the k6 alias "username" should be equal to "test_user"
Then the k6 response property "token" should be alias "expectedToken"

HTTP Request Steps

# GET requests
When I k6 make a GET request to "/users/1"
When I k6 make a GET request to "/users/1" with headers:
  | Authorization | Content-Type     |
  | Bearer abc123 | application/json |

# POST requests
When I k6 make a POST request to "/users"
When I k6 make a POST request to "/users" with payload from "payload.json"

# PUT requests
When I k6 make a PUT request to "/users/1"
When I k6 make a PUT request to "/users/1" with body:

# PATCH requests
When I k6 make a PATCH request to "/settings"
When I k6 make a PATCH request to "/settings" with body:

# DELETE requests (NEW!)
When I k6 make a DELETE request to "/users/1"
When I k6 make a DELETE request to "/users/{{USER_ID}}" with headers:
  | Authorization       |
  | Bearer {{authToken}} |
When I k6 make a DELETE request to "/api/items/1" with payload from "data/delete-payload.json"

Sample Features

@smoke @vus:10 @duration:1m
Feature: Comprehensive API Testing

  Background:
    Given the base URL is "https://jsonplaceholder.typicode.com"
    And I set the default headers:
      | Content-Type     | Accept           |
      | application/json | application/json |

  @group:user-api @threshold:http_req_duration=p(95)<500
  Scenario: Get specific user details
    When I make a GET request to "/users/1"
    Then the response status should be 200
    And the response should contain "name"

  @group:load-test @stages:0s-0,20s-10,30s-10,10s-0
  Scenario Outline: Validate multiple user endpoints
    When I make a GET request to "/users/<userId>"
    Then the response status should be <expectedStatus>

    Examples:
      | userId | expectedStatus |
      | 1      | 200            |
      | 5      | 200            |
      | 999    | 404            |

  @group:post-api
  Scenario: Create a post with bulk data
    Given I have the following post data:
      """
      {
        "title": "Performance Test",
        "body": "Testing DataTables and DocStrings",
        "userId": 1
      }
      """
    When I make a POST request to "/posts"
    Then the response status should be 201

Assertion Steps

Then the response status should be 200
Then the response should contain "name"
Then the response status should be <expectedStatus>

💖 Support

If you find this package useful, consider sponsoring me on GitHub. Your support helps me maintain and improve this project!

📄 License

MIT License - @qaPaschalE

  • This project is licensed under the MIT License - see the LICENSE file for details.