{"id":20364087,"url":"https://github.com/ekino/veggies","last_synced_at":"2025-08-19T16:32:55.375Z","repository":{"id":37821416,"uuid":"95651157","full_name":"ekino/veggies","owner":"ekino","description":":sparkles: :rocket: Veggies is an awesome cucumberjs library for API/CLI testing. Great for testing APIs built upon Express, Koa, HAPI, Loopback and others. It's also the perfect companion for testing CLI applications built with commander, meow \u0026 Co.","archived":false,"fork":false,"pushed_at":"2023-03-04T03:42:32.000Z","size":6473,"stargazers_count":90,"open_issues_count":11,"forks_count":18,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-12-09T09:54:46.948Z","etag":null,"topics":["api","bdd","cli","cucumberjs","gherkin","http-client","testing"],"latest_commit_sha":null,"homepage":"https://ekino.github.io/veggies/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekino.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-06-28T09:14:05.000Z","updated_at":"2024-04-23T20:24:46.000Z","dependencies_parsed_at":"2023-02-18T14:15:58.069Z","dependency_job_id":"143d3e08-5b57-439f-87f2-20a61d32ccbf","html_url":"https://github.com/ekino/veggies","commit_stats":{"total_commits":177,"total_committers":19,"mean_commits":9.31578947368421,"dds":0.4180790960451978,"last_synced_commit":"95168afe23557f20b7cf1df51838862ded6fb459"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekino%2Fveggies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekino%2Fveggies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekino%2Fveggies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekino%2Fveggies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekino","download_url":"https://codeload.github.com/ekino/veggies/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230363998,"owners_count":18214717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","bdd","cli","cucumberjs","gherkin","http-client","testing"],"created_at":"2024-11-15T00:09:44.159Z","updated_at":"2025-08-19T16:32:55.307Z","avatar_url":"https://github.com/ekino.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![veggies](https://raw.githubusercontent.com/ekino/veggies/master/doc/veggies-banner.png)](https://ekino.github.io/veggies/)\n\n[![NPM version][npm-image]][npm-url]\n[![Github CI][ci-image]][ci-url]\n[![Coverage Status][coverage-image]][coverage-url]\n\n[![Watch on GitHub][github-watch-badge]][github-watch]\n[![Star on GitHub][github-star-badge]][github-star]\n[![Tweet][x-badge]][x]\n\nVeggies is an awesome cucumberjs library for API/CLI testing.\nGreat for testing APIs built upon Express, Koa, HAPI, Loopback and others.\nIt's also the perfect companion for testing CLI applications.\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [CLI](#cli)\n- [Features](#features)\n  - [API testing](#api-testing)\n    - [Making a simple request](#making-a-simple-request-and-testing-its-status-code)\n    - [Posting data](#posting-data)\n    - [Posting data using fixture file](#posting-data-using-fixture-file)\n    - [Using values issued by a previous request](#using-values-issued-by-a-previous-request)\n    - [Using cookies](#using-cookies)\n    - [Testing json response](#testing-json-response)\n    - [Testing response headers](#testing-response-headers)\n    - [Debugging failing API tests](#debugging-failing-api-tests)\n    - [Type system](#type-system)\n  - [CLI testing](#cli-testing)\n    - [Running a simple command](#running-a-simple-command-and-checking-its-exit-code)\n    - [Testing a command error](#testing-a-command-error)\n  - [File System testing](#file-system-testing)\n    - [Testing file content](#testing-file-content)\n  - [Snapshot testing](#snapshot-testing)\n    - [API Snapshot testing](#api-snapshot-testing)\n    - [CLI Snapshot testing](#cli-snapshot-testing)\n    - [File Snapshot testing](#file-snapshot-testing)\n- [Extensions](#extensions)\n  - [**state**](#state-extension) [install](#state-installation) | [gherkin expressions](#state-gherkin-expressions) | [low level API](#state-low-level-api)\n  - [**fixtures**](#fixtures-extension) [install](#fixtures-installation) | [low level API](#fixtures-low-level-api)\n  - [**http API**](#http-api-extension) [install](#http-api-installation) | [gherkin expressions](#http-api-gherkin-expressions) | [low level API](#http-api-low-level-api)\n  - [**CLI**](#cli-extension) [install](#cli-installation) | [gherkin expressions](#cli-gherkin-expressions) | [low level API](#cli-low-level-api)\n  - [**fileSystem**](#file-system-extension) [install](#file-system-installation) | [gherkin expressions](#file-system-gherkin-expressions) | [low level API](#file-system-low-level-api)\n  - [**snapshot**](#snapshot-extension) [install](#snapshot-installation) | [low level API](#snapshot-low-level-api)\n- [Helpers](#helpers)\n  - [**cast**](#cast-helper) [usage](#cast-usage) | [add a type](#add-a-type)\n- [Examples](#examples)\n\n## Requirements\n\n- Node.js `\u003e=18.0`\n- cucumber `\u003e=11.0`\n- pnpm `\u003e=10.0`\n\n## Installation\n\n```sh\nnpm install -D @ekino/veggies\nyarn add -D @ekino/veggies\npnpm add -D @ekino/veggies\n```\n\nThen all you have to do is installing the provided extensions:\n\n```javascript\n// /support/world.js\n\nconst { setWorldConstructor } = require('@cucumber/cucumber')\nconst { state, fixtures, httpApi, cli } = require('@ekino/veggies')\n\nsetWorldConstructor(function () {\n    state.extendWorld(this)\n    fixtures.extendWorld(this)\n    httpApi.extendWorld(this)\n    cli.extendWorld(this)\n})\n\nstate.install()\nfixtures.install()\nhttpApi.install({\n    baseUrl: 'http://localhost:3000',\n})\ncli.install()\n```\n\n## CLI\n\nVeggies provides a simple CLI allowing the use of custom options to configure the feature it provides.\n\nAs `cucumber-js` **no longer supports custom options**, it's the safest way to use Veggies in full without problem.\n\nTo make use of it, you can use either of these commands:\n\n```shell\nnpm veggies\nyarn veggies\npnpm veggies\nnpx veggies\n./node_modules/.bin/veggies.js\n```\n\nThe available options are:\n\n| Option                     | Description                                                                                |\n| -------------------------- | ------------------------------------------------------------------------------------------ |\n| --cleanSnapshots           | removes unused snapshots (not recommended while matching tags)                             |\n| -u, --updateSnapshots      | updates current snapshots if required                                                      |\n| --preventSnapshotsCreation | a snapshot related step that would create one will fail instead (useful on CI environment) |\n| --help                     | prints the veggies CLI help then the cucumber-js CLI help                                  |\n\nPlease refer to the [CucumberJS CLI documentation](https://github.com/cucumber/cucumber-js/blob/master/docs/cli.md) to see native Cucumber options (or use `veggies --help`).\n\n## Features\n\n### API testing\n\nFor full feature list, have a look at\n[available gherkin expressions](#http-api-gherkin-expressions)\nfor the [dedicated extension](#http-api-extension).\n\n#### Making a simple request and testing its status code\n\n```gherkin\nScenario: Using GitHub API\n  Given I set User-Agent request header to veggies/1.0\n  When I GET https://api.github.com/\n  Then response status code should be 200\n```\n\n#### Posting data\n\nYou can easily issue a POST request using json payload\n\n```gherkin\nScenario: Creating a resource using json payload\n  Given I set request json body\n    | username | plouc |\n    | gender   | male  |\n  When I POST https://my-api.io/users\n  Then response status code should be 201\n```\n\nYou can also use form encoded values, all you have to do is\nto change `json` for `form`\n\n```gherkin\nScenario: Creating a resource using json payload\n  Given I set request form body\n    | username | plouc |\n    | gender   | male  |\n  When I POST https://my-api.io/users\n  Then response status code should be 201\n```\n\n#### Posting data using fixture file\n\nPutting large data payloads inside your scenarios can reduce legibility,\nto improve this, you can use the [fixtures extension](#fixtures-extension) to define it.\n\n```yaml\n# /features/user/fixtures/user.yml\n\nusername: plouc\ngender: male\n```\n\n```gherkin\n# /features/user/create_user.feature\n\nScenario: Creating a resource using json payload\n  Given I set request form body from user\n  When I POST https://my-api.io/users\n  Then response status code should be 201\n```\n\n#### Using values issued by a previous request\n\nImagine you want to test a resource creation and then that you're able\nto fetch this new entity through the API.\n\nIf resource id is generated by your API, it will be impossible to make\nthe second call because id is unknown.\n\nTo solve this problem you have the ability to collect data from\na previous response, store it in the state and inject it at various\nplaces using placeholders.\n\nThe following example calls the root GitHub API endpoint,\nextracts the `emojis_url` value from the json response and\nstores it in the current state under the `emojisUrl` key,\nthen it uses this value to make its next request.\n\n```gherkin\nScenario: Using GitHub API\n  Given I set User-Agent request header to veggies/1.0\n  When I GET https://api.github.com/\n  And I pick response json emojis_url as emojisUrl\n  And I GET {{emojisUrl}}\n  Then response status code should be 200\n```\n\nIt's even possible to mix this approach with scenario outline to have more concise tests\n(at the cost of clarity thought).\n\nThe following example will generate 3 scenario at runtime\nusing different response values for second request.\n\n```gherkin\nScenario Outline: Fetching \u003ckey\u003e API endpoint from root endpoint\n  Given I set User-Agent request header to veggies/1.0\n  When I GET https://api.github.com/\n  Then response status code should be 200\n  When I pick response json \u003ckey\u003e as \u003ckey\u003e\n  And I GET {{\u003ckey\u003e}}\n  Then response status code should be 200\n\n  Examples:\n    | key              |\n    | emojis_url       |\n    | feeds_url        |\n    | public_gists_url |\n```\n\nPick a value from response header\n\nSyntax:\n\n```\nI pick response header \u003ckey\u003e as \u003ckey\u003e\n```\n\nExample:\n\n```gherkin\nScenario: Setting json body from .json fixture file\n    And set request json body from json_file\n    When I POST https://examples.com/users\n    Then response status code should be 201\n    And I pick response header location as location\n    And I clear request body\n    And I GET {{location}}\n    And response status code should be 200\n```\n\n#### Replace placeholder in key of state\n\nSyntax:\n\n```\nI replace (placeholder) \u003csearch\u003e in \u003ckey\u003e to \u003cvalue\u003e with regex option \u003cflags\u003e\n```\n\n- `placeholder` and `with regex option \u003cflags\u003e` are optional\n- `\u003cvalue\u003e` does not support spaces\n\nExample:\n\n```\nAnd I replace {token} in URLPage to e1c401d5c\nAnd I replace placeholder {stateUpMode} in URLPage to live with regex option gi\n```\n\n#### Using cookies\n\nCookies are disabled by default, but you've got the ability to enable/disable the feature using a gherkin `Given` expression.\nBe warned that cookies do not persist across scenarios in order to ensure they're autonomous.\nIf you really need to keep a cookie for multiple scenarios, you should consider using a custom step definition\nand/or using the [state extension](#state-extension) to store it.\n\n```gherkin\nScenario: Enabling cookies\n  Given I enable cookies\n  # …\n\nScenario: Disabling cookies\n  Given I disable cookies\n  # …\n```\n\nSee [definitions](#http-api-gherkin-expressions) for all available cookies related gherkin expressions.\n\n#### Testing json response\n\n**veggies** gives you the ability to check json responses, the corresponding gherkin expression is:\n\n```\n/^(?:I )?json response should (fully )?match$/\n```\n\nChecking json response properties equal value:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should match\n      | field           | matcher | value |\n      | name            | equal   | thing |\n      | address.country | equal   | Japan |\n```\n\nChecking json response properties start with value:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should match\n      | field           | matcher     | value |\n      | name            | start with  | ing   |\n      | address.country | starts with | Jap   |\n```\n\nChecking json response properties contain value:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should match\n      | field           | matcher | value |\n      | name            | contain | ing   |\n      | address.country | contain | Jap   |\n```\n\nChecking json response properties end with value:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should match\n      | field           | matcher   | value |\n      | name            | end with  | ing   |\n      | address.country | ends with | pan   |\n```\n\nChecking json response properties match value:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should match\n      | field           | matcher | value     |\n      | name            | match   | ^(.+)ing$ |\n      | address.country | match   | ^Jap(.+)$ |\n```\n\nChecking json response properties equalRelativeDate value:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should match\n      | field           | matcher            | value                                        |\n      | endDate         | equalRelativeDate  | 2,days,fr,dddd                               |\n      | beginDate       | equalRelativeDate  | -1,week,fr,[Aujourd'hui] YYYY-MM-DD hh[h]mm  |\n```\n\nBy default, this assertion does not check for full match.\nProperties not listed will just be ignored, if you want a full match:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should fully match\n      | field           | matcher | value     |\n      | name            | match   | ^(.+)ing$ |\n      | address.country | equal   | Japan     |\n```\n\nNow if the json contains extra properties, the test will fail.\n\nAvailable matchers are:\n\n| matcher             | short matcher    | description                                 |\n| ------------------- | ---------------- | ------------------------------------------- |\n| `match`             | `~=`             | property must match given regexp            |\n| `matches`           | see `match`      | see `match`                                 |\n| `start with`        | `^=`             | property must start with given value        |\n| `starts with`       | see `start with` | see `startWith`                             |\n| `contain`           | `*=`             | property must contain given value           |\n| `contains`          | see `contain`    | see `contain`                               |\n| `end with`          | `$=`             | property must end with given value          |\n| `ends with`         | see `end with`   | see `endWith`                               |\n| `defined`           | `?`              | property must not be `undefined`            |\n| `present`           | see `defined`    | see `defined`                               |\n| `equal`             | `=`              | property must equal given value             |\n| `equals`            | see `equal`      | see `equal`                                 |\n| `type`              | `#=`             | property must be of the given type          |\n| `equalRelativeDate` | n/a              | property must be equal to the computed date |\n\n**Any** of these matchers can be negated when preceded by these : `!`, `not`, `does not`, `doesn't`, `is not` and `isn't`.\n\nThe short version of each matcher is intended to be used that way:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should fully match\n      | expression                   |\n      | name ~= ^(.+)ing$            |\n      | address.country = Japan      |\n      | address.city ?               |\n      | address.postalCode #= string |\n```\n\nIf it eases the reading, you can also pad your expressions:\n\n```gherkin\nScenario: Fetching some json response from the internets\n    When I GET https://whatever.io/things/1\n    Then json response should fully match\n      | expression                      |\n      | name               ~= ^(.+)ing$ |\n      | address.country    =      Japan |\n      | address.city       ?            |\n      | address.postalCode #=    string |\n```\n\n#### Testing response headers\n\nIn order to check response headers, you have the following gherkin expression available:\n\n```\n/^response header (.+) should (not )?(equal|contain|match) (.+)$/\n```\n\nIt supports multiple combinations to verify header value conforms to what you expect.\nThis example illustrates its different features:\n\n```gherkin\nScenario: Testing header related expectations\n    When I GET https://whatever.io/\n    Then response header X-Whatever-A should equal whatever\n    And response header X-Whatever-B should not equal whatever\n    And response header X-Whatever-C should contain part\n    And response header X-Whatever-D should not contain part\n    And response header X-Whatever-E should match ^(thing|other)$\n    And response header X-Whatever-F should not match ^(thing|other)$\n```\n\nIf the header does not exist, the test will fail.\n\n#### Debugging failing API tests\n\nWhen testing APIs using cucumber, we often faced situations were we didn't understand why a given test were failing.\nThe dirty fix was to add some nasty `console.log()` everywhere, that's why **veggies** provides helpers to dump response properties.\n\n```gherkin\nScenario: Fetching something from the internets\n    When I GET https://whatever.io/things\n    And dump response body\n    And dump response headers\n    And dump response cookies\n```\n\nYou'll now have the response body/headers/cookies dumped in your terminal.\nYou should disable those steps when the test is fixed as it can be noisy enough.\n\n#### Type system\n\nWhen testing json based APIs, which is a standard nowadays, you have to be aware of data types\nfor sending payloads or making assertions on received responses, that's why veggies provides\na lightweight type systems.\n\nThe following directives are available:\n\n| directive            | type        | example                  | output                    |\n| -------------------- | ----------- | ------------------------ | ------------------------- |\n| `((undefined))`      | `undefined` | `((undefined))`          | `undefined`               |\n| `((null))`           | `null`      | `((null))`               | `null`                    |\n| `\u003cvalue\u003e((string))`  | `string`    | `hi((string))`           | `'hi'`                    |\n| `\u003cvalue\u003e((number))`  | `number`    | `1((number))`            | `1`                       |\n| `\u003cvalue\u003e((boolean))` | `boolean`   | `true((boolean))`        | `true`                    |\n| `\u003cvalue\u003e((array))`   | `Array`     | `one,two,three((array))` | `['one', 'two', 'three']` |\n\nYou can now use those directive for most of the step definitions accepting data tables.\n\nFor example, you can use it to post typed json data:\n\n```gherkin\nScenario: Creating a resource using typed json payload\n  Given I set request json body\n    | username  | plouc((string))          |\n    | team_id   | 1((number))              |\n    | is_active | true((boolean))          |\n    | hobbies   | drawing,hacking((array)) |\n  When I POST https://my-api.io/users\n  Then response status code should be 201\n```\n\nwhich will generate the following payload:\n\n```json\n{\n    \"username\": \"plouc\",\n    \"team_id\": 1,\n    \"is_active\": true,\n    \"hobbies\": [\"drawing\", \"hacking\"]\n}\n```\n\n### CLI testing\n\nFor full feature list, have a look at\n[available gherkin expressions](#cli-gherkin-expressions)\nfor the [dedicated extension](#cli-extension).\n\n#### Running a simple command and checking its exit code\n\n```gherkin\nScenario: Getting info about installed yarn version\n  When I run command yarn --version\n  Then exit code should be 0\n```\n\n#### Testing a command error\n\n```gherkin\nScenario: Running an invalid command\n  When I run command yarn invalid\n  Then exit code should be 1\n  And stderr should contain error Command \"invalid\" not found.\n```\n\n### File System testing\n\n#### Testing file content\n\nIn order to check file content, you have the following gherkin expression available:\n\n```\n/^file (.+) content (not )?(equal|contain|match) (.+)$/\n```\n\nIt supports multiple combinations to verify file content conforms to what you expect.\nThis example illustrates its different features:\n\n```gherkin\nScenario: Testing file content related expectations\n    Then file sample_A.text content should equal whatever\n    And file sample_B.text content should not equal whatever\n    And file sample_C.text content should contain part\n    And file sample_D.text content should not contain part\n    And file sample_E.text content should match ^(thing|other)$\n    And file sample_F.text content should not match ^(thing|other)$\n```\n\nIf the file does not exist, the test will fail.\n\n### Snapshot testing\n\nSnapshot testing compare a response / content against a saved snapshot.\nSnapshots are stored in a file with same name as the feature file with the extension `.snap`\nin a folder **snapshots** in the same folder as the feature file.\n\n**:warning: Snapshots files should be versioned to be compared while running tests**\n\nFolder tree should look like :\nsupport/\nfeatures/\nfeature_with_snapshot.feature\nfeature_without_snapshot.feature\n**snapshots**/\nfeature_with_snapshot.feature.snap\n…\n\nIn a snapshot file, snapshot name follow the pattern:\nSNAPSHOT_NAME NUMBER_OF_TIME_THIS_NAME_WAS_ENCOUNTERED_IN_CURRENT_FILE.NUMBER_OF_TIME_WE_HAD_A_SNAPSHOT_IN_THIS_SCENARIO.\nFor example, this would give: Scenario 1 1.1\n\nIf a snapshot doesn't exist, it will be created the first time.\n\nTo update snapshot use the cucumber command line option '-u'. If you narrowed the tests with tags, only the snapshots\nrelated to the tagged scenarios will be updated.\n\nIn case you need to remove unused snapshots, you can use the option `--cleanSnapshots`.\n:warning: You shouldn't use this option with tags. It may result in used snapshots removed.\n:information_source: Snapshot files related to feature files with no snapshots won't get removed. You need to do it manually.\n\nSometimes, it could be useful to prevent the creation of snapshots, for instance in a CI environment. To do this,\nyou can use the `--preventSnapshotsCreation` flag. An error will be thrown if the snapshot is missing and this option is present.\n\n#### API Snapshot testing\n\nIn order to check an api response against a snapshot, you have the following gherkin expression available:\n\n```\n/^response body should match snapshot$/\n```\n\nThis example illustrates it:\n\n```gherkin\nScenario: Creating a resource using typed json payload\n  Given I set request json body\n    | username  | plouc((string))          |\n    | team_id   | 1((number))              |\n    | is_active | true((boolean))          |\n    | hobbies   | drawing,hacking((array)) |\n  When I POST https://my-api.io/users\n  Then response status code should be 201\n  And response body should match snapshot\n```\n\nIt is sometimes useful to ignore some fields in a response when comparing with the snapshot.\nIn this case and if it's json you can then use with a table:\n\n```\n/^response json body should match snapshot$/\n```\n\nThis examples illustrates it:\n\n```gherkin\nScenario: Creating a resource using typed json payload\n  Given I set request json body\n    | username  | plouc((string))          |\n    | team_id   | 1((number))              |\n    | is_active | true((boolean))          |\n    | hobbies   | drawing,hacking((array)) |\n  When I POST https://my-api.io/users\n  Then response status code should be 201\n  And response json body should match snapshot\n    | field  | matcher | value  |\n    | url    | type    | string |\n```\n\nThe table supports anything defined in [Testing json response](#testing-json-response)\n\n#### CLI Snapshot testing\n\nIn order to check a CLI output against a snapshot, you have the following gherkin expression available:\n\n```\n/^(stderr|stdout) output should match snapshot$/\n```\n\nThis example illustrates it:\n\n```gherkin\nScenario: Getting info about installed yarn version\n  When I run command yarn --version\n  Then exit code should be 0\n  And stdout output should match snapshot\n  And stderr output should match snapshot\n```\n\nIt is sometimes useful to ignore some fields in a cli json formatted output when comparing with the snapshot.\nIn this case and if it's json you can then use with a table:\n\n```\n/^(stderr|stdout) json output should match snapshot$/\n```\n\nThis examples illustrates it:\n\n```gherkin\nScenario: Snapshot testing on a json file\n  Given I set cwd to examples/features/snapshot/fixtures\n  Then json file file2.json content should match snapshot\n    | field           | matcher | value      |\n    | gender          | type    | string     |\n    | id              | type    | number     |\n```\n\nThe table supports anything defined in [Testing json response](#testing-json-response)\n\n#### File Snapshot testing\n\nIn order to check a file content against a snapshot, you have the following gherkin expression available:\n\n```\n/^file (.+) should match snapshot$/\n```\n\nThis example illustrates it:\n\n```gherkin\nScenario: Testing file content related expectations\n    Then file sample_1.text should match snapshot\n```\n\nIt is sometimes useful to ignore some fields in a json file when comparing with the snapshot.\nIn this case and if it's json you can then use with a table:\n\n```\n/^json file (.+) content should match snapshot$/\n```\n\nThis examples illustrates it:\n\n```gherkin\nScenario: Creating a resource using typed json payload\n  Then json file sample_1.text content should match snapshot\n    | field  | matcher | value  |\n    | url    | type    | string |\n```\n\nThe table supports anything defined in [Testing json response](#testing-json-response)\n\n## Extensions\n\nThis module is composed of several extensions.\n\n[state](#state-extension) | [fixtures](#fixtures-extension) | [http API](#http-api-extension) | [CLI](#cli-extension) | [file system](#file-system-extension) | [snapshot](#snapshot-extension)\n\n### state extension\n\nThe state extension is a simple helper used to persist state between steps \u0026 eventually scenarios\n(but you should try to avoid coupling scenarios).\n\nIt's involved for example when [you want to collect values issued by a previous request](#using-values-issued-by-a-previous-request)\nwhen using the [http API extension](#http-api-extension).\n\n#### state installation\n\nTo install the extension, you should add the following snippet to your `world` file:\n\n```javascript\n// /support/world.js\n\nconst { setWorldConstructor } = require('@cucumber/cucumber')\nconst { state } = require('@ekino/veggies')\n\nsetWorldConstructor(function () {\n    state.extendWorld(this)\n})\n\nstate.install()\n```\n\n#### State gherkin expressions\n\n```yaml\nGiven:\n    - /^(?:I )?set state (.+) to (.+)$/\n\nWhen:\n    - /^(?:I )?clear state$/\n    - /^(?:I )?dump state$/\n\nThen:\n    # No definitions\n```\n\n#### State low level API\n\nWhen installed, you can access it from the global cucumber context in your own step definitions.\nFor available methods on the state, please refer to its own\n[documentation](https://ekino.github.io/veggies/module-extensions_state_State.html).\n\n```javascript\nconst { When } = require('@cucumber/cucumber')\n\nWhen(/^I do something useful$/, function () {\n    const stateValue = this.state.get('whatever')\n    // …\n})\n```\n\n### Fixtures extension\n\nThe fixtures extension can be used to load data from files during testing.\n\nIt supports the following file extensions:\n\n- **.yaml**, **.yml** - loads and parses a yaml file, result can be `Object` or `Array`\n- **.txt** - loads text content, result is a `string`\n- **.json** - loads json, result is and `Object`\n- **.js** - loads a javascript module, the module must exports load function via `module.exports`,\n  result can be whatever type the function returns\n\n#### Fixtures installation\n\nTo install the extension, you should add the following snippet to your `world` file:\n\n```javascript\n// /support/world.js\n\nconst { setWorldConstructor } = require('@cucumber/cucumber')\nconst { fixtures } = require('@ekino/veggies')\n\nsetWorldConstructor(function () {\n    fixtures.extendWorld(this)\n})\n\nfixtures.install()\n```\n\n#### Fixtures low level API\n\nWhen installed, you can access it from the global cucumber context in your own step definitions.\nFor available methods on the fixtures loader, please refer to its own\n[documentation](https://ekino.github.io/veggies/module-extensions_fixtures_FixturesLoader.html).\n\n```javascript\nconst { When } = require('@cucumber/cucumber')\n\nWhen(/^I do something useful with fixtures$/, function () {\n    return this.fixtures.load('whatever').then((fixture) =\u003e {\n        // …\n    })\n})\n```\n\n### http API extension\n\n#### http API installation\n\nThe http API extension relies on the [state](#state-extension) \u0026\n[fixtures](#fixtures-extension) extensions, so make sure they're\nregistered prior to installation.\n\nTo install the extension, you should add the following snippet\nto your `world` file:\n\n```javascript\n// /support/world.js\n\nconst { setWorldConstructor } = require('@cucumber/cucumber')\nconst { state, fixtures, httpApi } = require('@ekino/veggies')\n\nsetWorldConstructor(function () {\n    state.extendWorld(this)\n    fixtures.extendWorld(this)\n    httpApi.extendWorld(this)\n})\n\nstate.install()\nhttpApi.install({\n    baseUrl: 'http://localhost:3000',\n})\n```\n\n#### http API gherkin expressions\n\n```yaml\nGiven:\n  - /^(?:I )?set request headers$/\n  - /^(?:I )?do not follow redirect$/\n  - /^(?:I )?follow redirect$/\n  - /^(?:I )?assign request headers$/\n  - /^(?:I )?set ([a-zA-Z0-9-_]+) request header to (.+)$/\n  - /^(?:I )?clear request headers/\n  - /^(?:I )?set request json body$/\n  - /^(?:I )?set request json body from (.+)$/\n  - /^(?:I )?set request form body$/\n  - /^(?:I )?set request form body from (.+)$/\n  - /^(?:I )?set request multipart body from (.+)$/\n  - /^(?:I )?clear request body$/\n  - /^(?:I )?set request query$/\n  - /^(?:I )?pick response (json|header) (.+) as (.+)$/\n  - /^(?:I )?replace(?: placeholder)? (.+) in (.+) to ([^\\s]+)(?: with regex options? (.+)?)?$/\n  - /^(?:I )?enable cookies$/\n  - /^(?:I )?disable cookies$/\n  - /^(?:I )?set cookie from (.+)$/\n  - /^(?:I )?clear request cookies$/\n\nWhen:\n  - /^(?:I )?reset http client$/\n  - /^(?:I )?(GET|POST|PUT|DELETE|PATCH) (.+)$/\n  - /^(?:I )?dump response body$/\n  - /^(?:I )?dump response headers$/\n  - /^(?:I )?dump response cookies$/\n\nThen:\n  - /^response status code should be ([1-5][0-9][0-9])$/\n  - /^response status should be (.+)$/\n  - /^response should (not )?have an? (.+) cookie$/\n  - /^response (.+) cookie should (not )?be secure$/\n  - /^response (.+) cookie should (not )?be http only$/\n  - /^response (.+) cookie domain should (not )?be (.+)$/\n  - /^(?:I )?json response should (fully )?match$/\n  - /^(?:I )?should receive a collection of ([0-9]+) items?(?: for path )?(.+)?$/\n  - /^response should match fixture (.+)$/\n  - /^response header (.+) should (not )?(equal|contain|match) (.+)$/\n```\n\n#### http API low level API\n\nWhen installed, you can access its client from the global cucumber context in your own step definitions.\nFor available methods on the client, please refer to its own\n[documentation](https://ekino.github.io/veggies/module-extensions_httpApi_client.html).\n\n```javascript\nconst { When } = require('@cucumber/cucumber')\n\nWhen(/^I do something useful$/, function () {\n    return this.httpApiClient.makeRequest(/* … */)\n})\n```\n\n### CLI extension\n\n#### CLI installation\n\nThe CLI extension relies on the [state](#state-extension) \u0026\n[fixtures](#fixtures-extension) extensions, so make sure they're\nregistered prior to installation.\n\nTo install the extension, you should add the following snippet\nto your `world` file:\n\n```javascript\n// /support/world.js\n\nconst { setWorldConstructor } = require('@cucumber/cucumber')\nconst { state, fixtures, cli } = require('@ekino/veggies')\n\nsetWorldConstructor(function () {\n    state.extendWorld(this)\n    fixtures.extendWorld(this)\n    cli.extendWorld(this)\n})\n\nstate.install()\nfixtures.install()\ncli.install()\n```\n\n#### CLI gherkin expressions\n\n```yaml\nGiven:\n    - /^(?:I )?set (?:working directory|cwd) to (.+)$/\n    - /^(?:I )?set ([^ ]+) (?:env|environment) (?:var|variable) to (.+)$/\n    - /^(?:I )?set (?:env|environment) (?:vars|variables)$/\n    - /^(?:I )?kill the process with ([^ ]+) in (\\d+)(ms|s)/\n\nWhen:\n    - /^(?:I )?run command (.+)$/\n    - /^(?:I )?dump (stderr|stdout)$/\n\nThen:\n    - /^(?:the )?(?:command )?exit code should be (\\d+)$/\n    - /^(stderr|stdout) should be empty$/\n    - /^(stderr|stdout) should contain (.+)$/\n    - /^(stderr|stdout) should not contain (.+)$/\n    - /^(stderr|stdout) should match (.+)$/\n    - /^(stderr|stdout) should not match (.+)$/\n```\n\n#### CLI low level API\n\nWhen installed, you can access it from the global cucumber context in your own step definitions.\nFor available methods on the client, please refer to its own\n[documentation](https://ekino.github.io/veggies/module-extensions_Cli_Cli.html).\n\n```javascript\nconst { When } = require('@cucumber/cucumber')\n\nThen(/^I check something from the CLI output$/, function () {\n    const out = this.cli.getOutput()\n    // …\n})\n```\n\n### File system extension\n\n#### File system installation\n\nThe fileSystem extension relies on the [cli](#cli-extension) extension,\nso make sure it's registered prior to installation.\n\nTo install the extension, you should add the following snippet\nto your `world` file:\n\n```javascript\n// /support/world.js\n\nconst { setWorldConstructor } = require('@cucumber/cucumber')\nconst { state, fixtures, cli, fileSystem } = require('@ekino/veggies')\n\nsetWorldConstructor(function () {\n    state.extendWorld(this)\n    fixtures.extendWorld(this)\n    cli.extendWorld(this)\n    fileSystem.extendWorld(this)\n})\n\nstate.install()\nfixtures.install()\ncli.install()\nfileSystem.install()\n```\n\n#### File system gherkin expressions\n\n```yaml\nGiven:\n    - /^(?:I )?create directory (.+)$/\n    - /^(?:I )?remove (?:file|directory) (.+)$/\n\nWhen:\n    # No definitions\n\nThen:\n    - /^(file|directory) (.+) should (not )?exist$/\n    - /^file (.+) content should (not )?(equal|contain|match) (.+)$/\n```\n\n#### File system low level API\n\nWhen installed, you can access it from the global cucumber context in your own step definitions.\nFor available methods on the fileSystem, please refer to its own\n[documentation](https://ekino.github.io/veggies/module-extensions_FileSystem_FileSystem.html).\n\n```javascript\nconst { Then } = require('@cucumber/cucumber')\n\nThen(/^I check something using file system$/, function () {\n    return this.fileSystem.getFileContent('whatever').then((content) =\u003e {\n        // …\n    })\n})\n```\n\n### Snapshot extension\n\n#### Snapshot installation\n\nThe snapshot extension add capabilities to [api](#http-api-extension), [cli](#cli-extension) and [file](#file-system-extension) extensions,\nso you will need these extensions if you want to use snapshot related gherkin definitions.\n\nTo install the extension, you should add the following snippet\nto your `world` file:\n\n```javascript\n// /support/world.js\n\nconst { setWorldConstructor } = require('@cucumber/cucumber')\nconst { state, fixtures, cli, fileSystem, snapshot } = require('@ekino/veggies')\n\nsetWorldConstructor(function () {\n    state.extendWorld(this)\n    fixtures.extendWorld(this)\n    cli.extendWorld(this)\n    fileSystem.extendWorld(this)\n    snapshot.extendWorld(this)\n})\n\nstate.install()\nfixtures.install()\ncli.install()\nfileSystem.install()\nsnapshot.install()\n```\n\n#### Snapshot low level API\n\nWhen installed, you can access it from the global cucumber context in your own step definitions.\nFor available methods on the snapshot, please refer to its own\n[documentation](https://ekino.github.io/veggies/module-extensions_snapshot_Snapshot.html).\n\n```javascript\nconst { Then } = require('@cucumber/cucumber')\n\nThen(/^Some content should match snapshot$/, function () {\n    this.snapshot.expectToMatch('whatever')\n})\n```\n\n## Helpers\n\n### Cast helper\n\nCast helper can be used to cast values for custom gherkin rules.\nTo find more about casting see [Type System](#type-system).\n\n#### Cast usage\n\nThis must be used on gherkin arrays. Based on your array type you have to use:\n\n- `step.hashes()` -\u003e `Cast.objects(step.hashes())`\n- `step.rows()` -\u003e `Cast.array(step.rows())`\n- `step.raw()` -\u003e `Cast.array(step.raw())`\n- `step.rowsHash()` -\u003e `Cast.objects(step.rowsHash())`\n\nFor example:\n\n```javascript\nconst { cast } = require('@ekino/veggies')\nconst { Given, When, Then } = require('@cucumber/cucumber')\n\nThen(/^User data should be$/, (step) =\u003e {\n    const userData = this.userData\n    const expectedData = Cast.objects(step.rowsHash())\n    expect(userData).to.be.deep.equal(expectedData)\n})\n```\n\n#### Add a type\n\nYou can provide your own type.\nFor example:\n\n```javascript\nCast.addType('newType', (value) =\u003e value === 'true')\n```\n\nCan be used on:\n\n```gherkin\n  Given I get user id1 profile\n  Then I should receive\n    | id              | id1             |\n    | age             | 1((number))     |\n    | name            | veggies         |\n    | isPublic        | true((newType)) |\n```\n\n## Examples\n\nThis repository comes with few examples, in order to run them, invoke the following script:\n\n```sh\npnpm run examples\n```\n\nIf you want to only run certain examples, you can use tags, for example to run cli extension examples:\n\n```sh\npnpm run examples -- --tags @cli\n```\n\nThere is a special tag which only runs examples not requiring network access:\n\n```sh\npnpm run examples -- --tags @offline\n```\n\nDue to public API rate limit (e.g. GitHub API), this tag is used when running on CI.\n\n[npm-image]: https://img.shields.io/npm/v/@ekino/veggies.svg?longCache=true\u0026style=for-the-badge\n[npm-url]: https://www.npmjs.com/package/@ekino/veggies\n[ci-image]: https://img.shields.io/github/actions/workflow/status/ekino/veggies/release.yml?branch=master\u0026style=for-the-badge\n[ci-url]: https://github.com/ekino/veggies/actions/workflows/release.yml\n[coverage-image]: https://img.shields.io/coveralls/ekino/veggies/master.svg?longCache=true\u0026style=for-the-badge\n[coverage-url]: https://coveralls.io/github/ekino/veggies?branch=master\n[github-watch-badge]: https://img.shields.io/github/watchers/ekino/veggies.svg?style=social\n[github-watch]: https://github.com/ekino/veggies/watchers\n[github-star-badge]: https://img.shields.io/github/stars/ekino/veggies.svg?style=social\n[github-star]: https://github.com/ekino/veggies/stargazers\n[x]: https://x.com/intent/tweet?text=Check%20out%20veggies!%20https://github.com/ekino/veggies%20%F0%9F%91%8D\n[x-badge]: https://img.shields.io/twitter/url/https/github.com/ekino/veggies.svg?style=social\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekino%2Fveggies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekino%2Fveggies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekino%2Fveggies/lists"}