All Projects → john-doherty → Selenium Cucumber Js

john-doherty / Selenium Cucumber Js

Licence: isc
Browser automation framework written in pure JavaScript using official selenium-webdriver and cucumber-js

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Selenium Cucumber Js

bdd-for-all
Flexible and easy to use library to enable your behavorial driven development (BDD) teams to easily collaborate while promoting automation, transparency and reporting.
Stars: ✭ 42 (-61.11%)
Mutual labels:  bdd, test-automation
demo-webdriverio-cucumber
E2E Tests with WebdriverIO and Cucumber
Stars: ✭ 28 (-74.07%)
Mutual labels:  bdd, selenium-webdriver
karate
Test Automation Made Simple
Stars: ✭ 6,384 (+5811.11%)
Mutual labels:  bdd, test-automation
Cdp4j
cdp4j - Chrome DevTools Protocol for Java
Stars: ✭ 232 (+114.81%)
Mutual labels:  test-automation, selenium-webdriver
Jgiven
Behavior-Driven Development in plain Java
Stars: ✭ 319 (+195.37%)
Mutual labels:  test-automation, bdd
Ocaramba
C# Framework to automate tests using Selenium WebDriver
Stars: ✭ 234 (+116.67%)
Mutual labels:  test-automation, selenium-webdriver
neodymium-library
A test automation library based on common other best practice open source libraries. It adds missing functionalities but does not reinvent the wheel. Just glues stuff together nicely and adds some sprinkles.
Stars: ✭ 70 (-35.19%)
Mutual labels:  bdd, test-automation
featurebook
A command line tool (and Node.js library) for generating beautiful system specifications from Gherkin source files.
Stars: ✭ 40 (-62.96%)
Mutual labels:  bdd, test-automation
atata-kendoui
A set of Atata components for Kendo UI
Stars: ✭ 17 (-84.26%)
Mutual labels:  test-automation, selenium-webdriver
page-modeller
⚙️ Browser DevTools extension for modelling web pages for automation.
Stars: ✭ 66 (-38.89%)
Mutual labels:  test-automation, selenium-webdriver
Gauge
Light weight cross-platform test automation
Stars: ✭ 2,622 (+2327.78%)
Mutual labels:  test-automation, bdd
Cucumberjvmexamples
Cucumber JVM with Selenium Java
Stars: ✭ 98 (-9.26%)
Mutual labels:  test-automation, bdd
Selenium extensions
Tools that will make writing tests, bots and scrapers using Selenium much easier
Stars: ✭ 140 (+29.63%)
Mutual labels:  test-automation, selenium-webdriver
SHAFT ENGINE
SHAFT is an MIT licensed test automation engine. Powered by best-in-class frameworks like Selenium WebDriver, Appium & RestAssured it provides a wizard-like syntax to increase productivity, and built-in wrappers to eliminate boilerplate code and to ensure your tests are extra stable and your results are extra reliable.
Stars: ✭ 170 (+57.41%)
Mutual labels:  test-automation, selenium-webdriver
karate-runner
VSCode Extension for Karate
Stars: ✭ 23 (-78.7%)
Mutual labels:  bdd, test-automation
Atata
C#/.NET test automation framework for web
Stars: ✭ 362 (+235.19%)
Mutual labels:  test-automation, selenium-webdriver
Karate
Test Automation Made Simple
Stars: ✭ 5,497 (+4989.81%)
Mutual labels:  test-automation, bdd
Coteafs Appium
📱 Wrapper Appium Framework in Java which supports Automation of Mobile and Tablet apps.
Stars: ✭ 93 (-13.89%)
Mutual labels:  test-automation
Dd
Binary Decision Diagrams (BDDs) in pure Python and Cython wrappers of CUDD, Sylvan, and BuDDy
Stars: ✭ 102 (-5.56%)
Mutual labels:  bdd
Quick
The Swift (and Objective-C) testing framework.
Stars: ✭ 9,303 (+8513.89%)
Mutual labels:  bdd

selenium-cucumber-js

npm

JavaScript browser automation framework using official selenium-webdriver and cucumber-js.

If you prefer to work with puppeteer check out puppeteer-cucumber-js

Table of Contents

Installation

npm install selenium-cucumber-js --save-dev

Usage

node ./node_modules/selenium-cucumber-js/index.js -s ./step-definitions

Options

-h, --help                          output usage information
-V, --version                       output the version number
-s, --steps <path>                  path to step definitions. defaults to ./step-definitions
-p, --pageObjects <path>            path to page objects. defaults to ./page-objects
-o, --sharedObjects [paths]         path to shared objects (repeatable). defaults to ./shared-objects
-b, --browser <path>                name of browser to use. defaults to chrome
-k, --browser-teardown <optional>   browser teardown strategy after every scenario (always, clear, none). defaults to "always"
-r, --reports <path>                output path to save reports. defaults to ./reports
-d, --disableLaunchReport           disable the auto opening the browser with test report
-j, --junit <path>                  output path to save junit-report.xml defaults to ./reports
-t, --tags <tagName>                name of tag to run
-f, --featureFile <path>            a specific feature file to run
-x, --timeOut <n>                   steps definition timeout in milliseconds. defaults to 10 seconds
-n, --noScreenshot                  disable auto capturing of screenshots when an error is encountered

By default tests are run using Google Chrome, to run tests using another browser supply the name of that browser along with the -b switch. Available options are:

Browser Example
Chrome -b chrome
Firefox -b firefox
Phantom JS -b phantomjs
Electron -b electron
Custom -b customDriver.js

To use your own driver, create a customDriver.js file in the root of your project and provide the filename with the -b switch.

Configuration file

Configuration options can be set using a selenium-cucumber-js.json file at the root of your project. The JSON keys use the "long name" from the command line options. For example the following duplicates default configuration:

{
    "steps": "./step-definitions",
    "pageObjects": "./page-objects",
    "sharedObjects": "./shared-objects",
    "reports": "./reports",
    "browser": "chrome",
    "timeout": 10000
}

Whereas the following would set configuration to match the expected directory structure of IntelliJ's Cucumber plugin, and make default timeout one minute. Note that the default browser has not been overridden and will remain 'chrome'.

{
    "steps": "./features/step_definitions",
    "pageObjects": "./features/page_objects",
    "sharedObjects": "./features/shared_objects",
    "reports": "./features/reports",
    "timeout": 60000
}

Feature files

A feature file is a Business Readable, Domain Specific Language file that lets you describe software’s behavior without detailing how that behavior is implemented. Feature files are written using the Gherkin syntax and must live in a folder named features within the root of your project.

# ./features/google-search.feature

Feature: Searching for vote cards app
  As an internet user
  In order to find out more about the itunes vote cards app
  I want to be able to search for information about the itunes vote cards app

  Scenario: Google search for vote cards app
    When I search Google for "itunes vote cards app"
    Then I should see some results

Browser teardown strategy

The browser automatically closes after each scenario to ensure the next scenario uses a fresh browser environment. But you can change this behavior with the "-k" or the "--browser-teardown" parameter.

Value Description
always the browser automatically closes (default)
clear the browser automatically clears cookies, local and session storages
none the browser does nothing

Step definitions

Step definitions act as the glue between features files and the actual system under test.

To avoid confusion always return a JavaScript promise your step definition in order to let cucumber know when your task has completed.

// ./step-definitions/google-search-steps.js

module.exports = function () {

    this.Then(/^I should see some results$/, function () {

        // driver wait returns a promise so return that
        return driver.wait(until.elementsLocated(by.css('div.g')), 10000).then(function(){

            // return the promise of an element to the following then.
            return driver.findElements(by.css('div.g'));
        })
        .then(function (elements) {

            // verify this element has children
            expect(elements.length).to.not.equal(0);
        });
    });
};

The following variables are available within the Given(), When() and Then() functions:

Variable Description
driver an instance of selenium web driver (the browser)
selenium the raw selenium-webdriver module, providing access to static properties/methods
page collection of page objects loaded from disk and keyed by filename
shared collection of shared objects loaded from disk and keyed by filename
helpers a collection of helper methods things selenium does not provide but really should!
by the selenium By class used to locate elements on the page
until the selenium until class used to wait for elements/events
expect instance of chai expect to expect('something').to.equal('something')
assert instance of chai assert to assert.isOk('everything', 'everything is ok')
trace handy trace method to log console output with increased visibility

Page objects

Page objects are accessible via a global page object and are automatically loaded from ./page-objects (or the path specified using the -p switch). Page objects are exposed via a camel-cased version of their filename, for example ./page-objects/google-search.js becomes page.googleSearch. You can also use subdirectories, for example ./page-objects/dir/google-search.js becomes page.dir.googleSearch.

Page objects also have access to the same runtime variables available to step definitions.

An example page object:

// ./page-objects/google-search.js

module.exports = {

    url: 'http://www.google.co.uk',

    elements: {
        searchInput: by.name('q'),
        searchResultLink: by.css('div.g > h3 > a')
    },

    /**
     * enters a search term into Google's search box and presses enter
     * @param {string} searchQuery
     * @returns {Promise} a promise to enter the search values
     */
    performSearch: function (searchQuery) {

        var selector = page.googleSearch.elements.searchInput;

        // return a promise so the calling function knows the task has completed
        return driver.findElement(selector).sendKeys(searchQuery, selenium.Key.ENTER);
    }
};

And its usage within a step definition:

// ./step-definitions/google-search-steps.js
this.When(/^I search Google for "([^"]*)"$/, function (searchQuery) {

    return helpers.loadPage('http://www.google.com').then(function() {

        // use a method on the page object which also returns a promise
        return page.googleSearch.performSearch(searchQuery);
    })
});

Shared objects

Shared objects allow you to share anything from test data to helper methods throughout your project via a global shared object. Shared objects are automatically loaded from ./shared-objects (or the path specified using the -o switch) and made available via a camel-cased version of their filename, for example ./shared-objects/test-data.js becomes shared.testData. You can also use subdirectories, for example ./shared-objects/dir/test-data.js becomes shared.dir.testData.

Shared objects also have access to the same runtime variables available to step definitions.

An example shared object:

// ./shared-objects/test-data.js

module.exports = {
    username: "import-test-user",
    password: "import-test-pa**word"
}

And its usage within a step definition:

module.exports = function () {

    this.Given(/^I am logged in"$/, function () {

        driver.findElement(by.name('usn')).sendKeys(shared.testData.username);
        driver.findElement(by.name('pass')).sendKeys(shared.testData.password);
    });
};

Helpers

selenium-cucumber-js contains a few helper methods to make working with selenium a bit easier, those methods are:

// Load a URL, returning only when the <body> tag is present
helpers.loadPage('http://www.google.com');

// get the value of a HTML attribute
helpers.getAttributeValue('body', 'class');

// get a list of elements matching a query selector who's inner text matches param.
helpers.getElementsContainingText('nav[role="navigation"] ul li a', 'Safety Boots');

// get first elements matching a query selector who's inner text matches textToMatch param
helpers.getFirstElementContainingText('nav[role="navigation"] ul li a', 'Safety Boots');

// click element(s) that are not visible (useful in situations where a menu needs a hover before a child link appears)
helpers.clickHiddenElement('nav[role="navigation"] ul li a','Safety Boots');

// wait until a HTML attribute equals a particular value
helpers.waitUntilAttributeEquals('html', 'data-busy', 'false', 5000);

// wait until a HTML attribute exists
helpers.waitUntilAttributeExists('html', 'data-busy', 5000);

// wait until a HTML attribute no longer exists
helpers.waitUntilAttributeDoesNotExists('html', 'data-busy', 5000);

// get the content value of a :before pseudo element
helpers.getPseudoElementBeforeValue('body header');

// get the content value of a :after pseudo element
helpers.getPseudoElementAfterValue('body header');

// clear the cookies
helpers.clearCookies();

// clear both local and session storages
helpers.clearStorages();

// clear both cookies and storages
helpers.clearCookiesAndStorages('body header');

// waits until an element to exist and returns it
helpers.waitForCssXpathElement('#login-button', 5000);

// scroll until element is visible
helpers.scrollToElement(webElement);

// select a value inside a dropdown list by its text
helpers.selectByVisibleText('#country', 'Brazil');

// waits and returns an array of all windows opened
helpers.waitForNewWindows();

Visual Comparison

The selenium-cucumber-js framework uses Applitools Eyes to add visual checkpoints to your JavaScript Selenium tests. It takes care of getting screenshots of your application from the underlying WebDriver, sending them to the Applitools Eyes server for validation and failing the test when differences are detected. To perform visual comparisons within your tests, obtain an Applitools Eyes API Key and assign it to the eye_key property of the selenium-cucumber-js.json config file in the root of your project.

For example the following configuration could be used with an increased timeout which allows enough time for visual checks:

{
  "eye_key": "Your_Api_Key",
  "timeout": 50000
}

And its usage within page Objects:

module.exports = {

    url: 'https://applitools.com/helloworld',

    elements: {
        clickme: by.tagName('button'),
        searchResultLink: by.css('div.g > h3 > a')
    },

    applitools_Eyes_Example: function () {

        // Start the test and set the browser's viewport size to 800x600.
        eyes.open(driver, 'Hello World!', 'My first Javascript test!',
            {width: 800, height: 600});

        // Navigate the browser to the "hello world!" web-site.
        driver.get(page.HelloWorld.elements.url);

        // Visual checkpoint #1.
        eyes.checkWindow('Main Page');

        // Click the "Click me!" button.
        driver.findElement(page.HelloWorld.elements.clickme).click();

        // Visual checkpoint #2.
        eyes.checkWindow('Click!');

        // End the test.
        eyes.close();
    }
};

Before/After hooks

You can register before and after handlers for features and scenarios:

Event Example
BeforeFeature this.BeforeFeatures(function(feature, callback) {})
AfterFeature this.AfterFeature(function(feature, callback) {});
BeforeScenario this.BeforeScenario(function(scenario, callback) {});
AfterScenario this.AfterScenario(function(scenario, callback) {});
module.exports = function () {

    // add a before feature hook
    this.BeforeFeature(function(feature, done) {
        console.log('BeforeFeature: ' + feature.getName());
        done();
    });

    // add an after feature hook
    this.AfterFeature(function(feature, done) {
        console.log('AfterFeature: ' + feature.getName());
        done();
    });

    // add before scenario hook
    this.BeforeScenario(function(scenario, done) {
        console.log('BeforeScenario: ' + scenario.getName());
        done();
    });

    // add after scenario hook
    this.AfterScenario(function(scenario, done) {
        console.log('AfterScenario: ' + scenario.getName());
        done();
    });
};

Reports

HTML and JSON reports are automatically generated and stored in the default ./reports folder. This location can be changed by providing a new path using the -r command line switch:

Cucumber HTML report

How to debug

Most selenium methods return a JavaScript Promise that is resolved when the method completes. The easiest way to step in with a debugger is to add a .then method to a selenium function and place a debugger statement within it, for example:

module.exports = function () {

    this.When(/^I search Google for "([^"]*)"$/, function (searchQuery, done) {

        driver.findElement(by.name('q')).then(function(input) {
            expect(input).to.exist;
            debugger; // <<- your IDE should step in at this point, with the browser open
            return input;
        })
        .then(function(input){
            input.sendKeys(searchQuery);
            input.sendKeys(selenium.Key.ENTER);

            done(); // <<- let cucumber know you're done
        });
    });
};

Directory structure

You can use the framework without any command line arguments if your application uses the following folder structure:

.
├── features
│   └── google-search.feature
├── step-definitions
│   └── google-search-steps.js
├── page-objects
│   └── google-search.js
└── shared-objects
│   ├── test-data.js
│   └── stuff.json
└── reports
    ├── cucumber-report.json
    └── cucumber-report.html

Demo

This project includes an example to help you get started. You can run the example using the following command:

node ./node_modules/selenium-cucumber-js/index.js

Bugs

Please raise bugs via the selenium-cucumber-js issue tracker and, if possible, please provide enough information to allow the bug to be reproduced.

Contributing

Everyone is very welcome to contribute to this project. You can contribute just by submitting bugs or suggesting improvements by opening an issue on GitHub.

Troubleshooting

IntelliJ Cucumber Plugin

IntelliJ based IDE's have a plugin that allows the tester to control click on a Given, When, Then statement within a Cucumber feature file and have the user taken to the associated step definition. This plugin relies on your project having the following folder structure:

.
└── features
   │   google-search.feature
   └── step_definitions
   │   └── google-search-steps.js
   └── page_objects
   │   └── google-search.js
   └── shared_objects
   │   ├── test-data.js
   │   └── stuff.json
   └── reports
       ├── cucumber-report.json
       └── cucumber-report.html

This can be achieved by restructuring your project to match the layout above (notice the underscores), and running your tests with the following switches:

node ./node_modules/selenium-cucumber-js/index.js -s ./features/step_definitions -p ./features/page_objects -o ./features/shared_objects -r ./features/reports

VSCode Cucumber Plugin

Visual Studio Code has also an extension for Cucumber (Gherkin) Language Support + Format + Steps/PageObjects Autocomplete. You can find how to install and use at Cucumber (Gherkin) Full Support.

Following the default structure, the settings.json should look like this:

{
    "cucumberautocomplete.steps": [
        "step-definitions/*.js"
    ],
    "cucumberautocomplete.syncfeatures": "features/*.feature",
    "cucumberautocomplete.strictGherkinCompletion": false,
    "cucumberautocomplete.onTypeFormat": true,
    "editor.quickSuggestions": {
        "comments": false,
        "strings": true,
        "other": true
    },
    "cucumberautocomplete.gherkinDefinitionPart": "(Given|When|Then)\\(",
}

License

Licensed under ISC License © John Doherty

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].