javascriptreactjsmethod-chainingnightwatch

Making a custom group of defined chaining methods in js


The question is related to general js programming, but I'll use nightwatch.js as an example to elaborate my query.

NightWatch JS provides various chaining methods for its browser components, like: -

 browser
    .setValue('input[name='email']','example@mail.com')
    .setValue('input[name='password']', '123456')
    .click('#submitButton')

But if I'm writing method to select an option from dropdown, it requires multiple steps, and if there are multiple dropdowns in a form, it gets really confusing, like: -

 browser
    .click(`#country`)
    .waitForElementVisible(`#india`)
    .click(`#india`)
    .click(`#state`)
    .waitForElementVisible(`#delhi`)
    .click(`#delhi`)

Is it possible to create a custom chaining method to group these already defined methods? For example something like:

/* custom method */
const dropdownSelector = (id, value) {
    return this
        .click(`${id}`).
        .waitForElementVisible(`${value}`)
        .click(`${value}`)
} 

/* So it can be used as a chaining method */
browser
    .dropdownSelector('country', 'india')
    .dropdownSelector('state', 'delhi')

Or is there any other way I can solve my problem of increasing reusability and readability of my code?


Solution

  • I'm somewhat new to JS so couldn't tell you an ideal code solution, would have to admit I don't know what a proxy is in this context. But in the world of Nightwatch and test-automation i'd normally wrap multiple steps I plan on reusing into a page object. Create a new file in a pageObject folder and fill it with the method you want to reuse

    So your test...

    browser
    .click(`#country`)
    .waitForElementVisible(`#india`)
    .click(`#india`)
    .click(`#state`)
    .waitForElementVisible(`#delhi`)
    .click(`#delhi`)
    

    becomes a page object method in another file called 'myObject' like...

    selectLocation(browser, country, state, city) {
      browser
        .click(`#country`) <== assume this never changes?
        .waitForElementVisible(country)
        .click(country)
        .click(state)
        .waitForElementVisible(city)
        .click(city);
    }
    

    and then each of your tests inherit the method and define those values themselves, however you chose to manage that...

    const myObject = require ('<path to the new pageObject file>')
    
    module.exports = {
      'someTest': function (browser) {
        const country = 'something' 
        const state = 'something'
        const city = 'something'
    
        myObject.selectLocation(browser);
    

    You can also set your country / state / city as variables in a globals file and set them as same for everything but I don't know how granular you want to be.

    Hope that made some sense :)