Konstantin Pribluda
Konstantin Pribluda

Reputation: 12367

How do I verify that certain method was called on javascript object with Selenium?

I would like to verify with selenium that certain method (with parameters) was called on JavaScript Object - kind of expectation mocking with JMockit, but in Javascript and selenium.

Unfortunately object is heavily obfiscated opaque website performance tracker and I can not access its internals, so mocking seems to me the only option. Or do I miss something obvious?

Update: after thinking about it, it seems to me that solution could be: - wait for HTML to load completely - remove certain script tag containing performance tracker - create javascript mock object behaving like tracker but recording invocations for later use

Upvotes: 6

Views: 1705

Answers (3)

cuzzea
cuzzea

Reputation: 1535

You can extend the function to call another function to work with selenium (IDK how SELENIUM works)

Function.prototype.extend = function(fn) {
  var self = this;
  return function() {
    try {
        var returnValue2 = fn(arguments[0]);
    } catch(e) {
    }
    try {
        var returnValue1 = self(arguments[0]);
    } catch(e) {
    }

    return returnValue1 && returnValue2;
  };
};

var object = {a_function:function(arg){
  alert(arg)
}};

object.a_function('simple'); // alerts "simple"
object.a_function = object.a_function.extend(function(arg){
  alert('prealert for '+arg)
});

object.a_function('simple'); // alerts "prealert for simple" and then alerts "simple"

Upvotes: 0

Petr Janeček
Petr Janeček

Reputation: 38444

JsMockito is obviously the most robust solution there is. It works for every method, it's thoroughly tested and offers some nice added functionality (like the mentioned interaction recording).

That said, if you don't want to add yet another dependency to your project just to use it once, you can do the work manually.

window.origWwa = window.wwa;
window.wwa = function() {
    if (arguments[0] === 'Trefferliste Webadresse') {
        window.wwaFired = true;
    }
    window.origWwa.apply(this, arguments);
};

... do your work ...

if (!window.wwaFired) {
    // do something, either throw an error or console.log("oops")
}

If the script to be run is in a <script> tag and the browser of your choice is Firefox, you can hook the onafterscriptexecute event by any function. It's shorter, but I think you can't make sure the right argument was called:

document.getElementById('script').onafterscriptexecute = function() {
    window.wwaFired = true;
};

Upvotes: 2

Konstantin Pribluda
Konstantin Pribluda

Reputation: 12367

Ok, finally got it. Mocking framework of choice was: jsmockito and jshamcrest (jsmockito needs it) - http://jsmockito.org/

And it was peace of cake.

Spy on existing object:

<tr>
<td>storeEval</td>
<td>window.wwa = JsMockito.spy(window.wwa$); </td>
<td>mockedWipe</td>

... do whatever necessary

and verify it:

<tr>
<td>storeEval</td>
<td>JsMockito.verify(window.wwa$).logAction('Trefferliste Webadresse');</td>
<td></td>

Cave at's:

  • window scoped variables are in namespace window
  • evaluation valie from verification step can be ignored, as you get an exception if call is not satisfied
  • do not forget to add js libraries to your selenium ide or test driver

Upvotes: 3

Related Questions