Select Kendo ComboBox in Cypress - testing

I have problem with selecting value from combobox in Cypress.
It allways writes me that:
CypressError: cy.select() can only be called on a <select>. Your subject is a: <span unselectable="on" class="k-select" aria-label="select" role="button" tabindex="-1" aria-controls="fabric_listbox">...</span>
Types text into numeric inputs
My code looks like this:
describe('KendoUI', () => {
it('types text into numeric inputs', () => {
cy.visit('https://demos.telerik.com/kendo-ui/combobox/index');
cy.get(':nth-child(4) > .k-dropdown-wrap > .k-select').select('Polyester')
})
})
Can you please give me some help?
You could try it on this page: https://demos.telerik.com/kendo-ui/combobox/index
Thank you.

I resolved it.
Make cy.click() on the element
Found with cy.contains() text what is in the box and then click on it (cy.contains('text').click)

cy.select() will only work for native HTML <select> elements. In your case you should simply cy.click() on the element you want to select. This is the way for all custom plugins which mimic select behaviour.

cy.get('kendo-popup').contains('Foobar').click({force:true})
You might need to force click as the element might not be visible

cy.get('combobox').contains('value').click()

I found that Cypress scrolling the viewport to the chosen option caused the dropdown to close. This command tells Cypress to wait for the dropdown to become non-disabled, scroll to the dropdown, click on the dropdown, wait for the dropdown to finish animating, then click on the item without further scrolling.
Tested with Kendo UI v2016.1.226
Declaration in commands.js:
Cypress.Commands.add('selectKendoDropdownItem', (dropdownName, item) => {
cy.get(`span[aria-disabled="false"][aria-owns="${dropdownName}_listbox"]`)
.click()
.get(`div#${dropdownName}-list li.k-item`)
.contains(item)
.click({ waitForAnimations: true, scrollBehavior: false, force: true });
});
Use in a spec:
cy.selectKendoDropdownItem('dropdownElementId', 'Text of option to select');

Related

Timed out retrying: cy.type() failed because this element is not visible. has CSS property: position: fixed and it's being covered by another element:

Unable to find the textbox element in a new pop-up window.
Actual Result:
Expected Result:
Able to type value in the text box.
Adding the cypress snippet below,
it("Add business test",function(){
cy.xpath("//a[contains(.,'1099/W-2')]").click({force:true});
cy.wait(5000);
cy.get(':nth-child(2) > .btn-hover-shrink > .v-btn__content').click({force: true});
cy.contains('Start Now').click({force:true});
//Add business pop-up open
cy.contains('Business Name').click({force: true}).type("Test LLC");
})
You can add {force: true} with type() to disable error checking -
cy.get('[id*="input-"]').type("Test LLC", {force: true});
The error message indicates that you are trying to type() into the label. That's because cy.contains('sometext') selects the element "owning" the text, which is the label, but you can also select a parent by using the pattern cy.contains(<parentSelector>, 'sometext')
Take a look at the page DOM, if you have a common parent of the <label> and the <textarea> (or <input>), like this
<div>
<label>Business Name</label>
<input />
</div>
you can target that parent in the .contains()
cy.contains('div', 'Business Name')
.find('input') // drill down to the element receiving the text
.should('be.visible') // since there's a toolbar in the mix, wait for visibility
.type('Test LLC')
An alternative might be to use .closest()
cy.contains('Business Name') // gives you the label
.closest('input') // nearby element receiving the text
.should('be.visible') // wait for visibility
.type('Test LLC')
Here's one more way, making use of the label's "for" attribute
cy.contains('Business Name') // gives you the label
.invoke('attr', 'for') // which id is it for?
.then(id => {
cy.get('#' + id) // get the actionable element
.should('be.visible') // wait for visibility
.type('Test LLC')
})
Taking a look at the Vuetify form component here which has a similar HTML to yours
<div class="v-text-field__slot">
<label for="input-6" class="v-label theme--light" style="left: 0px; right: auto; position: absolute;">Last name</label>
<input required="required" id="input-6" type="text">
</div>
the same test code you have succeeds on the sample code
cy.contains('Last name')
.click({force: true})
.type("Test LLC"); // text appears in the input
but if I simulate the covering toolbar, it fails with the same error you have.
Adding .type("Test LLC", {force: true}) also fails with a different error
cy.contains('Last name')
.click({force: true})
.type("Test LLC", {force: true});
cy.type() failed because it requires a valid typeable element.
Using the parent contains to find the "typeable element" and applying force: true option works
cy.contains('div', 'Business Name')
.find('input')
.should('be.visible')
.type("Test LLC", {force: true})
This assumes the toolbar remains static and does not animate away, in which case it would work without the force: true option.

Waiting for element to appear on static button in TestCafe

I have a strange behavior of TestCafe on my site. I have two checkboxes on a site and a button that brings me to the next step as soon as I click on it. When the page load, de button is visible and does not get manipulated at any time.
Here is the markup of the button:
<button id="confirmation-submit" type="submit" class="btn btn-success pull-right hidden-xs">
<span class="glyphicon glyphicon-flag"></span>
order now
</button>
Here is what my code looks like (the relevant part for this problem):
const submitOrderBtn = Selector('button[type="submit"].btn-success');
//const submitOrderBtn = Selector('#confirmation-submit');
test('complete order', async t =>{
await t
.click(submitOrderBtn)
In chrome it shows me this picture:
The output of the command line is this:
The button is visible the whole time and even when I look over the site with the developer tools, the button is there and it has the id (confirmation-submit) that I want to be clicked.
How can I get around this problem? On other pages, I can use the .click function without any problems.
As #Andrey Belym mentioned in his comment, TestCafe will consider element visibile if its width or height have a non-zero value and it is not hided using CSS properties like display: hidden and visibility: none.
You can check it in Computed CSS Properties in DevTools. In your case, #confirmation-button might be an invisible button hidden somewhere in an actual visible element.
Also, you can try to resize browser window using resizeWindow action. It may help if your layout is adaptive or it is a scrolling issue.
As a workaround you could try to click on the button parent container:
const submitOrderBtn = Selector('#confirmation-submit');
const confirmSelector = submitOrderBtn.parent();
test('complete order', async t =>{
await t
.click(confirmSelector)
if this does not work for the immediate parent, you could try to fetch the first parent div like this:
const submitOrderBtn = Selector('#confirmation-submit');
const confirmSelector = submitOrderBtn.parent('div');
test('complete order', async t =>{
await t
.click(confirmSelector)
<button data-se-id="confirmation-submit" type="submit" class="btn btn-success pull-right hidden-xs">
order now
</button
and in test add like this : for click specified element :
const submitOrderBtn =Selector('[data-se-id="confirmation-submit"]')
test('complete order', async t =>{
await t
.click(submitOrderBtn)

How to keyboard navigate to reCAPTCHA in a modal dialog?

I need to open Google's latest reCAPTCHA widget in a popup (modal) dialog, a Dojo Dialog in my case, and I've got that working fine, but I just realized that the user cannot keyboard navigate to it.
When the reCAPTCHA widget is displayed in the main view, not a modal dialog, then of course the user can easily keyboard navigate to it.
Has anyone found a way to set focus on the reCAPTCHA widget so that the user can access it without a mouse when the reCAPTCHA is in a Dojo Dialog?
I did see that reCAPTCHA is generated within an <iframe>. Is that part of the hurdle - that keyboard navigation can't reach content within an iframe? I've even tried to call document.getElementById("recaptcha-anchor") since I saw that that's the id of the <span> that holds the "checkbox" - but that is returning null. How to reach an element within an iframe?
I have a jsfiddle example available for demonstration at
https://jsfiddle.net/gregorco/xqs8w5pm/5/
<script>
var onloadCaptchaCallback = function() {
console.log("jsfiddle: rendering captcha");
globalRecaptchaWidgetId = grecaptcha.render('captchaDiv', {
'sitekey' : '6LcgSAMTAAAAACc2C7rc6HB9ZmEX4SyB0bbAJvTG',
'callback' : verifyCaptchaCallback,
'tabindex' : 2
});
grecaptcha.reset();
}
var verifyCaptchaCallback = function(g_recaptcha_response) {
console.log("Response validated. Not a robot.");
};
</script>
<script src='https://www.google.com/recaptcha/api.js?onload=onloadCaptchaCallback&render=explicit' async defer></script>
<div id="testDiv">
<button type="dojo/form/Button" onClick="captchaPopup.show();">Open reCAPTCHA</button>
</div>
<div data-dojo-type="dijit/Dialog" data-dojo-id="captchaPopup" title="Human Verification" style="width:350px;">
Cannot keyboard navigate to the checkbox!
<table>
<tr>
<td>
<div id="captchaDiv"></div><br/>
</td>
</tr>
</table>
</div>
Give this fiddle a try. Normally Dijit dialogs don't work too well with iframes in them because it doesn't know how to parse the content inside an iframe. In this case, we can use some of Dojo's functions to work around it. One notable thing to point out is that I've disabled autofocus of the Dijit Dialog so that it won't automatically focus the closeNode inside the dialog.
After the dialog loads, tab>space will select the captcha.
This may help others facing similar issue, but with Bootstrap modal dialog. I found the following solution on GitHub. Add the following Javascript to override Bootstrap:
Bootstrap 3x
$.fn.modal.Constructor.prototype.enforceFocus = function () { };
Bootstrap 4x
$.fn.modal.Constructor.prototype._enforceFocus = function () { };

Unable to render combo box in dialog

I want to show a popup dialog containing a dijit.ComboBox with data populated using ajax request or data store.
The problem I am facing is that the combobox is always disabled.
My selected code is:
<div dojoType="dojo.data.ItemFileReadStore" id="osTypeStore" data-dojo-id="osTypeStore" url="/AjaxPopulateOS.json">
</div>
<select id="osType" data-dojo-type="dijit.form.ComboBox"
data-dojo-props="
id:'osType',
store: osTypeStore,
placeHolder: 'Select a schdule type'" >
</select>
Any ideas
I believe it is because there are no items in it? Is it grayed out totally - and have the Disabled class parameter set?
Check that dijit.byId('osTypeStore') returns a store and that it has items in it.
If this is the case, change your code to
store: 'osTypeStore'
Note the quotes. This forces parser to evaluate the string into a dijit - and the store might not have been initialized correctly as a true variable at the point it is read. In other words, in combobox constructor - the javascript variable is undefined.
If this does not help, try forcing to set store after onShow has run for your dialog.
dialog.onShow = function() {
dijit.byId('osType').set('store', dijit.byId('osTypeStore'));
}
Try forcing it to enabled using the property of the combo
enabled: true,
Other than that, check it using Firebug or debug bar or something similar :)

jQuery radio button change function not being triggered when it should

I have a problem with this jQuery Change function:
<input type="radio" name="words" value="8" checked><span class="word">word1</span>
<input type="radio" name="words" value="6"><span class="word">word2</span>
$("input[#name='words']:checked").change(function(){
alert("test");
});
The problem is that the event gets only triggered when I click the first option (value=8) which is checked by default.
How Can I trigger the event when clicking any other option?
Please note: I have tried the above function on both Chrome and Firefox and I have the same problem.
Thanks!
should be $("input[name='words']").change(function(){
You are only binding the event handler to :checked elements. So as the first input has the checked property set, that's the only one that receives the event handler. Remove :checked and it should work fine:
$("input[name='words']").change(function(){
alert("test");
});
Here's a working example. Note that I've also removed the # character from your selector. You haven't needed it since like jQuery 1.2 or something like that.
$("input[#name='words']:checked").change(function(){
That finds all the input elements with the name words (actually, it won't work: the XPath-style # attribute selector has been removed since jQuery 1.3) that are checked and binds an event handler to them. If the elements are not checked when the selection is made, no event handlers will be bound to them.
The easiest solution is to bind to all relevant elements, and only fire code if they have been unchecked:
$('input[name="words"]').change(function() {
if (!this.checked) { // checkbox was checked, now is not
alert('unchecked');
}
});
working link
$("input[name='words']").change(function(){
alert("test");
});
$("input[#name='words']:checked").change(function(){
alert("test");
});
You've subscribed change function only to the radiobuttons whitch is checked (:checked). Remove it from selector.
$("input[name='words']").change(function(){
alert("test");
});
Code: http://jsfiddle.net/DRasw/1/
Give id property of Radio buttons
Add property of OnClick="CheckClick()" on second redio button.
In jquery CheckClick() function
if ($('#rb2').attr('checked')) {
alert('rb2 test');
}