Protractor wait for db connection

1.6k views Asked by At

I am trying to connect to my db before executing the below test, it seems that because of the callbacks Protractor doesn't waits for the DB connection. Here is my code:

describe('dashboard e2e test', function () {
  var pg = require('pg');
  var conString = "****";
  var dbClient;

  beforeEach(function() {
    function connectToDB() {
      console.log("----Connecting----");
      pg.connect(conString, function (err, client) {
        var defer = protractor.promise.defer();
        if (!err) {
          console.log("----Connected----");
          dbClient = client;
          defer.fulfill(dbClient);
        } else {
          console.error('error fetching client from pool', err);
          defer.reject(err);
        }

        return defer.promise;
      });
    }

    var flow = protractor.promise.controlFlow();
    flow.execute(connectToDB);
  });

  it('should able to connect to db', function () {
    console.log("----ittttt----");
    expect(dbClient !== undefined).toEqual(true);
  });
});

Here is my output:

[launcher] Running 1 instances of WebDriver
----Connecting----
----ittttt----
F

Failures:

  1) dashboard e2e test should able to connect to db
   Message:
     Expected false to equal true.
   Stacktrace:
     Error: Expected false to equal true.

Finished in 0.037 seconds
1 test, 1 assertion, 1 failure

----Connected----

How can I make it do the assertion after db connection?

1

There are 1 answers

1
Delian Mitankin On BEST ANSWER

To handle asynchronous calls outside of protractor's domain it's best to stick to the control-flow. Essentially, it is a queue of promises that are resolved one-by-one in the order they came in. That's how Selenium works to make sure that it executes the actions and assertions you pass to it in the proper order. The beauty of it is that each action you take with an element places a promise on the control-flow automatically. Protractor patches jasmine's expect function to also put a promise on the control-flow instead of trying to assert things right away.

Now, for your test things may look a bit convoluted:

var pg = require('pg');
var conString = "****";
var dbClient;

var connect = function () {
  var prom = protractor.promise.defer();

  pg.connect(conString, function (err, client, done) {
    if (!err) {
      console.log("1");
      dbClient = client;
      prom.fulfill(client);
    } else {
      return console.error('error fetching client from pool', err);
    }
  });

  return prom.promise;
}

var log2 = function () {
  console.log(2);
}

describe('dashboard e2e test', function () {

  it('should able to connect to db', function () {
    var flow = browser.controlFlow();    
    flow.execute(connect);    
    flow.execute(log2);    
  });
});    

but in a real-world-scenario it would most probably be something like:

describe('dashboard e2e test', function () {
  it('should able to connect to db', function () {
    var flow = browser.controlFlow();    

    #register the click function on the control-flow
    element(by.css('some-button')).click();

    # wait for the click and do the db-operation
    flow.execute(connect);

    #wait for the db-operation above to finish and assert something
    var warning = element(by.css('.warning'));
    expect(warning.getText()).toContain('stuff');
  });
});    

Regarding your updated question, you are almost there:

function connectToDB() {
  console.log("----Connecting----");
  var defer = protractor.promise.defer();
  pg.connect(conString, function (err, client) {
    if (!err) {
      console.log("----Connected----");
      dbClient = client;
      defer.fulfill(dbClient);
    } else {
      console.error('error fetching client from pool', err);
      defer.reject(err);
    }
  });

  return defer.promise;
}