{"id":21353371,"url":"https://github.com/marketionist/testcafe-cucumber-steps","last_synced_at":"2025-07-06T05:32:58.834Z","repository":{"id":48116360,"uuid":"229987496","full_name":"Marketionist/testcafe-cucumber-steps","owner":"Marketionist","description":"Cucumber steps (step definitions) written with TestCafe for end-to-end (e2e) tests","archived":false,"fork":false,"pushed_at":"2024-09-01T04:45:09.000Z","size":1236,"stargazers_count":24,"open_issues_count":3,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-30T06:51:27.078Z","etag":null,"topics":["bdd","bdd-tests","cucumber","cucumber-features","cucumber-steps","cucumber-tests","e2e","e2e-tests","end-to-end-testing","predefined-steps","testcafe","testcafe-cucumber-steps"],"latest_commit_sha":null,"homepage":"","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/Marketionist.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-24T18:23:41.000Z","updated_at":"2024-06-06T10:05:24.000Z","dependencies_parsed_at":"2024-11-14T14:25:10.530Z","dependency_job_id":"6ae01b41-0f97-4da1-9234-839238eb6f04","html_url":"https://github.com/Marketionist/testcafe-cucumber-steps","commit_stats":{"total_commits":335,"total_committers":3,"mean_commits":"111.66666666666667","dds":0.005970149253731294,"last_synced_commit":"602ed28d05c12e9884d0152b3678b9ca045df498"},"previous_names":[],"tags_count":51,"template":false,"template_full_name":null,"purl":"pkg:github/Marketionist/testcafe-cucumber-steps","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marketionist%2Ftestcafe-cucumber-steps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marketionist%2Ftestcafe-cucumber-steps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marketionist%2Ftestcafe-cucumber-steps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marketionist%2Ftestcafe-cucumber-steps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Marketionist","download_url":"https://codeload.github.com/Marketionist/testcafe-cucumber-steps/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Marketionist%2Ftestcafe-cucumber-steps/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263853444,"owners_count":23520142,"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":["bdd","bdd-tests","cucumber","cucumber-features","cucumber-steps","cucumber-tests","e2e","e2e-tests","end-to-end-testing","predefined-steps","testcafe","testcafe-cucumber-steps"],"created_at":"2024-11-22T03:17:23.195Z","updated_at":"2025-07-06T05:32:58.790Z","avatar_url":"https://github.com/Marketionist.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# testcafe-cucumber-steps\n\nCucumber steps (step definitions) written with TestCafe for end-to-end (e2e)\ntests - see the presentation of why and how you can easily use\n[TestCafe with Cucumber in 5 steps](https://prezi.com/e1wfgwlfvnhr/testcafe-with-cucumber-in-5-steps/)\n\n[![Actions Status](https://github.com/Marketionist/testcafe-cucumber-steps/actions/workflows/run-tests.yml/badge.svg?branch=master)](https://github.com/Marketionist/testcafe-cucumber-steps/actions)\n[![npm version](https://img.shields.io/npm/v/testcafe-cucumber-steps.svg)](https://www.npmjs.com/package/testcafe-cucumber-steps)\n[![NPM License](https://img.shields.io/npm/l/testcafe-cucumber-steps.svg)](https://github.com/Marketionist/testcafe-cucumber-steps/blob/master/LICENSE)\n\n## Supported versions\n\u003ctable\u003e\n    \u003cthead\u003e\n        \u003ctr\u003e\n            \u003cth\u003e\u003ca href=\"http://nodejs.org/\" rel=\"nofollow\" target=\"_blank\"\u003eNode.js\u003c/a\u003e\u003c/th\u003e\n            \u003cth\u003e\u003ca href=\"https://github.com/DevExpress/testcafe\" rel=\"nofollow\" target=\"_blank\"\u003eTestCafe\u003c/a\u003e\u003c/th\u003e\n            \u003cth\u003e\u003ca href=\"https://github.com/cucumber/cucumber-js\" rel=\"nofollow\" target=\"_blank\"\u003eCucumber\u003c/a\u003e\u003c/th\u003e\n        \u003c/tr\u003e\n    \u003c/thead\u003e\n    \u003ctbody\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e8.x - 20.x\u003c/td\u003e\n            \u003ctd\u003e1.x - 3.x\u003c/td\u003e\n            \u003ctd\u003e5.x - 10.x\u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/tbody\u003e\n\u003c/table\u003e\n\n## Table of contents\n\n* [Installation fast](#installation-fast)\n* [Installation detailed](#installation-detailed)\n* [Writing tests](#writing-tests)\n* [Importing and running in CLI](#importing-and-running-in-cli)\n* [Importing and running with config file](#importing-and-running-with-config-file)\n* [List of predefined steps](#list-of-predefined-steps)\n  * [Given steps](#given-steps)\n  * [When steps](#when-steps)\n  * [Then steps](#then-steps)\n* [Bonus feature: use XPath selectors in TestCafe](#bonus-feature-use-xpath-selectors-in-testcafe)\n* [Contributing](#contributing)\n* [Thanks](#thanks)\n\n## Installation fast\nIf you want to start writing tests as fast as possible, here are the commands\nyou'll need to execute:\n```bash\nnpm init --yes # To create a basic package.json\nnpm install testcafe-cucumber-steps @cucumber/cucumber testcafe gherkin-testcafe --save-dev # To install dependencies and save them to package.json\nnode node_modules/testcafe-cucumber-steps/utils/prepare.js # To create basic test and Page Object files\n```\n\nThen just see the [list of predefined steps](#list-of-predefined-steps) and\nstart writing tests (in `tests/*.feature`) and adding Page Objects\n(in `tests/page-model/*.js`).\n\nRun the tests with:\n```bash\nnode_modules/.bin/gherkin-testcafe chrome,firefox\n```\n\n\u003e Note: all [TestCafe CLI options](https://devexpress.github.io/testcafe/documentation/using-testcafe/command-line-interface.html)\n\u003e are supported.\n\n![Install testcafe-cucumber-steps](https://raw.githubusercontent.com/Marketionist/testcafe-cucumber-steps/master/media/testcafe-cucumber-steps-installation.gif)\n\n## Installation detailed\n\u003e Note: this package is lightweight and has only 3 peerDependencies - it uses:\n\u003e - [cucumber](https://github.com/cucumber/cucumber-js) to parse step definitions\n\u003e - [testcafe](https://github.com/DevExpress/testcafe) to execute steps\n\u003e - [gherkin-testcafe](https://github.com/Arthy000/gherkin-testcafe) to connect TestCafe with Cucumber\n\nFirst of all you will need to create `package.json` if you do not have one in\nthe root folder of your project:\n```bash\nnpm init --yes\n```\n\nTo install the testcafe-cucumber-steps package and its peerDependencies and to\nsave it to your `package.json` just run:\n\n```bash\nnpm install testcafe-cucumber-steps @cucumber/cucumber testcafe gherkin-testcafe --save-dev # In case if you want to use Cucumber 7 (the recent one)\n```\nOR\n```bash\nnpm install testcafe-cucumber-steps cucumber@6.0.5 testcafe gherkin-testcafe@2.5.1 --save-dev # In case if you want to use Cucumber 6\n```\nOR\n```bash\nnpm install testcafe-cucumber-steps cucumber@5.1.0 testcafe gherkin-testcafe@2.5.1 --save-dev # In case if you want to use Cucumber 5\n```\n\nIf you also want to have pre-created config (`.testcaferc.json`) and example\ntest files (`tests/test-example.feature`, `tests/page-model/test-page-example.js`) -\nrun additionally:\n```bash\nnode node_modules/testcafe-cucumber-steps/utils/prepare.js\n```\n\n## Writing tests\nTo give a short example of how you can write the tests - here is \n`test-main-page.feature` feature file:\n```gherkin\n# tests/test-main-page.feature\n\nFeature: My portal main page tests\n  As a user of My portal\n  I should be able to use main page\n  to log in\n\n  Scenario: Open the main page, page title should be present\n    Given user goes to URL \"http://myportal.test/login.html\"\n    Then the title should be \"Test1 main page\"\n\n  Scenario: Products link should lead to Products page\n    Given user goes to pageMain from main-page\n    When user clicks linkProducts from main-page\n    Then URL should contain \"/products\"\n    And the title should contain \"Test1 Products\"\n\n  Scenario: Log in, link with username and status should be present\n    Given user goes to pageMain from main-page\n    When user types \"mytestuser\" in inputLogin from main-page\n    And user types \"mytestpassword\" in inputPassword from main-page\n    And user clicks buttonLogin from main-page\n    Then linkUsernameLoggedIn from main-page should be present\n```\n\nAnd the Page Object file for this tests will look like this:\n```javascript\n// tests/page-model/main-page.js\n\nlet mainPage = {\n\n    pageMain: 'http://myportal.test/login.html',\n    linkProducts: '.link-products',\n    inputLogin: '#login',\n    inputPassword: '#pass',\n    buttonLogin: '.btn-login',\n    linkUsernameLoggedIn: 'a.username-authorized'\n\n};\n\nmodule.exports = mainPage;\n```\n\nIf you want the Page Objects to look even shorter - you can write the same tests\nlike this:\n```gherkin\n# tests/test-main-page.feature\n\nFeature: My portal main page tests\n  As a user of My portal\n  I should be able to use main page\n  to log in\n\n  Scenario: Open the main page, page title should be present\n    Given user goes to URL \"http://myportal.test/login.html\"\n    Then the title should be \"Test1 main page\"\n\n  Scenario: Products link should lead to Products page\n    Given user goes to \"main-page\".\"pageMain\"\n    When user clicks \"main-page\".\"linkProducts\"\n    Then URL should contain \"/products\"\n    And the title should contain \"Test1 Products\"\n\n  Scenario: Log in, link with username and status should be present\n    Given user goes to \"main-page\".\"pageMain\"\n    When user types \"mytestuser\" in \"main-page\".\"inputLogin\"\n    And user types \"mytestpassword\" in \"main-page\".\"inputPassword\"\n    And user clicks \"main-page\".\"buttonLogin\"\n    Then \"main-page\".\"linkUsernameLoggedIn\" should be present\n```\n\nSee more examples of how to use predefined steps in\n[`test1-user.feature`](https://github.com/Marketionist/testcafe-cucumber-steps/blob/master/tests/test1-user.feature) and\n[`test2-user.feature`](https://github.com/Marketionist/testcafe-cucumber-steps/blob/master/tests/test2-user.feature).\n\nIf you want to get access to Page Objects in your custom Cucumber steps - you can just require them inside any step definitions\nfile like this:\n```javascript\nconst pageObjects = require('testcafe-cucumber-steps/utils/get-page-objects.js');\n```\n\n## Importing and running in CLI\nTo get access to all Cucumber steps defined in this package just specify the\npath to this package when launching tests:\n```bash\nnode_modules/.bin/gherkin-testcafe chrome,firefox node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature\n```\n\nIf you store your Page Objects not in `tests/page-model` folder, then\n`PO_FOLDER_PATH` environment variable has to be specified to show the path to\nyour Page Objects folder:\n```bash\nPO_FOLDER_PATH='tests/my-custom-page-objects' node_modules/.bin/gherkin-testcafe chrome,firefox node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature\n```\n\n\u003e Note: you can specify multiple Page Object folders by separating them with commas:\n\u003e `PO_FOLDER_PATH='main/my-custom1,login/my-custom2,auth,create/my-custom3'`\n\nAlso you can just add `test-e2e` command to `scripts` in `package.json`:\n```json\n\"test-e2e\": \"PO_FOLDER_PATH='tests/my-custom-page-objects' node_modules/.bin/gherkin-testcafe 'chrome:headless' node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature\"\n```\nand then launch tests with:\n```\nnpm run test-e2e\n```\n\n\u003e Note: all [TestCafe CLI options](https://devexpress.github.io/testcafe/documentation/using-testcafe/command-line-interface.html)\n\u003e are supported.\n\nAdditionally, you can specify:\n\n- tags to run:\n    ```bash\n    node_modules/.bin/gherkin-testcafe chrome,firefox node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --tags @fast\n    ```\n\n    When using more than one tag, the list needs to be comma separated:\n    ```bash\n    node_modules/.bin/gherkin-testcafe chrome node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --tags @fast,@long\n    ```\n\n    Negation of a tag (via `~`) is also possible (to run all scenarios that have\n    tag `fast`, but not `long`):\n    ```bash\n    node_modules/.bin/gherkin-testcafe chrome node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --tags @fast,~@long\n    ```\n\n- custom parameter types:\n    ```bash\n    node_modules/.bin/gherkin-testcafe chrome node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --param-type-registry-file ./a-file-that-exports-a-parameter-type-registry.js\n    ```\n\n    \u003e Note: see Cucumber Expressions in\n    \u003e [gherkin-testcafe](https://github.com/kiwigrid/gherkin-testcafe#cucumber-expressions)\n    \u003e and Custom Parameter types in\n    \u003e [cucumber.io](https://cucumber.io/docs/cucumber/cucumber-expressions/#custom-parameter-types).\n\n## Importing and running with config file\nTo make life easier and not to specify all options in CLI command, a\n`.testcaferc.json` configuration file can be created in the root directory of\nyour project to store all settings (pathes to all step definitions and tests\nshould be specified inside the array in `src`):\n```json\n{\n    \"browsers\": \"chrome\",\n    \"src\": [\"node_modules/testcafe-cucumber-steps/index.js\", \"tests/**/*.js\", \"tests/**/*.feature\"],\n    \"screenshots\": {\n        \"path\": \"tests/screenshots/\",\n        \"takeOnFails\": true,\n        \"pathPattern\": \"${DATE}_${TIME}/test-${TEST_INDEX}/${USERAGENT}/${FILE_INDEX}.png\"\n    },\n    \"quarantineMode\": false,\n    \"stopOnFirstFail\": true,\n    \"skipJsErrors\": true,\n    \"skipUncaughtErrors\": true,\n    \"concurrency\": 1,\n    \"selectorTimeout\": 3000,\n    \"assertionTimeout\": 1000,\n    \"pageLoadTimeout\": 1000,\n    \"disablePageCaching\": true\n}\n```\nand then launch tests with:\n```bash\nnode_modules/.bin/gherkin-testcafe\n```\nor if you use custom Page Objects folder:\n```bash\nPO_FOLDER_PATH='tests/my-custom-page-objects' node_modules/.bin/gherkin-testcafe\n```\n\nAll options that are specified in CLI command will override settings from `.testcaferc.json`.\n\n\u003e Note: for all possible settings see:\n\u003e - [TestCafe configuration file description](https://devexpress.github.io/testcafe/documentation/using-testcafe/configuration-file.html) and\n\u003e [example of .testcaferc.json](https://github.com/DevExpress/testcafe/blob/master/examples/.testcaferc.json)\n\u003e - [TestCafe command line options](https://devexpress.github.io/testcafe/documentation/using-testcafe/command-line-interface.html)\n\n## List of predefined steps\n### Given steps\n1. `I/user go(es) to URL \"...\"` - open a site (by its URL provided in \"\" as a\nstring - for example: `\"https://github.com/Marketionist\"`) in the current\nbrowser window/tab.\n2. `I/user go(es) to \"...\".\"...\"` - open a site (by its URL provided in\n**\"page\".\"object\"**) in the current browser window/tab.\n- `I/user go(es) to ... from ...` - open a site (by its URL provided in\n**object** from **page**) in the current browser window/tab.\n3. `I/user set(s) cookie \"...\"` - set cookie on the current site (cookie\nprovided in \"\" as a string - for example: `\"my_test_cookie1=11\"`).\n- `I/user set(s) cookie \"...\".\"...\"` - set cookie on the current site (cookie\nprovided in **\"page\".\"object\"**).\n- `I/user set(s) cookie ... from ...` - set cookie on the current site (cookie\nprovided in **object** from **page**).\n4. `I/user send(s) \"...\" request to \"...\" with body \"...\"` - send request\n(request method provided in \"\" as a string - for example: `POST`) to URL\n(provided in \"\" as a string - for example: `\"http://httpbin.org/post\"`) with\nbody (provided in \"\" as JSON - for example: `\"{ \\\"test1\\\": 1, \\\"test2\\\": 2 }\"`).\n\u003e Note: GET request will be sent with default header `'Content-Type': 'text/html'`,\n\u003e all other requests will be sent with default header\n\u003e `'Content-Type': 'application/json'`.\n- `I/user send(s) \"...\" request to \"...\" with body \"...\".\"...\"` - send request\n(request method provided in \"\" as a string - for example: `POST`) to URL\n(provided in \"\" as a string - for example: `\"http://httpbin.org/post\"`) with\nbody (provided in **\"page\".\"object\"**).\n- `I/user send(s) \"...\" request to \"...\".\"...\" with body \"...\".\"...\"` - send\nrequest (request method provided in \"\" as a string - for example: `POST`) to URL\n(provided in **\"page\".\"object\"**) with body (provided in **\"page\".\"object\"**).\n- `I/user send(s) \"...\" request to ... from ... with body ... from ...` - send\nrequest (request method provided in \"\" as a string - for example: `POST`) to URL\n(provided in **object** from **page**) with body (provided in **object** from\n**page**).\n5. `I/user send(s) \"...\" request to \"...\" with headers \"...\" and body \"...\"` -\nsend request (request method provided in \"\" as a string - for example: `POST`)\nto URL (provided in \"\" as a string - for example: `\"http://httpbin.org/post\"`)\nwith headers (provided in \"\" as JSON - for example:\n`\"{ \\\"Content-Type\\\": \\\"application/json\\\", \\\"Authorization\\\": \\\"Bearer aBcD1234\\\" }\"`\n) and body (provided in \"\" as JSON - for example:\n`\"{ \\\"test1\\\": 1, \\\"test2\\\": 2 }\"`).\n- `I/user send(s) \"...\" request to \"...\" with headers \"...\".\"...\" and body \"...\".\"...\"` -\nsend request (request method provided in \"\" as a string - for example: `POST`) to URL\n(provided in \"\" as a string - for example: `\"http://httpbin.org/post\"`) with\nheaders (provided in **\"page\".\"object\"**) and body (provided in\n**\"page\".\"object\"**).\n- `I/user send(s) \"...\" request to \"...\".\"...\" with headers \"...\".\"...\" and body \"...\".\"...\"` -\nsend request (request method provided in \"\" as a string - for example: `POST`)\nto URL (provided in **\"page\".\"object\"**) with headers (provided in\n**\"page\".\"object\"**) and body (provided in **\"page\".\"object\"**).\n- `I/user send(s) \"...\" request to ... from ... with headers ... from ... and body ... from ...` -\nsend request (request method provided in \"\" as a string - for example: `POST`) to URL\n(provided in **object** from **page**) with headers (provided in **object** from\n**page**) and body (provided in **object** from **page**).\n\n### When steps\n6. `I/user log(s) in with l: \"...\" in \"...\".\"...\" and p: \"...\" in\n\"...\".\"...\" and click(s) \"...\".\"...\"` - log in to any site with login (provided\nin \"\" as a string), login/username input (provided in **page1**.**object1** as\nCSS selector), password (provided in \"\" as a string), password input (provided\nin **page2**.**object2** as CSS or XPath selector), login button (provided in\n**page3**.**object3** as CSS or XPath selector).\n- `I/user log(s) in with l: \"...\" in ... from ... and p: \"...\" in ...\nfrom ... and click(s) ... from ...` - log in to any site with login (provided\nin \"\" as a string), login/username input (provided in **object1** from **page1**\nas CSS or XPath selector), password (provided in \"\" as a string), password input\n(provided in **object2** from **page2** as CSS or XPath selector), login button\n(provided in **object3** from **page3** as CSS or XPath selector).\n- `I/user log(s) in with l: \"...\".\"...\" in \"...\".\"...\" and p: \"...\".\"...\" in\n\"...\".\"...\" and click(s) \"...\".\"...\"` - log in to any site with login (provided\nin **page1**.**object1** as CSS or XPath selector), login/username input\n(provided in **page2**.**object2** as CSS or XPath selector), password (provided\nin **page3**.**object3** as CSS or XPath selector), password input (provided in\n**page4**.**object4** as CSS or XPath selector), login button (provided in\n**page5**.**object5** as CSS or XPath selector).\n- `I/user log(s) in with l: ... from ... in ... from ... and p: ... from ... in\n... from ... and click(s) ... from ...` - log in to any site with login\n(provided in **object1** from **page1** as CSS or XPath selector),\nlogin/username input (provided in **object2** from **page2** as CSS or XPath\nselector), password (provided in **object3** from **page3** as CSS or XPath\nselector), password input (provided in **object4** from **page4** as CSS or\nXPath selector), login button (provided in **object5** from **page5** as CSS or\nXPath selector).\n7. `I/user reload(s) the page` - reload current page.\n8. `I/user click(s) \"...\".\"...\"` - click on any element (provided in\n**\"page\".\"object\"** as CSS or XPath selector).\n- `I/user click(s) ... from ...` - click on any element (provided in **object**\nfrom **page** as CSS or XPath selector).\n9. `I/user right click(s) \"...\".\"...\"` - right click on any element (provided in\n**\"page\".\"object\"** as CSS or XPath selector).\n- `I/user right click(s) ... from ...` - right click on any element (provided in\n**object** from **page** as CSS or XPath selector).\n10. `I/user wait(s) for ... ms` - wait for provided amount of time (in\nmilliseconds).\n11. `I/user wait(s) and click(s) \"...\".\"...\"` - wait for 300 ms and then click\non any element (provided in **\"page\".\"object\"** as CSS or XPath selector).\n- `I/user wait(s) and click(s) ... from ...` - wait for 300 ms and then click on\nany element (provided in **object** from **page** as CSS or XPath selector).\n12. `I/user wait(s) up to ... ms for \"...\".\"...\" to appear` - wait up to\nprovided amount of time (in milliseconds) for any element (provided in\n**\"page\".\"object\"** as CSS or XPath selector) to appear.\n- `I/user wait(s) up to ... ms for ... from ... to appear` - wait up to provided\namount of time (in milliseconds) for any element (provided in **object** from\n**page** as CSS or XPath selector) to appear.\n13. `I/user click(s) \"...\".\"...\" if present` - click on any element (provided in\n**\"page\".\"object\"** as CSS or XPath selector) only if it is present on the page.\n- `I/user click(s) ... from ... if present` - click on any element (provided in\n**object** from **page** as CSS or XPath selector) only if it is present on the\npage.\n14. `I/user double click(s) \"...\".\"...\"` - double click on any element (provided\nin **\"page\".\"object\"** as CSS or XPath selector).\n- `I/user double click(s) ... from ...` - double click on any element (provided\nin **object** from **page** as CSS or XPath selector).\n15. `I/user type(s) \"...\" in \"...\".\"...\"` - type any text (provided in \"\" as a\nstring) in the input field (provided in **\"page\".\"object\"** as CSS or XPath\nselector).\n- `I/user type(s) \"...\" in ... from ...` - type any text (provided in \"\" as a\nstring) in the input field (provided in **object** from **page** as CSS\nselector).\n- `I/user type(s) \"...\".\"...\" in \"...\".\"...\"` - type any text (provided in\n**\"page1\".\"object1\"**) in the input field (provided in **\"page2\".\"object2\"** as\nCSS selector).\n- `I/user type(s) ... from ... in ... from ...` - type any text (provided in\n**object1** from **page1**) in the input field (provided in **object2** from\n**page2** as CSS or XPath selector).\n16. `I/user clear(s) \"...\".\"...\" and type(s) \"...\"` - clear the input field\n(provided in **\"page\".\"object\"** as CSS or XPath selector) and type any text\n(provided in \"\" as a string).\n- `I/user clear(s) ... from ... and type(s) \"...\"` - clear the input field\n(provided in **object** from **page** as CSS or XPath selector) and type any\ntext (provided in \"\" as a string).\n- `I/user clear(s) \"...\".\"...\" and type(s) \"...\".\"...\"` - clear the input field (provided in **\"page1\".\"object1\"** as CSS or XPath selector) and type any text\n(provided in **\"page2\".\"object2\"**).\n- `I/user clear(s) ... from ... and type(s) ... from ...` - clear the input\nfield (provided in **object1** from **page1** as CSS or XPath selector) and type\nany text (provided in **object2** from **page2**).\n17. `I/user select(s) \"...\" in \"...\".\"...\"` - select any option (provided in \"\"\nas a string) in the dropdown (provided in **\"page\".\"object\"** as CSS or XPath\nselector).\n- `I/user select(s) \"...\" in ... from ...` - select any option (provided in \"\"\nas a string) in the dropdown (provided in **object** from **page** as CSS or\nXPath selector).\n- `I/user select(s) \"...\".\"...\" in \"...\".\"...\"` - select any option (provided in\n**\"page1\".\"object1\"**) in the dropdown (provided in **\"page2\".\"object2\"** as CSS\nor XPath selector).\n- `I/user select(s) ... from ... in ... from ...` - select any option\n(provided in **object1** from **page1**) in the dropdown (provided in\n**object2** from **page2** as CSS or XPath selector).\n18. `I/user move(s) to \"...\".\"...\"` - move the mouse pointer over any element\n(hover with cursor an element provided in **\"page\".\"object\"** as CSS or XPath\nselector).\n- `I/user move(s) to ... from ...` - move the mouse pointer over any element\n(hover with cursor an element provided in **object** from **page** as CSS or\nXPath selector).\n19. `I/user move(s) to \"...\".\"...\" with an offset of x: ...px, y: ...px` - move\nthe mouse pointer over any element (hover with cursor an element provided in\n**\"page\".\"object\"** as CSS or XPath selector) with an offset of x: ...px,\ny: ...px.\n- `I/user move(s) to ... from ... with an offset of x: ...px, y: ...px` - move\nthe mouse pointer over any element (hover with cursor an element provided in\n**object** from **page** as CSS or XPath selector) with an offset of x: ...px,\ny: ...px.\n20. `I/user switch(es) to \"...\".\"...\" frame` - switch the context to iframe\n(provided in **\"page\".\"object\"** as CSS or XPath selector).\n- `I/user switch(es) to ... frame from ...` - switch the context to iframe\n(provided in **object** from **page** as CSS or XPath selector).\n21. `I/user wait(s) up to ... ms and switch(es) to \"...\".\"...\" frame` - wait up\nto provided amount of time (in milliseconds) for the iframe to load and then\nswitch the context to that iframe (provided in **\"page\".\"object\"** as CSS or\nXPath selector).\n- `I/user wait(s) up to ... ms and switch(es) to ... frame from ...` - wait up\nto provided amount of time (in milliseconds) for the iframe to load and then\nswitch the context to that iframe (provided in **object** from **page** as CSS\nor XPath selector).\n22. `I/user switch(es) to main frame` - switch the context back to default\n(initial) frame.\n23. `I/user set(s) \"...\" file path in \"...\".\"...\"` - set a file path (provided\nin \"\" as a string) in the input (provided in **\"page\".\"object\"** as CSS or XPath\nselector). This step can be used to upload files and images.\n- `I/user set(s) \"...\" file path in ... from ...` - set a file path (provided in\n\"\" as a string) in the input (provided in **object** from **page** as CSS\nselector).\n- `I/user set(s) \"...\".\"...\" file path in \"...\".\"...\"` - set a file path\n(provided in **\"page1\".\"object1\"**) in the input (provided in\n**\"page2\".\"object2\"** as CSS or XPath selector).\n- `I/user set(s) ... from ... file path in ... from ...` - set a file path\n(provided in **object1** from **page1**) in the input (provided in\n**object2** from **page2** as CSS or XPath selector).\n24. `I/user execute(s) \"...\".\"...\" function` - execute script (JavaScript\nfunction) provided in **\"page\".\"object\"**.\n- `I/user execute(s) ... function from ...` - execute script (JavaScript\nfunction) provided in **object** from **page**.\n25. `I/user drag(s)-and-drop(s) \"...\".\"...\" to \"...\".\"...\"` - drag-and-drop\nelement (provided in **\"page1\".\"object1\"** as CSS or XPath selector) to another\nelement (provided in **\"page2\".\"object2\"** as CSS or XPath selector).\n- `I/user drag(s)-and-drop(s) ... from ... to ... from ...` - drag-and-drop\nelement (provided in **object1** from **page1** as CSS or XPath selector) to\nanother element (provided in **object2** from **page2** as CSS or XPath selector\n).\n26. `I/user accept(s) further browser alerts` - accept (OK) all further browser\nalerts (after this step).\n27. `I/user dismiss(es) further browser alerts` - dismiss (Cancel) all further\nbrowser alerts (after this step).\n28. `I/user open(s) \"...\" in new browser window` - open a site (by its URL\nprovided in \"\" as a string - for example: `\"https://github.com/Marketionist\"`)\nin the new browser window/tab.\n- `I/user open(s) \"...\".\"...\" in new browser window` - open a site (by its URL\nprovided in **\"page\".\"object\"**) in the new browser window/tab.\n- `I/user open(s) ... from ... in new browser window` - open a site (by its URL\nprovided in **object** from **page**) in the new browser window/tab.\n29. `I/user close(s) current browser window` - close current browser window/tab.\n30. `I/user press(es) \"...\"` - press the specified keyboard keys (provided in \"\"\nas a string - see the\n[list of supported keys and key combinations](https://devexpress.github.io/testcafe/documentation/test-api/actions/press-key.html#browser-processing-emulation)).\n31. `I/user set(s) PAGE_URL environment variable` - take current page URL and\nwrite it to PAGE_URL environment variable.\n32. `I/user go(es) to PAGE_URL` - open a site from PAGE_URL environment\nvariable.\n33. `I/user debug(s)` - set a breakpoint to stop the tests execution and start\ndebugging.\n\n### Then steps\n34. `the title should be \"...\"` - verify that title of the current browser\nwindow/tab equals to the text (provided in \"\" as a string).\n35. `the title should contain \"...\"` - verify that title of the current browser\nwindow/tab contains the text (provided in \"\" as a string).\n36. `\"...\".\"...\" should be present` - verify that element (provided in\n**\"page\".\"object\"** as CSS or XPath selector) is present on the page.\n- `... from ... should be present` - verify that element (provided in\n**object** from **page** as CSS or XPath selector) is present on the page.\n37. `... \"...\".\"...\" should be present` - verify that the number of elements\n(provided in **\"page\".\"object\"** as CSS or XPath selector) are present on the\npage.\n- `... ... from ... should be present` - verify that the number of elements\n(provided in **object** from **page** as CSS or XPath selector) are present on\nthe page.\n38. `\"...\".\"...\" should not be present` - verify that element (provided in\n**\"page\".\"object\"** as CSS or XPath selector) is not present on the page.\n- `... from ... should not be present` - verify that element (provided in\n**object** from **page** as CSS or XPath selector) is not present on the page.\n39. `\"...\".\"...\" text should be \"...\"` - verify that text of the element\n(provided in **\"page\".\"object\"** as CSS or XPath selector) equals to the text\n(provided in \"\" as a string).\n- `... from ... text should be \"...\"` - verify that text of the element\n(provided in **object** from **page** as CSS or XPath selector) equals to the\ntext (provided in \"\" as a string).\n- `\"...\".\"...\" text should be \"...\".\"...\"` - verify that text of the element\n(provided in **\"page1\".\"object1\"** as CSS or XPath selector) equals to the text\n(provided in **\"page2\".\"object2\"**).\n- `... from ... text should be ... from ...` - verify that text of the\nelement (provided in **object1** from **page1** as CSS or XPath selector) equals\nto the text (provided in **object2** from **page2**).\n40. `\"...\".\"...\" text should contain \"...\"` - verify that text of the element\n(provided in **\"page\".\"object\"** as CSS or XPath selector) contains the text\n(provided in \"\" as a string).\n- `... from ... text should contain \"...\"` - verify that text of the element\n(provided in **object** from **page** as CSS or XPath selector) contains the\ntext (provided in \"\" as a string).\n- `\"...\".\"...\" text should contain \"...\".\"...\"` - verify that text of the\nelement (provided in **\"page1\".\"object1\"** as CSS or XPath selector) contains\nthe text (provided in **\"page2\".\"object2\"**).\n- `... from ... text should contain ... from ...` - verify that text\nof the element (provided in **object1** from **page1** as CSS or XPath selector)\ncontains the text (provided in **object2** from **page2**).\n41. `URL should be \"...\"` - verify that URL of the current page equals to the\ntext (provided in \"\" as a string).\n- `URL should be \"...\".\"...\"` - verify that URL of the current page equals to\nthe text (provided in **\"page\".\"object\"**).\n- `URL should be ... from ...` - verify that URL of the current page equals to\nthe text (provided in **object** from **page**).\n42. `URL should contain \"...\"` - verify that URL of the current page contains\nthe text (provided in \"\" as a string).\n- `URL should contain \"...\".\"...\"` - verify that URL of the current page\ncontains the text (provided in **\"page\".\"object\"**).\n- `URL should contain ... from ...` - verify that URL of the current page\ncontains the text (provided in **object** from **page**).\n43. `\"...\".\"...\" attribute \"...\" should contain \"...\"` - verify that the\nattribute (provided in \"\" as a string) of the element (provided in\n**\"page\".\"object\"**) contains provided string (provided in \"\" as a string).\n- `... from ... attribute \"...\" should contain \"...\"` - verify that the\nattribute (provided in \"\" as a string) of the element (provided in\n**\"page\".\"object\"**) contains provided string (provided in \"\" as a string).\n\n## Bonus feature: use XPath selectors in TestCafe\nAs you know TestCafe does not support XPath selectors out of the box. But now\nyou can use them in TestCafe Cucumber steps - just write XPath selector in\na Page Object file the same way as you do with CSS selectors - see the example\nin [`test1-page.js`](https://github.com/Marketionist/testcafe-cucumber-steps/blob/master/tests/page-model/test1-page.js).\nIt can also be used in your custom Cucumber steps - for example:\n```javascript\nconst SelectorXPath = require('testcafe-cucumber-steps/utils/selector-xpath.js');\n\nconst buttonStartTest = SelectorXPath('//*[ancestor::*[@class=\"test-panel\"] and contains(text(), \"Start test\")]');\n```\n\n## Contributing\nYou are welcome to contribute to this repository - please see\n[CONTRIBUTING.md](https://github.com/Marketionist/testcafe-cucumber-steps/blob/master/CONTRIBUTING.md)\nto help you get started. It is not mandatory, so you can just create a pull\nrequest and we will help you refine it along the way.\n\n## Thanks\nIf this package was helpful to you, please give it a **★ Star** on\n[GitHub](https://github.com/Marketionist/testcafe-cucumber-steps).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarketionist%2Ftestcafe-cucumber-steps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarketionist%2Ftestcafe-cucumber-steps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarketionist%2Ftestcafe-cucumber-steps/lists"}