1

I am new to protractor and javascript. I am building a test framework where each test suit has corresponding module file and locator file. In test cases of test suit file , test modules are being called by passing parameter. When i am trying to nest the called function with then i am getting "TypeError: Cannot read property 'then' of undefined". I saw many solutions on stack overflow where promise was not returned but i am returning promise from called function. Below are files of code.

UserPage.js // Test suit from where modules are called

var d = require("../Data/TestCaseData.js");
var login = require("../Modules/LoginPageModule.js");
var user = require("../Modules/UserPageModule.js");
var userl = require("../Locators/UserPageLocators");

describe('first test suit',function(){

    beforeEach(function(){

           browser.get(d.iManUrl).then(function(){
            browser.manage().window().maximize();
            login.OSPLogin(d.username,d.password);
        })
    });

    it ('Creating user',function(){
        var person = {'Username' : 'u6' , 'Context' : 'novell' , 'Last name' : 'last' , 'Password' : 'n'};

        user.InputData(person).then(function(){
        //some steps
        };

    })


})

Below is module :

/**
 * UserPageModule.js
 */
var obj = require("../Locators/LoginPageLocators");
var landing = require("../Locators/LandingPageLocators");
var user = require("../Locators/UserPageLocators");

var usercreated = false;

function UserPageModule(){

    this.InputData = function(person){

        this.InputUserPasswordContext(person).then(function(person){

            this.fill =function(data){
                for (var key in data) {
                      console.log(key);
                      element(by.xpath(user.identificationAddValueButtonXpath.replace("Input Field", key))).click();
                      element(by.css(user.identificationValueInputCss)).sendKeys(person [ key ]);
                      element(by.buttonText(user.identificationAcceptValueButtonText)).click();               
                    }
            }
            return new Promise(function(resolve,request){
                 return resolve(this.fill(person));
            })
        });
    }

    /*this.InputData = function(person){
        this.InputUserPasswordContext(person).then(function(person){
            this.InputFields(person);
        });
    }*/


    this.InputUserPasswordContext = function(person){
            return new Promise(function(resolve,reject){
                //Navigating to user page
                element(by.css(landing.userLinkCss)).click();

                //Clicking on add button
                element(by.css(user.createuserButtonCss)).click();

                //Inputting Username
                element(by.css(user.usernameInputCss)).sendKeys(person.Username).then(function(){
                    delete person.Username;
                });

                //Input password
                element(by.css(user.identificationPasswordInputCss)).sendKeys(person.Password);
                element(by.css(user.identificationRetypeInputCss)).sendKeys(person.Password).then(function(){
                    delete person.Password;
                });

                //Inputting context
                element(by.css(user.contextInputCss)).sendKeys(person.Context).then(function(){
                    delete person.Context;
                }).then(function(){
                    resolve(person);
                })
            })                  
    }




}

module.exports = new UserPageModule

Now i am feeling how easy it was to make a modular test framework with java and selenium.

Pankaj Kumar
  • 61
  • 2
  • 9
  • Could you copy the full error text so we can tell exactly where the error is occurring? And yes, I agree with your sentiments about Java and Selenium but when you get it working Protractor really is best for Angular pages.... – C. Peck Mar 09 '19 at 20:11
  • @C.Peck Now with one of answers(after including return) i am not getting the error. But now then block is getting executing before 'for loop' execution of InputData is finished. – Pankaj Kumar Mar 10 '19 at 13:35

2 Answers2

1

You missed return at the top level of function InputData.

this.InputData = function(person){

        return this.InputUserPasswordContext(person).then(function(person){....
yong
  • 13,357
  • 1
  • 16
  • 27
  • Your input removed error, but now then block is getting executed before InputData is finished execution. That is ; user.InputData(person).then(function(){ element(by.buttonText("Create")).click(); }); . Here , element(by.buttonText("Create")).click(); is getting executed before 'this.fill'(see main question) is executed. – Pankaj Kumar Mar 10 '19 at 07:42
  • Frankly i don't understand promises and javascript properly. I researched a lot on internet but could not find proper material to deal with protractor promises. Some people have discussed about 'defer' but i could not understand properly. Is defer helpful in such cases. https://bridge360blog.com/2015/05/05/improving-protractor-tests-using-shared-functions-and-promises/ – Pankaj Kumar Mar 10 '19 at 07:53
  • I was under impression that 'return resolve(this.fill(person));' will first execute this.fill(person) before returning. – Pankaj Kumar Mar 10 '19 at 07:57
0

That error you're getting is common, and can be caused because of a missing return in your beforeEach function; most likely you need a return before the browser.get() if you're adding a .then() to it. I'm not entirely sure tho, but try the following:

beforeEach(function(){
    return browser.get(d.iManUrl).then(function(){
        browser.manage().window().maximize();
        login.OSPLogin(d.username,d.password);
    });
});
Joaquin Casco
  • 704
  • 5
  • 14