jubo
jubo

Reputation: 123

How to open different popups with the same title in CasperJS?

I'm trying to automate some tasks using casperJS, and I need to open multiple popups. However, all popups have the exact same url (http://.../printit.aspx/...), so that whenever I use

this.withPopup(/printit/, function() {...});

it always opens the first popup. I can't access the other ones.

I suppose there are two possibilities :

Upvotes: 2

Views: 757

Answers (2)

j.c
j.c

Reputation: 2882

In my case i have a list of links. Every link calls some javascript that opens a new tab(=popup in casperjs), always with the same url (...\View.aspx).
Inside the tab i have to click a button that changes the url in the tab (...\List.aspx).
on("popup.loaded"...) is called twice, pushing every new page in the casper.popups array. They usually alternate, but for some reason (i guess asyncrony) not always: sometimes casper.popups[/*LAST*/].url matches /View\.aspx/, sometimes it matches /List\.aspx/.
I always had to use casper.withPopup( /*LAST VIEW.ASPX LOADED*/, ...); that was not always the last popup loaded and neither the one matching /View.aspx/ (it could be one of the oldes), so i had to find the latest loaded matching /View\.aspx/.
Here's my solution:

var is_view_loaded=false;

casper.on('popup.loaded', function(page) {
    if(page.url.match(/View\.aspx/)) {
        is_view_loaded=true;
    }
}

// return last popup which url matches the required regexp
casper.getLastRegExPopup=function(regex) {
    var l=casper.popups.length;
    var i=l-1;
    while(!regex.test(casper.popups[i].url)) {
        i--;
        if(i<0) return null;
    }
    return casper.popups[i];
}

Then in my core steps:

.
.
// clicked the link, must wait for popup (but which?!)

casper.waitFor(
    function test() {
        return is_view_loaded;
    },
    function then() {
        var popup=casper.getLastRegExPopup(/View\.aspx/);
        casper.withPopup(popup, function() {
            // do things with "this"
        });
        is_view_loaded=false;
    }
    //, timeout
);
.
.

Upvotes: 0

Artjom B.
Artjom B.

Reputation: 61952

There is no easy and documented way of disambiguating two popups. The documentation says that casper.popups is an array-like property. So you could iterate over it. Judging by the code, the popups property itself is a pagestack. One can easily modify the pagestack.findByRegExp() function to do this kind of thing.

It seems that the casper.popups property contains duplicate entries, so one can filter them out.

casper.findAllPopupsByRegExp = function(regexp){
    var popups = this.popups.filter(function(popupPage) {
        return regexp.test(popupPage.url);
    });
    if (!popups) {
        throw new CasperError(f("Couldn't find popup with url matching pattern %s", regexp));
    }

    // remove duplicates
    var uniquePopups = [];
    popups.forEach(function(p){
        if (uniquePopups.indexOf(p) === -1) {
            uniquePopups.push(p);
        }
    });
    return uniquePopups;
}

casper.withPopup() accepts three types of inputs to identify a popup page. The third one is a the page object itself. So you can retrieve the matching popup page objects with findAllPopupsByRegExp(), select the one that you want and pass that to withPopup() to change into its context:

casper.then(function(){
    var popups = this.findAllPopupsByRegExp(/printit/);
    this.withPopup(popups[1], function(){
        ...
    });
});

Upvotes: 1

Related Questions