How to clear a date from input type="date" with WebdriverIO - webdriver-io

I'm now using WebdriverIO and developing a web app.
these days I tried to set a date from input type="date", I got errors
invalid element state: Element must be user-editable in order to clear
it.
and found that
I could get rid of the errors by using addValue() but still the value won't be cleared by any API.
client.clearElement('#deadline')
Also get
invalid element state: Element must be user-editable in order to clear
it.
How can I remove the value from the form?

You can run in browser script to clear it
browser.execute(function () {
document.querySelector('#deadline').value = '';
}, null);
OR give it some value
var date = '2020-03-28';
browser.execute(function (date) {
document.querySelector('#deadline').value = date';
}, date);
reference: https://github.com/webdriverio/webdriverio/issues/386
A more elegant way is to create a custom command and put this piece of code inside

this one worked for me:
client.selectorExecute("#dateInput", function(inputs, value) {
// you can run over the inputs
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].type == 'date') // any condition
inputs[i].value = "1973-12-09";
}
// or just do that:
inputs[i].value = "1973-12-09";
return;
})

Related

How can I save part of a string in an alias using Cypress?

I'm trying to save just a number from a string I get from a paragraph but when I try to asign an alias to it and then check the value it returns undefined. I've tried a few solutions I found but none of those seem to work for me. These are two ways I tried (I tried another one similar to the second one but using split, had same result). The console.log inside of the 'then' doesn't show in the console, and when I try the alias after the code is when I get undefined.
cy.get('p')
.eq(1)
.should('have.text', '/[0-9]+/g')
.as('solNumber')
cy.get('p')
.eq(1)
.invoke('text')
.then((text)=>{
var fullText = text;
var pattern = /[0-9]+/g;
var number = fullText.match(pattern);
console.log(number);
})
.as('solNumber')
Please convert with + operator and return the numeric value if you want numeric type to be stored.
cy.get('p').eq(1)
.invoke('text')
.then(fullText => {
const number = fullText.match(/[0-9]+/);
return +number // text to numeric
})
.as('solNumber')
cy.get('#solNumber')
.should('eq', 42) // numeric type
});
Running your 2nd code on this,
<p>21</p>
<p>42</p>
gives the correct outcome
cy.get('p')
.eq(1)
.invoke('text')
.then((text)=>{
var fullText = text;
var pattern = /[0-9]+/g;
var number = fullText.match(pattern);
console.log(number); // logs 42
})
.as('solNumber')
cy.get('#solNumber')
.should('eq', '42') // passes
So, you need to inspect the DOM, it looks like it's not what you expect.
The first attempt you were passing a jquery element to the .should() and although some chainers change the subject yours did not so it saved the jquery element as solNumber.
The second attempt invokes the .text() which was passed to the .then() it logs the number correctly. However, you did not return anything at the end of the .then() block, therefore, solNumber should hold the entire paragraph.
This should help you out to extract the specific number and save it as an alias.
cy.get('p')
.invoke('text')
.invoke('trim')
.then(paragraph => {
const matcher = /some/
expect(paragraph).to.match(matcher) // check number is there
const indexOfText = paragraph.match(matcher) // get index of match text
return paragraph.substring(indexOfText.index, indexOfText.index + indexOfText[0].length) // return substring
})
.as('savedText')
cy.get('#savedText')
.then(cy.log) // will print out the number you seek

How to quit finding of element given under locator strategies of #findbyall when first match gets found?

On a page I'm my element has any one of three different identifiers. Having given all three under findByAll, I wish to quit the search for find element as soon as any one of it gets found. Looking for short circuit search for the element, no more search should happen once the element is found.
#
iOSXCUITFindByAllSet(value = { #iOSXCUITFindAll(value = {
#iOSXCUITBy(iOSNsPredicate = "type == 'XCUIElementTypeStaticText' && name == 'Acc_label_Header' && visible ==1"),
#iOSXCUITBy(iOSNsPredicate = "type == 'XCUIElementTypeStaticText' && name == 'ET NOW - Live Radio' && visible ==1"),
#iOSXCUITBy(iOSNsPredicate = "type == 'XCUIElementTypeStaticText' && name == 'ET NOW - Live Tv' && visible ==1") }) })
Don't want the request for find element to be going as soon as one of the element gets found, as this step of finding element by all locator is taking a lot of time.
I do not know what language you are using to control selenium. I wrote a bit of code in Javascript which waits for either one of several elements to be visible on the page:
// define what we are looking for
let xpathParts = [];
xpathParts.push("//h4[contains(#class,'search-title') and text()='Title 1']");
xpathParts.push("//h3[text()='Title 2']");
xpathParts.push("//h3[text()='Title 3']");
// try to get one of it
let elements = [];
for (let i = 0; i < 50 && elements.length == 0; i++) {
elements = driver.findElements(By.xpath(xpathParts.join("|")));
await new Promise(s => setTimeout(s, 100));
}
// throw an error if we did not find it within the time
if (elements.lenght == 0) {
throw "Could not find one of the elements";
}

Set several initial dates in inline datetimepicker tempusdominus

I'm trying to set up the datetimepicker on
https://tempusdominus.github.io/bootstrap-3/
and configure it to be used inline. It is initialized with:
$('#datetimepicker5').datetimepicker({
inline: true,
allowMultidate: true,
multidateSeparator: ';',
locale: 'nb',
format: 'L',
useCurrent: false,
});
It works, but I cannot find out how to initialize several dates.
As you can see I use it with allowMultidate.
So, how can I initialize the datetimepicker with several dates pre-set?
I met the same problem and I can't find any answers here. So I tried to resolve it with a little revise to "tempusdominus-bootstrap-4.js".
I hope this will help you and make some reference for anyone who met the same problem.
At first adding a method multiDate for Object DateTimePicker.
var DateTimePicker = function () {
…
DateTimePicker.prototype.multiDate = function multiDate(params) {
var date = params[0];
var index = params[1];
this.date(date, index);
};
…
}
The next, invoke your method at your page.
Suppose your initial data is like this:
var values = ['2019-02-06','2019-03-06','2019-05-08','2019-07-02'];
So you can initialize these in your multidatepicker.
var initializeMultidate = function(){
for(var i=0; i<values.length; i++){
var date = moment(values[i], 'YYYY-MM-DD');
$("#datetimepicker1").datetimepicker("multiDate", [date, i]);
}
};
=================================================
That's all.
The only solution I found was to do a search for the dates and using JQuery to click them, it is not elegant but it worked for me.
var fechas = ['01/10/2020', '02/10/2020', '03/10/2020'];
for (let index = 0; index < fechas.length; index++) {
$("[data-day='"+fechas[index]+"']").click();
}
Unfortunately, what you are asking cannot be done using tempusdominus. I struggled with the same issue and in the end switched over to jQueryUI MultiDatesPicker, which allows for much more control.
http://dubrox.github.io/Multiple-Dates-Picker-for-jQuery-UI/

Refresh a dijit.form.Select

First, you have to know that I am developing my project with Struts (J2EE
Here is my problem :
I have 2 dijit.form.Select widgets in my page, and those Select are filled with the same list (returned by a Java class).
When I select an option in my 1st "Select widget", I would like to update my 2nd Select widget, and disable the selected options from my 1st widget (to prevent users to select the same item twice).
I succeed doing this (I'll show you my code later), but my problem is that when I open my 2nd list, even once, it will never be refreshed again. So I can play a long time with my 1st Select, and choose many other options, the only option disabled in my 2nd list is the first I've selected.
Here is my JS Code :
function removeSelectedOption(){
var list1 = dijit.byId("codeModif1");
var list2 = dijit.byId("codeModif2");
var list1SelectedOptionValue = list1.get("value");
if(list1SelectedOptionValue!= null){
list2.reset();
for(var i = 0; i < myListSize; i++){
// If the value of the current option = my selected option from list1
if(liste2.getOptions(i).value == list1SelectedOptionValue){
list2.getOptions(i).disabled = true;
} else {
list2.getOptions(i).disabled = false;
}
}
}
Thanks for your help
Regards
I think you have to reset() the Select after you've updated its options' properties. Something like:
function removeSelectedOption(value)
{
var list2 = dijit.byId("codeModif2"),
prev = list2.get('value');
for(var i = 0; i < myListSize; i++)
{
var opt = myList[i];
opt.disabled = opt.value === value;
list2.updateOption(opt);
}
list2.reset();
// Set selection again, unless it was the newly disabled one.
if(prev !== value) list2.set('value', prev);
};
(I'm assuming you have a myList containing the possible options here, and the accompanying myListSize.)

Conditionally adjust visible columns in Rally Cardboard UI

So I want to allow the user to conditionally turn columns on/off in a Cardboard app I built. I have two problems.
I tried using the 'columns' attribute in the config but I can't seem to find a default value for it that would allow ALL columns to display(All check boxes checked) based on the attribute, ie. the default behavior if I don't include 'columns' in the config object at all (tried null, [] but that displays NO columns).
So that gets to my second problem, if there is no default value is there a simple way to only change that value in the config object or do I have to encapsulate the entire variable in 'if-else' statements?
Finally if I have to manually build the string I need to parse the values of an existing custom attribute (a drop list) we have on the portfolio object. I can't seem to get the rally.forEach loop syntax right. Does someone have a simple example?
Thanks
Dax - Autodesk
I found a example in the online SDK from Rally that I could modify to answer the second part (This assumes a custom attribute on Portfolio item called "ADSK Kanban State" and will output values to console) :
var showAttributeValues = function(results) {
for (var property in results) {
for (var i=0 ; i < results[property].length ; i++) {
console.log("Attribute Value : " + results[property][i]);
}
}
};
var queryConfig = [];
queryConfig[0] = {
type: 'Portfolio Item',
key : 'eKanbanState',
attribute: 'ADSK Kanban State'
};
rallyDataSource.findAll(queryConfig, showAttributeValues);
rally.forEach loops over each key in the first argument and will execute the function passed as the second argument each time.
It will work with either objects or arrays.
For an array:
var array = [1];
rally.forEach(array, function(value, i) {
//value = 1
//i = 0
});
For an object:
var obj = {
foo: 'bar'
};
rally.forEach(obj, function(value, key) {
//value = 'bar'
//key = 'foo'
});
I think that the code to dynamically build a config using the "results" collection created by your query above and passed to your sample showAttributeValues callback, is going to look a lot like the example of dynamically building a set of Table columns as shown in:
Rally App SDK: Is there a way to have variable columns for table?
I'm envisioning something like the following:
// Dynamically build column config array for cardboard config
var columnsArray = new Array();
for (var property in results) {
for (var i=0 ; i < results[property].length ; i++) {
columnsArray.push("'" + results[property][i] + "'");
}
}
var cardboardConfig = {
{
attribute: 'eKanbanState',
columns: columnsArray,
// .. rest of config here
}
// .. (re)-construct cardboard...
Sounds like you're building a neat board. You'll have to provide the board with the list of columns to show each time (destroying the old board and creating a new one).
Example config:
{
attribute: 'ScheduleState'
columns: [
'In-Progress',
'Completed'
]
}