-1

If I have multiple functions written inside a Nightwatch script - like the ones below - how can I move them outside the script in order to be used by other scripts too?

function firstFunction (aaa, callback) {
    // do async stuff
    callback(result)
}

function secondFunction (bbb, callback) {
    firstFunction (aaa, function (result) {
    // do async stuff
    callback(result)
    }
}

secondFunction (ccc, function (result) {
    // script actions/verifications
}

I would like to keep only the last part (the script actions) inside my script and move the functions outside in order to be used by other scripts too.

LE: I created a separate folder named Utils where I created 2 files - getColumnValues.js and getTableColumns.js (my functions that are working inside the script).

The content of my files:

// getTableColumns.js (first function)

exports.getTableColumns = function (tableSelector, callback) {
    var columnNames = [];
    var tableHeaderSelector = tableSelector + ' > tbody > tr:nth-of-type(1) > th';
    this.api.elements('css selector', tableHeaderSelector, function (objectResults) {
        for (var i in objectResults.value) {
            this.elementIdAttribute(objectResults.value[i].ELEMENT, 'innerText', function(result) {
                columnNames.push(result.value);
                if (columnNames.length == objectResults.value.length) {
                    callback(columnNames);
                }
            });
        }
    });
}

// getColumnValues.js (second function)

var path = require('path'); var utils = require( path.resolve( __dirname, "./getTableColumns" ) );

exports.getColumnValues = function (columnName, tableSelector, callback) {
    utils.getTableColumns(tableSelector, function (columnList) {
        var columnIndex = columnList.indexOf(columnName) + 1;
        var columnValues = [];
        cellSelector = tableSelector + ' > tbody > tr:nth-of-type(3) > td:nth-of-type(' + columnIndex + ')';
        this.api.element('css selector', cellSelector, function (objectResult) {
            this.elementIdAttribute(objectResult.value.ELEMENT, 'childElementCount', function(result1) {
                for (var j = 2; j < 22; j++) {
                    cellSelector = tableSelector + ' > tbody > tr:nth-of-type(' + j + ') > td:nth-of-type(' + columnIndex + ')';
                    this.api.element('css selector', cellSelector, function (objectResult) {
                        this.elementIdAttribute(objectResult.value.ELEMENT, 'innerText', function(result) {
                            columnValues.push(result.value);
                            if (columnValues.length == 20) {
                                callback(columnValues);
                            }
                        });
                    });             
                }
            });
        }); 
    });
}

//myScript.js

var utils = require('../../lib/utils/getColumnValues.js');
utils.getColumnValues('Route', 'table.table-striped', function (result) {
//do something
}

When I ran the script like this, I get this error: "ReferenceError: client is not defined at Object.exports.getTableColumns (C:\automation\lib\utils\getTableColumns.js:4:9) at Object.exports.getColumnValues (C:\automation\lib\utils\getColumnValues.js:5:15)"

If I change client with this.api, I get this error:

Running:  Demo test
 ✖ TypeError: Cannot read property 'elements' of undefined
    at Object.exports.getTableColumns (C:\automation\lib\utils\getTableColumns.js:4:17)
    at Object.exports.getColumnValues (C:\automation\lib\utils\getColumnValues.js:5:15)
    at Object.Demo test (C:\automation\tests\Kite\demotest1.js:55:16)
    at Module.call (C:\automation\lib\nightwatch\lib\runner\module.js:62:34)
    at C:\automation\lib\nightwatch\lib\runner\testcase.js:70:29

FAILED:  1 errors (15ms)

 _________________________________________________

 TEST FAILURE: 1 error during execution,  0 assertions failed, 0 passed. (93ms)

 × Kite\demotest1

   - Demo test (15ms)

     Error while running [Kite / Demotest1 / Demo test]:

     TypeError: Cannot read property 'elements' of undefined
       at Object.exports.getTableColumns (C:\automation\lib\utils\getTableColumns.js:4:17)
       at Object.exports.getColumnValues (C:\automation\lib\utils\getColumnValues.js:5:15)
       at Object.Demo test (C:\automation\tests\Kite\demotest1.js:55:16)
       at Module.call (C:\automation\lib\nightwatch\lib\runner\module.js:62:34)
       at C:\automation\lib\nightwatch\lib\runner\testcase.js:70:29
dorin123
  • 15
  • 1
  • 5

1 Answers1

0

Yes:

  1. Create a file with your functions, and expose them as a module
  2. Use your function in both scripts by requiring the file you previously created

As simple as that:

// utils/getTableColumns
// Note the first argument: client
exports.getTableColumns = (client, tableSelector, callback) => {
  // use the client here
  client.api.element('css selector', tableSelector, () => {
    callback();
  });
}

In your second file:

var utils = require('../../lib/utils/getColumnValues.js');


describe("suite" , () => {
  it("should test", test);
});

function test(client){
  // Pass the client as an argument
  utils.getColumnValues(client, 'Route', 'table.table-striped', function (result) {
    //do something
  }
}
ghusse
  • 3,200
  • 2
  • 22
  • 30
  • I added more details in the initial comment about how I am trying to fix this using your suggestion. I still receive some errors when I try to run the script. Any suggestion is welcomed. Thanks. – dorin123 Apr 24 '17 at 05:29
  • Can you update the code you're using and post the errors? – ghusse Apr 24 '17 at 06:09
  • I updated the functions and the error message. Please let me know if you need anything else. – dorin123 Apr 24 '17 at 09:11
  • I edited my response to show you how to use the client – ghusse Apr 24 '17 at 09:31