I have a question: What happens if I need to create a course of action based on an assert in Cypress? Suppose that when entering a certain page, there is a pop-up window that is visible randomly; sometimes it appears and sometimes it doesn't. So, I need to click the "OK" button on that popup when it appears just to make it go away. How can I make sure that the test does not fail on occasions when that window does not appear? The test fails since it does not find the corresponding element to the "Accept" button. How do I make it ignore that action when the window doesn't appear? Thank you in advance.
I tryed with something like this, but it doesn't work:
if(cy.get('#pop-up-window-1').should('exist')){
cy.get('#btn-accept').click()
}else{
nothing
}
You can do something like this. Check the length and if its greater than 0, then element is present, if not then element is not present.
cy.get('body').then(($body) => {
if ($body.find('#pop-up-window-1').length > 0) {
//pop up is present
cy.get('#btn-accept').click()
} else {
cy.log('Pop Up not present. Moving on..')
}
})
Using conditional testing can give you a flaky test.
If you test for the presence of the popup with if ($body.find('#pop-up-window-1').length) the timing may be off, and sometimes it works and sometimes it does not.
That's particularly true if the modal uses animation to open.
One option is to wait for a suitable period before checking
cy.wait(3000)
cy.get('body').then($body => {
if ($body.find('#pop-up-window-1').length) {
cy.get('#btn-accept').click()
}
})
Related
I have a protractor test looking for a record in my infinite scroller component like this.
searchPage.searchEntitlement('search criteria');
var myHiddenElementInScroller = element(by.repeater('result in ctrl.results track by $index').row(12));
browser.driver.executeScript(function () { arguments[0].scrollIntoView(); }, myHiddenElementInScroller .getWebElement());
myHiddenElementInScroller.click();
This is supposed to scroll to the element and click it. Instead its throwing me element not visible error.
Has anyone come across this situation? Any help greatly appreciated.
You might need to explicitly wait for the scrolling into view actually happen:
browser.driver.executeScript("arguments[0].scrollIntoView()", myHiddenElementInScroller.getWebElement()).then(function () {
myHiddenElementInScroller.click();
});
Or, with browser.actions():
browser.actions().mouseMove(myHiddenElementInScroller).click().perform();
In few scenarios the element which we are looking for will be covered with some other element from DOM.when protractor tries to click it,the click will be received by the element that covers the actual element. So in such situation you need to use native javascript click event. Look at the below code.
browser.executeScript("arguments[0].click()", myHiddenElementInScroller.getWebElement())
The above code will send a click event directly to the mentioned webElement even if it is visible or not.
NOTE: this is not the recommended way for clicking an element. but you can you this in scenarios where you have no other workaround to achieve the click event.
Thanks for all the responses. I was able to resolve this issue by using element(by.CssContainingText(cssSelector, searchText)) locator.
(Follow on questions from Placeholder Hidden)
I'd like my form to validate existing data when it is loaded. I can't seem to get that to happen
I jQuery.each of my controls and call focus() and blur(), is there a better way than this? I tried to call ctrl.checkValidity(), but it wasn't always defined yet. When it was, it still didn't mark the controls.
I seem to have a timing issue too, while the focus and blur() fire, the UI does not update. It's as if the Webshims are not fully loaded yet, even though this fires in the $.webshims.ready event.
I also tried to call $('#form').submit(), but this doesn't fire the events as I expected. The only way I could make that happen was to include an input type='submit'. How can I pragmatically case a form validation like clicking a submit button would?
Here's a jsFiddle that demonstrates the problem. When the form loads, I want the invalid email to be marked as such. If you click the add button it will be marked then, but not when initially loaded. Why?
Focus and blur in the control will cause it to be marked.
BUT, clicking ADD will too (which runs the same method that ran when it was loaded). Why does it work the 2nd time, but not when initially loaded?
updateValidation : function () {
this.$el.find('[placeholder]').each(function (index, ctrl) {
var $ctrl = $(ctrl);
if( $ctrl.val() !== "" && (ctrl.checkValidity && !ctrl.checkValidity()) ) {
// alert('Do validity check!');
$ctrl.focus();
$ctrl.blur();
}
});
}
I see this in FF 17.0.5. The problem is worse in IE9, sometimes taking 2 or 3 clicks of ADD before the fields show in error. However, I get errors on some of the js files I've liked 'due to mime type mismatch'.
This has to do with the fact, that you are trying to reuse the .user-error class, which is a "shim" for the CSS4 :user-error and shouldn't be triggered from script. The user-error scripts are loaded after onload or as soon as a user seems to interact with an invalid from.
From my point of view, you shouldn't use user-error and instead create your own class. You can simply check for validity using the ':invalid' selector:
$(this)[ $(this).is(':invalid') ? 'addClass' : 'removeClass']('invalid-value');
Simply write a function with similar code and bind them to events like change, input and so on and call it on start.
In case you still want to use user-error, you could do the following, but I would not recommend:
$.webshims.polyfill('forms');
//force webshims to load form-validation module as soon as possible
$.webshims.loader.loadList(['form-validation']);
//wait until form-validation is loaded
$.webshims.ready('DOM form-validation', function(){
$('input:invalid')
.filter(function(){
return !!$(this).val();
})
.trigger('refreshvalidityui')
;
});
I'm using an html select element as an active menu. When you select an item from it, it does an action and then in some cases, a side effect of the action is resetting the value of the menu to something else.
function onMenuChangeHandler() {
var menu = $('#menu');
var menuChoice = menu.val();
if (menuChoice == ...) {
...
menu.blur(); // ensure change handler doesn't get fired again
menu.val(OTHER_VALUE); // **
}
};
This works fine on the desktop in multiple browsers and works fine on iOS5. It inexplicably stopped working on iOS6. The result is that it acts as if the line marked ** above is not there.
It works fine in any case where I don't set the value.
FYI: There's another change in iOS6 which seems unrelated to this but mentioning it just in case. When the menu is selected, it now dismisses the picker immediately rather than leaving it open. This is how it works on every other platform. If you have more more than one select element, you still get the non-standard behavior.
I spent a lot of time trying to track this down and eventually discovered that the problem is that iOS6 sets the value of the control a second time after my change handler exits. If I put in alerts, I can clearly see that the control changes to the OTHER_VALUE (underneath the alert). Then when I dismiss the alert, the control reverts. (Without the alert, the change happens too fast to see.)
So here's a workaround:
function onMenuChangeHandler() {
var menu = $('#menu');
var menuChoice = menu.val();
if (menuChoice == ...) {
...
setTimeout(function() {
menu.blur(); // ensure change handler doesn't get fired again
menu.val(OTHER_VALUE);
}, 1);
}
};
Maybe someone else has a better answer or a better explanation.
I have been fiddling with a few lines of code for two days now and for some reason I cannot get it running.
What I want:
A user selects a relation from a combobox and subsequently must select a person from a list of persons filtered by the first combobox. If there is only one person, it must be selected outright. If it has more than one, I want the combobox to expand and of course show the list of retrieved persons. Sounds pretty simple.
The onRelationContactSelect() is code which is normally executed when a person is selected. Since the select event isn't triggered when setting a value manually, I simply call it by hand. I have the code in the callback of the load event to ensure the data is retrieved from the server. That is required to expand in the first place or select a record.
The problem:
When I have one record (records.length == 1) everything works like a charm. When I have more than 1 record, the combobox contactCombo fails to expand. I debugged quite a bit through the ExtJs internal code and the reason is that is has no focus. No matter what I try with calling contactCombo.focus(), it does not focus. Therefore it won't expand. To make it even more annoying I can expand another combobox with the following code:
function onRelationContactSelect() {
categorieStore.load({ callback: function(r, options, success) {
//debugger;
//categorieCombo.focus();
//categorieCombo.expand();
}});
categorieCombo.focus();
categorieCombo.expand();
}
As can be seen I call focus() and expand() outside of the callback but the mode of categorieStore is 'local'. The data in categorieStore is static but still retrieved from the server.
The code:
function onRelatieSelect() {
contactStore.baseParams = {"relatieId": relatieCombo.value };
contactStore.load({callback: function(records, options, success) {
if(records.length == 1) {
contactCombo.setValue(records[0].get('Id'));
onRelationContactSelect();
} else {
contactCombo.clearValue();
contactCombo.focus();
contactCombo.expand();
}
}});
openTicketRelationLabel.show();
gridTicketRelatie.show();
ticketRelatieStore.load({ params: {relatieId:relatieCombo.value}});
SetRelatieInfo();
SetContractsInfo();
setSfHoursOsab();
showRelationNotifications(relatieCombo.value);
}
I have tried for ages, but it seems I simply cannot focus a combobox from within the callback handler and outside of the callback handler I have no data yet.
Can anybody please help me out?
After sandboxing two different comboboxes I found the solution.
The solution turned out to be weird but simple:
categorieCombo.on('select', function() {
subcategorieCombo.focus();
subcategorieStore.load({ callback: function(r, options, success) {
subcategorieCombo.focus();
subcategorieCombo.expand();
} });
Focus before the load.
Focus again in the callback of the load.
The only dissatisfying about this solution except from needing to focus twice is that I have no clue whatsoever why this works, but it solved the problem for me.
I'm using extJS 4.
I have a form pop up every time you click edit profile.
The problem is that every time you click edit Profile another form pops up so you can just keep clicking.
Is there a way to make the form only pop up if there isn't one already up.
Thanks for the help!!!
The problem sounds like you are creating a new window on every click of the "edit profile" button/link.
What you need to do is put a check in at the beginning of your form code to check to see if it exists first. If it doesn't, create the window and .show() it... Otherwise, you will just need to .show() it. Be sure to also reset the form if need be. You will also want to try and hide the window instead of destroying it. Otherwise, you will be creating new objects every time.
You can make your form modal, so to block entire interface until you close it, or you can use something like this to your controller to create form:
editProfile: function(button) {
var me = this;
if (!me.win) {
me.win = Ext.widget('editProfile');
// delete the me.win reference if the window gets destroyed
me.win.on('destroy', function() {
delete me.win;
return;
});
}
me.win.show();
}