user1665355
user1665355

Reputation: 3393

Wait until drop-down list element is visible in CasperJS

I have this drop down list:

<select name="date" class="form-control" on-change:Calendar.submitFilterForm();">
    <option value="2015-09-15">Tue 2015-09-15</option>
    <option value="2015-09-16">Wed 2015-09-16</option>
    <option value="2015-09-17">Thu 2015-09-17</option> 
    <option value="2015-09-18">Fri 2015-09-18</option>
    <option value="2015-09-19">Sat 2015-09-19</option>
    <option value="2015-09-20">Sun 2015-09-20</option>
    <option value="2015-09-21">Mon 2015-09-21</option>
    <option value="2015-09-22">Tue 2015-09-22</option>
</select>

Each night at 00:00 AM (or a few seconds later) the drop-down list above is updated with a new (next) day, for example <option value="2015-09-23">Wed 2015-09-23</option> would be added and <option value="2015-09-15">Tue 2015-09-15</option> would disappear.

I then want to click on that drop-down list option that is added as soon as it is visible. Is it possible?

Now I use:

casper.thenEvaluate(function(){
    var form = document.querySelector('.form-control');
    form.selectedIndex = 7; //7 equals the last value currently visible.
    $(form).change();
});

It works but how should I do to make casperjs wait until the options is visible and then directly click on it? Maybe I can make a variable var ClickValue = "2015-09-23" or something like that?

Upvotes: 1

Views: 1217

Answers (1)

Artjom B.
Artjom B.

Reputation: 61932

CasperJS is not the right place to schedule long running tasks, because the underlying browser (PhantomJS or Slimer.js) may run into memory problems or otherwise fail. So you should write a short running script that only waits a short amount of time until the element appears. You can schedule the execution of this script just before midnight through your operating system (cron on Linux or at on Windows).

Element appears through JavaScript

If the select field is updated by JavaScript, then you can simply use a "long"-running waitFor():

casper.then(function(){
    var lastDate = this.getElementAttribute(".form-control :last-child", "value");
    this.waitFor(function(){
        return this.getElementAttribute(".form-control :last-child", "value") !== lastDate;
    }, null, null, 600000); // 10 minutes
}).thenEvaluate(function(){
    var form = document.querySelector('.form-control');
    form.selectedIndex = 7; //7 equals the last value currently visible.
    $(form).change();
});

A page reload is necessary

If you will see the added option only when you reload the page, then you need casper.reload() the page for every check.

casper.then(function(){
    var lastDate = this.getElementAttribute(".form-control :last-child", "value");

    function checkReload(){
        var curDate = this.getElementAttribute(".form-control :last-child", "value");
        if (lastDate !== curDate) { // TODO: add timeout handling here
            return; // finished
        }

        this.reload();
        this.wait(1000, checkReload); // check again in a second
    }
    this.then(checkReload);
}).thenEvaluate(function(){
    var form = document.querySelector('.form-control');
    form.selectedIndex = 7; //7 equals the last value currently visible.
    $(form).change();
});

This runs indefinitely, so you should add timeout handling.

No comparison necessary with precomputed date

The above solutions work by comparing the previous option value with the current one. This is not entirely robust, because if something wrong happens and the script is started at a time when the new option appears, then the script will run another 24 hours. You could also change that to directly compute the expected option value by creating the expected

var d = new Date(Date.now()+(1000 * 60 * 60 * 24 * 7)); // seven days later
var expectedValue = ""+d.getFullYear()
        +"-"+zeroFill(d.getMonth()+1, 2)
        +"-"+zeroFill(d.getDate(), 2);

expectedValue would replace lastDate in the previous snippets and don't forget to flip the comparison from !== to ===.
zeroFill() is taken from here.

Upvotes: 2

Related Questions