Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a Angular js date picker from Protractor

I'm new to Protractor and here I'm trying to test an angularjs date picker from Protractor.

I tried to find a way to do this and this article was the only thing I found and It is not very clear to use

If someone know how to test please help.

What I need is to select today's date.

Thanks in advance :)

  • edit -

alecxe, here is the screen shot of my date picker. Unfortunately cannot provide the link of the page. :(

date picker

<input 
       class="form-control ng-pristine ng-valid ng-not-empty ng-touched" 
       ng-model="invoice.fromdate" 
       data-date-format="yyyy-MM-dd" 
       data-date-type="string" 
       data-max-="" data-autoclose="1" 
       bs-datepicker="" 
       ng-change="dateRange()" 
       type="text">
like image 576
Manuli Avatar asked Mar 08 '16 06:03

Manuli


2 Answers

I think you can avoid manipulating the datepicker manually and instead set the date either by just sending the keys with a today's date value:

var picker = element(by.model("invoice.fromdate"));

// get today's date
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();

if(dd<10) {
    dd='0'+dd
} 

if(mm<10) {
    mm='0'+mm
} 

today = mm+'/'+dd+'/'+yyyy;

picker.clear();
picker.sendKeys(today);

Or, by setting the associated model's value directly:

picker.evaluate("invoice.fromdate= '" + today + "'");
like image 126
alecxe Avatar answered Oct 05 '22 11:10

alecxe


Two methods have been suggested so far: 1. sendKeys() 2. evaluate() I'm a bit new to protractor but I think both of these have issues in the case of not having an input element that spawns the calendar, i.e.: standalone datepicker

Sendkeys() works only if date is on an element and the uib-datepicker is a dropdown sort of deal. This didn't help me because my datepicker element is a standalone and isn't paired with an input element.
evaluate() doesn't update angular's actual model in the browser (which begs the question of how useful evaluate actually is...). According protractor docs, evaluate, "Evaluates the input as if it were on the scope of the current underlying elements." In my case I want to test whether the date generated by the datepicker gets to my enpdpoint via a post request and then back again (hence e2e) without getting effed (corrupted), therefore, I need my date to be on my angular model in the browser instance, not just in the browser-driver environment or whatever the runtime environment of the protractor test is. I could be wrong about this.
This expect() passes but the ng-form is invalid (i'm assuming b/c model in browser wan't actually updated to receive the date I'm trying to pass in.):

function convertToPickerDate(date) {
    var date = new Date(date);
    var dd = date.getDate();
    var mm = date.getMonth() + 1; //January is 0!
    var yyyy = date.getFullYear();
    var yy = yyyy.toString().slice(2);

    return mm + '/' + dd + '/' + yy;
}     

// expect passes, but form is invalid - DON'T USE for standalone cal
it('should enter start date in date picker', function () {
        offerStart = convertToPickerDate(myData.startDate);
        var offerStartPicker = element(by.model('current.startDate'));
        offerStartPicker.evaluate("current.startDate = '" + offerStart + "'");
        offerStartPicker.evaluate("current.startDate").then(function (value) {
            expect(value).toBe(offerStart);
        });
})

but the ng-form that the element is on is invalid...

My solution uses css selection and arrow keys to select a date relative to today:

Shipment Start Date: <em id="offerStartPrint">{{current.startDate | date:'shortDate' }}</em>
<div id="offerStart"
        name="offerStart"
        uib-datepicker
        ng-model="current.startDate"
        class=""
        ng-change="setStartDate()"
        datepicker-options="startDateOptions"
        required></div>
</div>

function convertToPickerDate(date) {
    var date = new Date(date);
    var dd = date.getDate();
    var mm = date.getMonth() + 1; //January is 0!
    var yyyy = date.getFullYear();
    var yy = yyyy.toString().slice(2);

    return mm + '/' + dd + '/' + yy;
}

it('should enter expiration date in date picker using tabs and arrows :)', function () {
        // select today element on uib-datepicker calendar
        // div#offerStart elem has date model
        var calToday = element(by.css('div#offerStart table td button.active')); 

        calToday.sendKeys(protractor.Key.ARROW_DOWN);  // one week away
        calToday.sendKeys(protractor.Key.ARROW_DOWN);  // two weeks away
        calToday.click(); // if you remove this click no date is entered
        var fortnightAway = new Date(Date.now() + 12096e5);
        fortnightAwayString = convertToPickerDate(fortnightAway);
        expect(element(by.id('offerStartPrint')).getText()).toBe(fortnightAwayString);
    })

Left and right arrows can be used to increment/decrement date by one day at a time. up/down arrows can be used to inc/dec one week at a time. One could probably figure out how to arrow through months and years as well.

like image 36
Robin Nelson Avatar answered Oct 05 '22 10:10

Robin Nelson