Search code examples
javascripttestingcasperjscolumnsorting

How to verify the sorting(ascending and descending) functionality in casperjs


I am new to this framework and also not getting any idea how to test the sorting functionality with CasperJS.

The scenario is, I need to verify the search results with sorting functionality. When i search with any keyword it displays all the possible matching results.

Search functionality picture


Solution

  • You will have to define your own comparison functions. Here for example one that compares the lexicographical string ordering in a case insensitive manner:

    function cmpLexiInsAsc(a, b) {
        return a.toLowerCase() < b.toLowerCase();
    }
    function cmpLexiInsDesc(a, b) {
        return a.toLowerCase() > b.toLowerCase();
    }
    

    The difficulty will be to retrieve the proper elements that you can compare. For example, you will probably need to split the price and the currency, parse the price as number and compare those.

    I will assume for the rest of the answer that you have a default <table> and use column-wise ordering.

    You can define a function that takes the column index (beginning at 1), the additional selector to find the element in a cell and the comparison function for that column. It internally defines the CSS selectors or XPath expressions to access the table cells. Keep in mind that to do this, you need to know how many rows there are and possibly adjust this if there is a header/footer row.

    function compare(colIndex, cellSelector, cmpFunc){
        function rowSelector(rowIndex) {
            return "table#tableId tr:nth-child(" + rowIndex + ") > td:nth-child(" + colIndex + ")" + cellSelector;
        }
    
        var count = this.getElementsInfo("table#tableId tr");
        if (count < 2) {
            return true;
        }
    
        var previous = this.getElementInfo(rowSelector(i)).text,
            current;
        for(var i = 2; i <= count; i++) {
            current = this.getElementInfo(rowSelector(i)).text;
            if (!cmpFunc(previous, current)) {
                return false;
            }
            previous = current;
        }
        return true;
    }
    

    You can then run this compare() function for multiple columns depending on your criteria. For example:

    casper.then(function(){
        casper.test.assert(compare.call(this, 1, " > span > span.info", cmpLexiInsAsc), "Column 1 ascending");
        this.click("some selector to change ordering");
    });
    
    casper.then(function(){
        casper.test.assert(compare.call(this, 2, " > div > span.info", cmpLexiInsDesc), "Column 2 descending");
    });
    

    There is a rare bug in PhantomJS 1.x for :nth-child() CSS selectors. You may try to use XPath selectors which are supported in CasperJS through the helper function:

    var x = require('casper').selectXPath;
    ...
    casper.getElementsInfo(x("//table[@id='tableId']//tr["+rowIndex+"]/td["+colIndex+"]/span/span"));
    

    Note that CasperJS is built on top of PhantomJS and has the same limitations. You cannot directly work on DOM elements outside of the page context (casper.evaluate()). You will need to get a representation of such an element beforehand. I do this by accessing the text property on the object returned from getElementsInfo().