1

I am working on a test that detects information of different select entries (here: vehicles) and will check if this vehicle can order a product.

The value for price and name can be and i have it in the "generalData" Object, but not for the selected vehicle the name and status...

var TestData = require('./testdata.js');
var TD = new TestData();
var generalData = TD.generalData;

(doing logging, open page)
                    PDP.elementPrice.getText().then(function (value) {
                        value = value.replace(/[^0-9\.,-]+/g, "");
                        generalData.articleData.price = value;
                        console.log(value);
                    });
                    PDP.elementArticleNumber.getText().then(function (value) {
                        generalData.articleData.number = value;
                        console.log(value);
                    });

Starting here, no value is saved to GeneralData Object

    PDP.elementCarList.count().then(function (value) {
                                console.log("Fahrzeuge: " + value);
                                vehicles = parseInt(value, 16);
                                for (var car = 0; car < vehicles; ++car) {
                                    console.log(car);


PDP.elementCarList.get(car).getAttribute("data-testid").then(function (value) {
                                            value = value.split("-").pop();
                                            generalData.articleData.fin = value
                                            console.log(value);
                                        });
                                        PDP.selectCar(car);
                                        PDP.elementSelectCar.getText().then(function (value) {
                                            generalData.articleData.vehicle = value;
                                            console.log(value);
                                        });                            PDP.elementStatus.getAttribute("class").then(function (value) {
                                            value = value.split("-").pop();
                                            generalData.articleData.status = value;
                                            console.log(value);
                                        });
                                        expect(PDP.elementStatus).toBeDefined();
                                        var options = buildSendOptions(generalData);
                                        request(options, callback);
                                    }
                                });
halfer
  • 19,824
  • 17
  • 99
  • 186
Stefanie Uhl
  • 166
  • 1
  • 2
  • 11

2 Answers2

1

A promise .then() handler is called asynchronously sometime LATER after the rest of your code has executed. The ONLY place you can use the value passed to a .then() handler is inside of that handler or in a function you call from that handler and pass the data to it.

You cannot use the value outside the .then() handler like you are attempting to do. Here's some explanation:

PDP.elementPrice.getText().then(function (value) {
    // you must use value here inside this code block, not outside this
    value = value.replace(/[^0-9\.,-]+/g, "");
    console.log(value);

    // this will not do you much good because your code
    // will not know when the new price value has been set
    generalData.articleData.price = value;
});
// this line of code is executed BEFORE then above .then() handler is called
// as such, you cannot use the value of generalData.articleData.price here

Here's a simple example:

console.log("1");
someAsync().then(function(value) {
    // this is the only place you can reliably use value
    console.log("2");
});
console.log("3");

This will show in the console as:

 1
 3
 2

That's because the result of the async operation happens AFTER the rest of your inline code executes.


One possibility for a solution to your issue is to run your two operations in parallel, use Promise.all() to know when they're both done and then nest the rest of your code inside the .then() handler:

let p1 = PDP.elementPrice.getText().then(function (value) {
    value = value.replace(/[^0-9\.,-]+/g, "");
    generalData.articleData.price = value;
    console.log(value);
});
let p2 = PDP.elementArticleNumber.getText().then(function (value) {
    generalData.articleData.number = value;
    console.log(value);
});
Promise.all([p1, p2]).then(function() {
    // put your code in here that wants to use generalData.articleData
}).catch(function(err) {
    // handle error here
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Could you please give me a sample how to solve it? I am still a newbie at this... – Stefanie Uhl Aug 16 '16 at 07:55
  • @StefanieZachmann - You need to chain or nest your promises so you can use the results of a prior asynchronous operation. Here are some ideas: [How to chain and share prior results with Promises](http://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with-promises/28714863#28714863). – jfriend00 Aug 16 '16 at 07:57
  • That was the solution. Didn't know that :) Thank you – Stefanie Uhl Aug 23 '16 at 07:41
  • @StefanieZachmann - If this answered your question, then you can indicate that to the community by clicking the green checkmark to the left of the answer. This will also earn you some reputation points for following the proper procedure here. – jfriend00 Aug 23 '16 at 13:50
1

@jfriend00's explanation is really great. In addition to that, here is a practical example how you resolve and use multiple promises specifically in Protractor:

var p1 = PDP.elementPrice.getText().then(function (value) {
    return value.replace(/[^0-9\.,-]+/g, "");
});
var p2 = PDP.elementArticleNumber.getText();

protractor.promise.all([p1, p2]).then(function(values) {
    var price = values[0],
        number = values[1];

    // do something with price and number
});

In other words, operate and pass around promises. Whenever you need an actual value - resolve.

Also see:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195