'undefined' value when using the callback function on getValue to set a variable within a test group

1,014 views
Skip to first unread message

Andrew McMurtrie

unread,
Apr 23, 2014, 10:24:14 PM4/23/14
to nightw...@googlegroups.com
I thought I would post the outcome from resolving a problem with setting a variable from the getValue or getText callback function and using within the same test step.

We have a project I have started writing tests for (I'm new to nightwatch and selenium) that required checking the values entered into a form are displayed later in a summary page (sounds easy).

Scenario:
I had trouble with a couple of date-picker fields that can't be set using setValue because it is effectively sending key strokes and the field validation was too controlling for that to work so I had to directly interact with the date-picker itself to set the date value. Once the values are set I wanted the result of that from the input field so I can use it later in the same test.

Code structure:
I have a create_project.js file with a couple of variables defined at the top level one of which stores an array of details to enter into the form, there are functions defined for entering those details into the form and also for checking the summary values and then there is the test group with a number of steps defined.

I had defined the first step as createProject and within that test step the function for populating the form was called, project creation was completed and the summary page displayed. The details var is set just prior to the function call to populate the data but is declared at the top of the file so the scope is global to everything in the file. 
Within the function to populate the form I had the following code to manipulate the date-pickers and get the values:


   
//datepicker needs special handling as we can't just edit the field
   
.click('input[name="project.startDate"]')
   
.pause(500)
   
.waitForElementVisible('a[class~="ui-datepicker-next"]',10000)
   
.click('td.ui-datepicker-today a')
   
.pause(1000)
   
.getValue('input[name="project.startDate"]', function(result){
        details
['startDate'] = result.value;
     
})
   
.click('input[name="project.endDate"]')
   
.pause(500)
   
.waitForElementVisible('a[class~="ui-datepicker-next"]',10000)
   
.click('a[class~="ui-datepicker-next"]')
   
.pause(1000)
   
.click('td[data-handler="selectDay"]:last-child a')
   
.pause(1000)
   
.getValue('input[name="project.endDate"]', function(result){
        details
['endDate'] = result.value;
     
})



The Problem:
If I tried to check the values in the summary against what I had from the creation process within the createProject test step it would fail saying what containsText was expecting to find was 'undefined' and not that date from the field. details['startDate'] = 'undefined' when checking it within the same test step. I thought it might be scope problems or async problems but nothing I did gave me a value. and console.log(details['startDate']) positioned at the end of the createProject code always displayed first when running the test with an undefined value.

Here are the tests run against the summary page:

   
//start and end dates need to be in a shorter format
     
.assert.containsText('span[ng-bind~="project.startDate"]', details['startDate'].substring(0,6) + details['startDate'].substring(8))
     
.assert.containsText('span[ng-bind~="project.endDate"]', details['endDate'].substring(0,6) + details['endDate'].substring(8))


The Cause:
It seems that the createProject test step is processed before it is run and so the value of variable details is set at that point by its set declaration which in my case doesn't include 'startDate' or 'endDate', they are added when the date picker is manipulated. So the value for those two items in the details array are undefined and seems to remain that way as far as the createProject test step is concerned even though it is set during the step.

The Solution:
I created a new step checkSummary and moved the call to the function that checks against the summary page into that test step and suddenly the values appeared in the details array. It seems that the new step is processed with the updated details values from the previous step and everything works. I had been confused when I hit this problem because I was getting the ID for the created project from the summary page and using it fine in other test steps for editing and deleting the same project but it was never used within the same step as it was set so no problem. 

Andrei Rusu

unread,
Apr 25, 2014, 4:59:13 AM4/25/14
to nightw...@googlegroups.com
Thank you for your elaborate post, I'm sure it will be very useful for others. Maybe you can also show the code for the working solution?

Cheers,
Andrei

Andrew McMurtrie

unread,
Apr 25, 2014, 7:26:35 AM4/25/14
to nightw...@googlegroups.com
I wont post the exact code but I will give you the sort of thing that will fail and that which will work.

The following will give you an undefined value using a getValue callback in the same test step.

'use strict';

var fieldValue; 

module.exports = {
  'My Test': function(client){ 
    client
      .url('http://localhost')
      .waitForElementVisible('body', 2000)
      .getValue('#someInputField', function(result){
        fieldValue = result.value;
   }
//additional tests here and any number of pauses
........
//this will run at the very start with an undefined value
    console.log(fieldValue);
    client
      //this will fail because it will look for 'undefined'
      .assert.containsText('#someSummaryDiv', fieldValue);
      .end();
};

If we add a second test step to this code and move the test that reuses the value within it, the value becomes available:
'use strict';

var fieldValue; 

module.exports = {
  'My Test': function(client){ 
    client
      .url('http://localhost')
      .waitForElementVisible('body', 2000)
      .getValue('#someInputField', function(result){
        fieldValue = result.value;
    }
//additional tests here and any number of pauses
........
//this will run at the very start with an undefined value
    console.log(fieldValue);
  },
  'My Test second step': function(client){ 
    client
      //this will work because fieldValue is no longer 'undefined'
      console.log(fieldValue); //this will display a value and not 'undefined'
      .assert.containsText('#someSummaryDiv', fieldValue);
      .end();
 }
};

Hope this clarifies.


Andrew McMurtrie

unread,
Apr 25, 2014, 7:29:49 AM4/25/14
to nightw...@googlegroups.com
'My Test second step': function(client){
    client
     
//this will work because fieldValue is no longer 'undefined'
      console
.log(fieldValue); //this will display a value and not 'undefined'
     
.assert.containsText('#someSummaryDiv', fieldValue);
     
.end();


should be:

'My Test second step': function(client){

      console
.log(fieldValue); //this will display a value and not 'undefined'

    client
     
//this will work because fieldValue is no longer 'undefined'
Reply all
Reply to author
Forward
0 new messages