Selecting angular-ui date-picker value from the calendar using Protractor - protractor

My datepicker structure looks like:
<button type="button" class="date-picker-item">
<span>1</span>
</button>
<button type="button" class="date-picker-item">
<span>2</span>
</button>
etc..
I am trying to use by.cssContainingText from the protractor api.
element.all(by.cssContainingText('.date-picker-item > span', day))
but its not selecting it at the minute. Do I need to target this a different way?
Thanks a lot in advance.

In one of my project i wrote function like this:
elementDate: function(inArray,object){
var day = inArray.day.toString();
var cYear = new Date();
var cYear = cYear.getFullYear();
var year = inArray.year;
var month = inArray.month;
object.click();
element(by.css('.btn.btn-sm.btn-danger.uib-clear.ng-binding')).click().then(function(){
return object.click()
});
element(by.css('button[ng-click="toggleMode()"]')).click();
if(cYear > year){
for(var i = cYear; i > year; i--){
object.element(by.css('.btn.btn-default.btn-sm.pull-left.uib-left')).click();
};
}
else if (cYear < year) {
for(var i = cYear; i < year; i++){
object.element(by.css('.btn.btn-default.btn-sm.pull-right.uib-right')).click();
};
}
else{
}
element(by.cssContainingText('.btn.btn-default', month)).click();
element(by.cssContainingText('.uib-day .btn.btn-default.btn-sm', day)).click();
return this;
},
It takes dataPicker element (for example if you would have 2 data pickers one would be name="DatePick1" second name="DatePick2" as element name) and array of date, i think you should only change by.css elements for your project, i recommend to use fireBug to do so

Related

How to test a datepicker with protractor?

I have been trying to make my protractor test on a datepicker work.
I have the following in my html file
<div fxFlex>
<mat-datepicker #pickerBirthdate></mat-datepicker>
<input matInput
style="visibility: hidden;"
[min]="minBirthdate"
[max]="maxBirthdate"
[matDatepicker]="pickerBirthdate"
placeholder="Fecha de nacimiento"
[(ngModel)]="registry.data.fechaNac"
name="fechaNac">
</div>
And the following on my spec file
expect(page.getElementByClass('.date-select-picker'));
// get today's date
let today: any = new Date();
let dd: any = today.getDate();
let mm: any = today.getMonth() + 1; // January is 0!
const yyyy = today.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if ( mm < 10) {
mm = '0' + mm;
}
today = mm + '/' + dd + '/' + yyyy;
page.sleep();
page.getElementByClass('.date-select-picker').sendKeys(today);`
The problem is, it doesn't show up any date it just looks raised.
I've read this threads but I haven't been able to make it work, I don't know if it's due to my angular version.
How to test a Angular js date picker from Protractor
https://github.com/angular/material/issues/10404
Thanks in advance and good day
I had a similar problem with the datepicker, this is how I select a date in the future:
/// click the datepicker
element(by.css('.mat-datepicker-toggle')).click();
/// opens the table with years
element(by.css('.mat-calendar-arrow')).click();
/// select year, month and day
element(by.cssContainingText(".mat-calendar-body-cell-content", "2040")).click();
element(by.cssContainingText(".mat-calendar-body-cell-content", "DEC.")).click();
element(by.cssContainingText(".mat-calendar-body-cell-content", "31")).click();
use the harness:
const harnessLoader = ProtractorHarnessEnvironment.loader();
const matDatepickerToggleHarness = await harnessLoader.getHarness<MatDatepickerToggleHarness>(
MatDatepickerToggleHarness.with({selector: 'mat-datepicker-toggle'})
);
await matDatepickerToggleHarness.openCalendar();

jquery DatePicker on specific date

I need to show a datepicker allowing customer to choose multiple dates based on below criteria and also based on business logic that number of Orders can delivery per day.
Show T + 5 days only where T is current date and customer can choose only 5dates in datepicker for delivery. Other dates will be de activated
No Sundays
There will be threshold limit for order delivery. If for example no of orders on specific date met the threshold limit, then that date should be disabled from choosing and show next date for customer to choose for delivery.
$(document).ready( function() {
var threshold_orderlimit = 100; // limit for orders to accept
var tdays = 5; // show today + 5 days
var noOfOrdersPlaced = 40; // current order count
if(noOfOrdersPlaced >= threshold) {
tdays = tdays +1; // next 5 days
}
$("#date").datepicker( {
minDate: +tdays,
maxDate: '+5D', // show only 5 days
beforeShowDay: function(date) { // No sundays
var day = date.getDay();
return [(day != 0), ''];
}
});
});
Can some one help me to check if it is achievable in Jquery Date Picker
In case of using the Jquery Datepicker, its not possible to select multiple dates. Need to add a plugin jQuery MultiDatePicker.
var date = new Date();
var threshold_reached_dates = [date.setDate(15), date.setDate(29),date.setDate(18)];
var today = new Date();
var maximumdays_limit = 5;
var pickable_range = 6;
$("#datepicker").multiDatesPicker({
minDate:today,
beforeShowDay : function(date){ return [date.getDay()!=0,'']},
maxPicks : maximumdays_limit,
pickableRange : pickable_range,
adjustRangeToDisabled: true,
addDisabledDates : threshold_reached_dates
});
function getSelectedDates()
{
console.log($("#datepicker").multiDatesPicker("getDates"))
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdn.rawgit.com/dubrox/Multiple-Dates-Picker-for-jQuery-UI/master/jquery-ui.multidatespicker.css" rel="stylesheet"/>
<link href="https://code.jquery.com/ui/1.12.1/themes/pepper-grinder/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdn.rawgit.com/dubrox/Multiple-Dates-Picker-for-jQuery-UI/master/jquery-ui.multidatespicker.js"></script>
<div id="datepicker">
<button onclick="getSelectedDates()">Get Selected Dates</button>
In case of using the Bootstrap Datepicker
var startdate = new Date();
var enddate = new Date();
var threshold_reached_dates = ["2018-07-05","2018-07-25","2018-07-13","2018-07-17"];
var maximumdays_limit = 5;
enddate.setDate(startdate.getDate()+maximumdays_limit);
var l = threshold_reached_dates.filter(function(d){return new Date(d)>=startdate && new Date(d)<=enddate;}).length;
(l && enddate.setDate(enddate.getDate()+l));
$('#date').datepicker({
format: "yy-mm-dd",
startDate : startdate,
endDate : enddate,
daysOfWeekDisabled : '0',
datesDisabled: threshold_reached_dates,
multidate: true,
multidateSeparator: ",",
}).on("changeDate",function(event){
var dates = event.dates, elem=$('#date');
if(dates.length>maximumdays_limit)
{
dates.pop();
$("#date").datepicker("setDates",dates)
}
});
function getDates()
{
console.log($("#date").datepicker("getUTCDates"));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/js/bootstrap-datepicker.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.8.0/css/bootstrap-datepicker.css" rel="stylesheet"/>
<input type="text" id="date">
<button onclick="getDates()">Get Dates</button>

Vue data model change not reflected in bound component

A jQuery datepicker is wrappped in a Vue component. The component emits an update message used to update the app model.
The app has two datepicker input fields:
startDate
adjustmentDate
When startDate is modified, adjustmentDate is to be updated to the next first or fifteenth of the month. However, the adjustmentDate datepicker component is not being notified of the update.
Expected behaviour:
startDate datepicker onSelect triggers the Vue component emit which is captured by Vue method updateStartDate
method updateStartDate sets model property adjustmentDate
It was hoped this would trigger the adjustmentDate component update since the adjustmentDate model attribute is bound to the datepicker componentDate property which has a watch.
But changing the model doesn't have the affect of notifying the component.
Any suggestions how to do this properly and show the newly calculated adjustmentDate when the startDate is changed?
Demo code:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://unpkg.com/vue"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>
<div id="app">
<div><label>Start date</label></div>
<div>
<date-picker
v-model="startDate"
v-bind:component-date="startDate"
date-format="yy-mm-dd"
#update-date="updateStartDate"
v-once
></date-picker>
</div>
<div><label>Adjustment date</label></div>
<div>
<date-picker
v-model="adjustmentDate"
v-bind:component-date="adjustmentDate"
date-format="yy-mm-dd"
#update-date="updateAdjustmentDate"
v-once
></date-picker>
</div>
</div>
<script>
Vue.component('date-picker', {
props: ['dateFormat', 'componentDate'],
template: '<input/>',
mounted: function() {
var self = this;
var _convertDateStringToDate = function(dateString) {
var dateParts = dateString.split("-");
var year = dateParts[0];
var month = dateParts[1];
var dayOfMonth = dateParts[2];
return new Date(year, month, dayOfMonth);
};
$(this.$el).datepicker({
dateFormat: this.dateFormat,
onSelect: function(date) {
self.$emit('update-date', _convertDateStringToDate(date));
},
onClose: function(date) {
self.$emit('update-date', _convertDateStringToDate(date));
}
});
$(this.$el).datepicker('setDate', this.componentDate);
},
watch: {
componentDate: function(newValue, oldValue) {
$(this.$el).datepicker('setDate', this.componentDate);
}
},
beforeDestroy: function() {
$(this.$el).datepicker('hide').datepicker('destroy');
}
});
var _calculateAdjustmentDate = function(date) {
var year = date.getFullYear();
var month = date.getMonth();
var dayOfMonth = date.getDate();
if (dayOfMonth > 15) {
month = month + 1;
dayOfMonth = 1;
} else if (dayOfMonth > 1 && dayOfMonth < 15) {
dayOfMonth = 15;
}
return new Date(year, month, dayOfMonth);
};
var data = function() {
var now = new Date();
return {
startDate: now,
adjustmentDate: _calculateAdjustmentDate(now),
};
};
new Vue({
el: '#app',
data: data,
methods: {
updateStartDate: function(date) {
this.startDate = date;
this.adjustmentDate = _calculateAdjustmentDate(date);
},
updateAdjustmentDate: function(date) {
this.adjustmentDate = date;
},
}
});
</script>
</body>
</html>
You need to remove the v-once directive from your adjustment date component as it prevents re-rendering when the data changes.
Additionally, you can simply put _calculateAdjustmentDate into a computed property, see Computed Properties.
See your updated example here: https://codepen.io/anon/pen/VQYarZ
There are some other issues with your code, I suggest you look into the Vue guide, especially at Method Event Handlers and Computed Properties as well as into Reactivity in Depth.
Also, _calculateAdjustmentDate does not really do what you describe, so you might look into this as well. You might consider Moment.js

Why is childNodes not working in this script?

I am new to JS and trying to learn some basic stuff. I have spent hours on this but i don't think it should be that difficult. For some reason, my computer is not recognizing that I am asking for childNodes.
This is a simply script that is only trying to count the number of li tags I have. I know there are other ways to do this but i am trying to learn this way.
<title>To-Do List</title>
<script>
function findComments(){
var bodyTag = document.getElementsByTagName("ol");
var count = 0;
for(var i=0;i<bodyTag.childNodes.length;i++){
if(bodyTag.childNodes[i].nodeType == 1){
count++;
}
}
alert(count);
}
window.onload = findComments;
</script>
<!--List is declared-->
<ol id="toDoList">
<!--List Items are created-->
<li>Mow the lawn</li>
<li>Clean the windows</li>
<li>Answer your email</li>
</ol>
<!--Main paragraph-->
<p id="toDoNotes">Make sure all these are completed by 8pm so you can watch the game on TV!</p>
<script>
</script>
getElementsByTagName returns an array, you need to retrieve its first element (and change the name from bodyTag to olTag or something since it's not the body tag and confused the heck out of me trying to make sense of your code)
function findComments(){
var ol = document.getElementsByTagName("ol")[0];
var count = 0;
for(var i=0;i<ol.childNodes.length;i++){
if(ol.childNodes[i].nodeType == 1){
count++;
}
}
alert(count);
}
And here's what you really should do now that you know what's wrong with your code
var ol = document.getElementsByTagName("ol")[0];
var liCount = ol.getElementsByTagName("li").length;

what the proper cross-browser date format is for passing to new Date()

i did use
var elems = $("#D li").toArray();
elems.sort(function(a, b) {
var adate = new Date($(a).find('div.dateDiv').text());
var bdate = new Date($(b).find('div.dateDiv').text());
return adate > bdate ? -1 : 1;
});
$("#D").html(elems);
<div id="D">
<li>1<div class="dateDiv">2012-04-15 10:25:45</div><div>df</div></li>
<li>2 <div class="dateDiv">2012-04-10 19:41:08</div><div>df</div></li>
<li> 3 <div class="dateDiv">2012-04-20 07:00:10</div><div>ab</div></li>
<li>4 <div class="dateDiv">2012-04-12 16:45:50</div><div>a</div></li>
<li>1<div class="dateDiv">2012-04-15 10:25:45</div></li>
<li>2 <div class="dateDiv">2012-04-10 19:41:08</div></li>
<li> 3 <div class="dateDiv">2012-04-20 07:00:10</div></li>
<li>4 <div class="dateDiv">2012-04-12 16:45:50</div></li>
<li>1<div class="dateDiv">2012-04-15 10:25:45</div></li>
<li>2 <div class="dateDiv">2012-04-10 19:41:08</div></li>
<li> 3 <div class="dateDiv">2012-04-20 07:00:10</div></li>
<li>4 <div class="dateDiv">2012-04-12 16:45:50</div></li>
<li>1<div class="dateDiv">2012-04-15 10:25:45</div></li>
<li>2 <div class="dateDiv">2012-04-10 19:41:08</div></li>
<li> 3 <div class="dateDiv">2012-04-20 07:00:10</div></li>
<li>4 <div class="dateDiv">2012-04-12 16:45:50</div></li>
</div>​
i try it many times
some problem with Firefox browser or IE or safari
it's work only with opera and chrome ,
what the proper cross-browser date format is for passing to new Date() ?
If you can control the date format in the HTML, then it would probably be best to convert it to a timestamp. Otherwise, you'd need to create a function in javascript to convert it to the proper format, whatever that might be.
Instead of doing that, why not just split it up into it's parts and pass the proper arguments to new Date() -- year, month, day, hours, minutes, seconds.
http://jsfiddle.net/katylava/xpjRa/2/
function parseDate(date) {
var date_time = date.split(' ');
var ymd = date_time[0].split('-');
var his = date_time[1].split(':');
return new Date(ymd[0], ymd[1], ymd[2], his[0], his[1], his[2]);
}
var elems = $("#D li").toArray();
elems.sort(function(a, b) {
var adate = parseDate($(a).find('div.dateDiv').text());
var bdate = parseDate($(b).find('div.dateDiv').text());
return adate > bdate ? -1 : 1;
});