Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Protractor: Execute Scripts in Browser Context

In my index.html, I explicitly say:

window.myAppInstance = new MyApp.myAppConstructor();

In my todo-spec.js, I have the following setup:

describe('my web page', function() {
  it('should have a "myAppInstance" object on the window', function() {
    browser.get('https://my.web.page.com');

    function myTest() {
      return Object.keys(window.myAppInstance).sort();
    };

    var p = browser.driver.executeScript(myTest);
     p.then(function(ret) {
        console.log("yay");
        console.log(ret);
     }, function() {
        console.log("error");
        console.log(arguments);
     });
  });
});

But protractor doesn't find my app. Instead it finds null or undefined:

error
{ '0':
   { [WebDriverError: unknown error: Cannot convert undefined or null to object
 (Session info: chrome=50.0.2661.102)
... and more garbage

But from Chrome's console, I can run

window.myAppInstance

just fine, and it prints out the object properly.

How can I access this window object from my protractor test?

Edit 1: More explicit about the constructors.

Edit 2: In my app, I'm using angular's manual bootstrapping. Upon further investigation, I can add this line to my test:

<snip>
  browser.get('https://my.web.page.com');
  **browser.pause()**
<snip>

My steps now: 1) Hit F12 to bring up Chrome's developer tools 2) Look in the console. Note an error. My app has crashed. 3) Manually hit the refresh button on the browser. 4) Note how the app refreshes and everything loads beautifully. Scratch my head in puzzlement. Conclude that it's probably that somehow, launching the page programmatically with

browser.get('https://my.web.page.com'); 

is different enough from opening the browser up and typing in that URL to break it.

I'm wondering now, What about running the tests with protractor would cause my app to fail?

like image 919
Bill Avatar asked May 13 '16 22:05

Bill


2 Answers

There could be a timing issue - the value is not yet available and you might need to wait for it:

function waitForKey() {
  return browser.executeScript("return window.myAppXXXXXXXXXXXXX");
}

browser.wait(waitForKey, 5000);
var p = browser.executeScript(myTest);
// ...
like image 139
alecxe Avatar answered Oct 22 '22 13:10

alecxe


Your object myAppXXXXXXXXXXXXX is probably not yet instantiated at the time myTest is executed. If that's the case, then one solution is to call executeAsyncScript instead to return the keys of your object once the object is present:

function myTest(callback){
  if (window.myAppXXXXXXXXXXXXX) {
    callback(Object.keys(window.myAppXXXXXXXXXXXXX).sort());
  } else {
    setTimeout(myTest, 30);  // try again in 30ms
  }
}

browser.driver.executeAsyncScript(myTest)
  .then(function(ret) {
    console.log("yay");
    console.log(ret);
  }, function() {
    console.log("error");
    console.log(arguments);
  });
like image 24
Florent B. Avatar answered Oct 22 '22 12:10

Florent B.