Casperjs: testing jquery autocomplete

2.5k Views Asked by At

I'm having trouble interacting with a jquery auto-complete input box with casperjs. I've tried many different ways, but I can't seem to select the auto complete option when the list of options pops up.

My code is as follows:

casper.thenEvaluate(function() {
  $('#myInput').val('cars');  // fill in the text box
  $('#myInput').blur();  // should trigger the autocomplete ajax call
  $('.ui-autocomplete li.ui-menu-item:nth-of-type(1)').click(); // should click the first item in the list
});

// take a picture to make sure it worked
casper.then(function() {
  this.captureSelector('pics/test1.png', '#theForm');
});

This doesn't work at all, even though it looks like it should. By playing around with it, I've found that triggering a down arrow keypress a few times triggers the auto complete to show up, so here is a version that is closer to working. This works in the browser, but not in a casper.thenEvaluate block for some reason.

$('#myInput').val('cars');  // fill in the text box
var e = jQuery.Event("keydown");
e.which = 40; // press down arrow a few times, not sure why this works
$("#myInput").trigger(e);
$("#myInput").trigger(e);
$('.ui-autocomplete li.ui-menu-item:nth-of-type(1)').click();
2

There are 2 best solutions below

2
On

This is not based on jQuery UI's autocomplete, but rather Typeahead which is related to Bootstrap, but the mechanics should be the same.

I have had success with the following:

casper.sendKeys("#field_departure_airport", 'a', {keepFocus: true});
casper.waitUntilVisible(".typeahead", function() {
    casper.click(".typeahead>li:nth-child(1)>a");
    test.assertField("departure_airport", "A. L. Mangham Jr. Regional Airport(Nacogdoches, Texas, United States) [OCH]"); 
});

This runs in a casper.then() function, the sendKeys selects a field by ID and passes "a" to it. The keepFocus is important, otherwise it will deselect the input after inserting the text!

Wait for .typeahead to appear, that waits for the AJAX call to the server, then click the first a element in the Typeahead.

And lastly test the value of the field. Note that the field selector is its name, not a CSS3 selector.

4
On

I tried a lot of different solutions, which didn't work, or not always. I've finally found one which seems robust :

/*
 * You have to specify the input selector, the text you want to write in (which activates the auto-completion), and the text on which you want to click
 */
casper.fillAutoCompletion = function (inputSelector, text, autoCompleteText) {
    //keepfocus : true to keep the auto-completion opened
    this.sendKeys(inputSelector, text, {keepFocus: true});
    //wait for the auto-complete block to appear
    this.waitUntilVisible("[class*='ui-autocomplete']", function() {
        var x = require('casper').selectXPath
            ,xpath = "//*[contains(text(),'" + autoCompleteText + "')]"
            ;
    //move on the wanted element and click
    this.mouse.move(x(xpath));
    this.click(x(xpath));
    });
};

Or if you don't prefer to extend, js function :

var fillAutoCompletion = function (inputSelector, text, autoCompleteText) {
    //keepfocus : true to keep the auto-completion opened
    casper.sendKeys(inputSelector, text, {keepFocus: true});
    //wait for the auto-complete block to appear
    casper.waitUntilVisible("[class*='ui-autocomplete']", function() {
        var x = require('casper').selectXPath
            ,xpath = "//*[contains(text(),'" + autoCompleteText + "')]"
            ;
    //move on the wanted element and click
    casper.mouse.move(x(xpath));
    casper.click(x(xpath));
    });
};

Call it :

.thenOpen("yourUrl", function(){
    this.fillAutoCompletion(".jODMainSearch","Ren", "Rennes");//extending
    fillAutoCompletion(".jODMainSearch","Par", "Paris");//js
})

The trick (for me) was to use mouse.move() on the wanted element (to activate its selection) before clicking on it, otherwise it didn't work.