2

In our application we load requirejs, which in return loads angularjs, and also other javascript modules. I am wondering if there any way to get hole of these LOADED modules (angularjs, javascript modules) in protractor test. Note, we want the instance that is loaded by the browser when running Protractor, we don't want to create instance by ourselves.

Any suggestion or example?

Thanks in advance.

Jahid Shohel
  • 1,395
  • 4
  • 18
  • 34

3 Answers3

2

Nick Tomlin's answer is what you can do if a module returns serializable data structure as a value. You call require and call with the module's value the callback that executeAsyncScript gives you to allow returning asynchronous values. This will work, for instance, if your module returns "foo" or { foo: 'bar' } or structures that are generally serializable.

However, it won't always work. Complex modules cannot be retrieved that way. Roughly speaking you should expect what you send through executeScript and executeAsyncScript and what they return to have the same limitations as JSON.stringify does. One major exception is that Selenium will wrap DOM objects returned from these calls into a structure that allows to identify them on the script side, and that allows passing them back to the browser. (Then again, there are limitations there too. This is why you get stale element exceptions, for instance.)

If you try to retrieve modules that export functions, you'll probably get something but it won't be complete. Try this, for instance:

browser.executeAsyncScript(function () {
    arguments[0]({ foo: function () {}});
}).then(function (value) {
    console.log(value);
});

The output I get is:

Object { foo: Object {} }

The function has been turned into an empty object.

Community
  • 1
  • 1
Louis
  • 146,715
  • 28
  • 274
  • 320
1

I do not use angular with require.js, but i'm assuming you could access the require'd angular the same way you would in a module:

var pageAngular = browser.driver.executeAsyncScript(function () {
  var callback = arguments[arguments.length - 1];
  require(['angular'], function (angular) {
    callback(angular);
  })
});

The use of executeAsync is necessary here, since AMD modules are loaded asynchronously.

Do note that as @louis noted, the return of executeAsyncScript is going to be a serialized object, not the "live" instance of angular. If you need to interact with angular within the context of your page, you should do so within the callback torequire.

Nick Tomlin
  • 28,402
  • 11
  • 61
  • 90
0

Something like this should do it:

var angular = browser.driver.executeScript("return window.angular;");
Tim B
  • 2,340
  • 15
  • 21