2

I created a small api to generate test data on the fly. Each call creates a fresh user and returns the created data.

To load the data I use the package request:

var flow = protractor.promise.controlFlow();
var result = flow.execute(function() {
    var defer = protractor.promise.defer();
    request('http://localhost/test/recipe/person', function (error, response, body) {
        if (!error && response.statusCode === 200) {
            defer.fulfill(JSON.parse(body));
        }
    });
    return defer.promise;
});

To make any use of the retrieved data I have to resolve the promise and proceed the test script inside a callback:

result.then(function(data) {
    element(by.model('username')).sendKeys(data.person.email);
    element(by.model('password')).sendKeys('test');
    $('button[type="submit"]').click();
});

I don't like this callback handling and the possible hell it will lead to. Besides that, Protractor is so good in hiding this messy callback handling thingy. So, the question is:

How to use the result of an async call?

At the end I would like to perform code like the following:

var flow = protractor.promise.controlFlow();
var result = flow.execute(function() {...});

element(by.model('username')).sendKeys(result.person.email);
//...

Any ideas?

scheffield
  • 6,618
  • 2
  • 30
  • 31
  • Closing as duplicate - short answer: You really can't in a good way, if you do it, it will slow your tests down _a whole lot_ and they'll act unreliable in terms of performance. Long answer is in the duplicate question. If you feel that the duplicate I found does not cover your issue (I believe it really does) - let me know and I'll reopen this. – Benjamin Gruenbaum May 16 '14 at 23:32
  • @BenjaminGruenbaum: I don't think it's an exact duplicate. The different is the environment in which the ajax call is made. On the one side you have an event driven client in which blocking IO means a blocked UI. On the other side you have a test execution framework which key feature it is to execute subsequent async calls in one line as they where synchronous calls. – scheffield May 17 '14 at 07:49
  • Suit yourself, I think the core problem is _exactly_ the same here, but I've reopened it – Benjamin Gruenbaum May 17 '14 at 11:26

2 Answers2

5

You can either make the http request synchronous - In most cases that's a bad thing to do.
Or, you can insert the callback into the execute function:

var flow = protractor.promise.controlFlow();
var result = flow.execute(function() {
    var defer = protractor.promise.defer();
    request('http://localhost/test/recipe/person', function (error, response, body) {
        if (!error && response.statusCode === 200) {
            defer.fulfill(JSON.parse(body));
        }
    });

    defer.promise.then(function(data) {
       element(by.model('username')).sendKeys(data.person.email);
       element(by.model('password')).sendKeys('test');
       $('button[type="submit"]').click();
    });

    return defer.promise;
});

but result will stay a promise.

Amir Popovich
  • 29,350
  • 9
  • 53
  • 99
1

It worked for me:

var request = require('request');

var options = {
  method: 'POST',
  url: 'http://testurl.com/endpoint/test/',
  headers: {'id': 'ABCD',
    'sessionid': 'dummyId',
    'Accept': 'application/json',
    'Accept-Language': 'en-us'
  },
  body: '{ "pay_load": [] }'
};

function callback(error, response, body) {
  if (!error && response.statusCode == 200) {
    var info = JSON.parse(body);
    console.log(body);
    console.log(info);
  }
}

request(options, callback);
Prashant Goel
  • 141
  • 1
  • 7