I have a table with a variable number of tr elements. Each tr is clickable and when clicked a modal opens (always the same modal for each tr). In the modal a toggle has to be set:
it('Set payment methods', () => {
cy.el('tablePaymentMethods')
.children()
.each(($el, index) => {
cy.intercept({
method: 'PATCH',
url: `${Cypress.env('API_URL')}/api/v1/company/*/paymentMethod/*?cache_buster=*`,
}).as('paymentMethod');
cy.wrap($el).click();
cy.el('toggleActive').click();
cy.el('btnEditPaymentMethod').click();
cy.wait('#paymentMethod').then((data: any) => {
expect(data.response.body.data.active).to.eq(true);
});
});
});
The problem with this test is that Cypress executes them at the same time, showing me the error:
is being covered by another element
I can use force: true to still click on the toggle but I would much rather wait with clicking on the second tr when the cy.wait() has gotten a response (meaning the first modal is closed).
Related
I have below issue in cypress:
Get all delete buttons.
Iterate over each delete button.
click on each button.
Navigate to delete confirmation page(it is different page all together not a popup)
Click on (red) Delete button (will be navigated back to list page)
Perform same action on remaining shopping lists
cy.get('a[href*=delete][href$=confirm]').each(($ele) => {
cy.wrap($ele).click({ force: true });
// on confirm delete screen
cy.contains('button', 'Delete').click({force: true,});
Try repeating the get inside the loop
const selector = 'a[href*=delete][href$=confirm]'
cy.get(selector).each(($el, index) => {
cy.get(selector).first()
.click({ force: true })
// on confirm delete screen
cy.contains('button', 'Delete').click({force: true,})
cy.contains('h1', 'Name').should('be.visible') // confirm we are back on 1st page
})
I have a page with a few Results panels, each panel has its own delete button.
I wrote a Cypress test to test the delete process, the test works as expected, the panel gets deleted:
cy.get('div[data-test="Results"]')
.first()
.within(() => {
cy.get('p[data-test="Contact ID"]').then($match => {
contactID = $match.html();
cy.get('button[data-test="Delete Contact"]')
.click()
.get('div[data-test="Delete Record Modal"]')
.should('be.visible')
.get('button[data-test="Confirm Deletion"]')
.click();
});
});
Next I'm trying to detect if the correct panel got deleted.
How can I iterate through all the <p />s of all panels and make sure none of them has a contactID equal to the one that was deleted?
I tried this:
cy.get('p[data-test="ContactID"]').then($match2 => {
expect($match2.text()).not.to.eq(contactID);
});
But in $match2 I get all contacts ids all together for example: 12345678 instead of 1234 and 5678
You can use each:
cy.get('p[data-test="ContactID"]').each(($match) => {
cy.wrap($match).invoke('text').should('not.eq', contactID)
})
invoke calls a function on the subject, in this case, .text()
the chained .should makes an assertion on that text
this will retry the assertion until it passes or times out (see retry-ability) due to the cy.wrap
I have a single page mark-up with popup divs that contain forms that the user can use to update his/her account information. After form submission the popup closes and the page refreshes showing the updated information that is located within a li (this seems to be working). The problem is, if the user goes back and tries to update again the button within the popup is not submitting.
Thanks in advance for any suggestions!!!
Javascript
$('#updateadmin').click(function() {
var admin = $('#adminform').serializeArray();
/*alert(admin);*/
$.ajax({
type: "POST",
url: 'adminupdate.php',
data: admin,
success: function(data) {
if(data=="success") {
$('#admindiv').popup('close');
$.mobile.changePage('companyinfo.php', {
allowSamePageTransition: true,
transition: 'none',
reloadPage: true,
changeHash: false
});
} else {
$('#adminupdatestatus').html(data).css({color: "red"}).fadeIn(1000);
}
}
});
return false;
});
It sounds like the #updateadmin link/button is located on the page that gets reloaded, if this is the case then you should delegate your event handler so it affects matching elements in the DOM for all time, not just when the code runs.
You would change this:
$('#updateadmin').click(function() {
to this:
$(document).on("click", "#updateadmin", function() {
This works because you're now attaching the event handler to the document element which always exists. When events reach the document element they are checked to see if the element on which they originally fired matches the selector we put as the second argument for .on().
Documentation for .on(): http://api.jquery.com/on
Trying to find out why this jQuery JS isn't making ajax call though it is being called for execution.
I have this button to make an ajax GET request to a method in the controller, the method will partial render. When I click on the button I don't see any request coming on the console but I see the alert "test" on the browser.
I have the same exact JS with other parameters working for other tupes of ajax calls, so I just copied one of them and changed all required parameters, expecting it shall work right away. Neither I get any errors on the console. My routes and id names are good and verified. What is it that I am missing here?
view - Note: this button is rendered via a different ajax, that part works.
<%= button_tag "Add / Remove", :id => "add_remove_button", :onclick => "javascript:add_remove();" %> #note: this is buried under div tags in a html table
JS-
function add_remove(){
$('#add_remove_button').click(function() {
$.ajax({
type: 'GET',
url: "/item/add_remove",
success:$('#view_item').html(data)
/*function(){ },
data:$('#test').serialize(),
error: function(){ },
success: function(data){ },
complete: function (){ }*/
}); #No ajax call made
/*return false;*/
});
alert('test'); #I get this alert
}
You'll always see that alert() because click() is asynchronous: the code inside the function() passed to click does not get executed until you click, but the rest of add_remove() will get called.
Here's what is actually happening in your code, which explains why the AJAX call doesn't get made:
Using :onclick => ... attaches add_remove() to your button.
You click the button, add_remove() gets called and attaches another click callback to your button. Then add_remove() calls alert(). There is no AJAX call happening here, just adding a new click handler, and sending an alert.
You click the button a second time, and you will attach a third click callback to the button. However since you also attached a click handler the first time you clicked the button, you should see an AJAX request here.
Click it a third time and you'll see two AJAX requests this time, for a total of 3 AJAX requests.
Here's what you actually want to do. Remove the :onclick => ... from the button:
<%= button_tag "Add / Remove", :id => "add_remove_button" %>
Attach a click event to the button when the page first loads:
$(function(){
$('#add_remove_button').click(function() {
$.ajax({
type: 'GET',
url: "/item/add_remove",
success: function(data) { $('#view_item').html(data); },
data: $('#test').serialize(),
error: function(){ },
success: function(data){ },
complete: function (){ }
});
return false;
});
});
You are mixing up the jquery-registering-callbacks style and the old event-handler attributes. So you triggered the registering when calling the add_remove function.
Simply remove the :onclick stuff and function add_remove(){ ... }
I have an ajax request which brings in new posts and each post has a toggle button to show and hide an element which is hidden by default.
The below code works, but with the inserted ajax data it only works the first time (open) and not the second (close)
$(".voice_btn").live( 'click', function(){
$(this).toggleClass('active voice_btn');
$(this).closest('.element').children('.voice_box').toggle(300);
$('.tipsy').hide();
$(this).attr("title", ($(this).hasClass("active")?"Close":"Open") + " voicebox");
return false;
});
If you remove the voice_btn class from the element, it will no longer trigger the click event because it no longer satisfies the selector.
change
$(this).toggleClass('active voice_btn');
to
$(this).toggleClass('active');
just update line 2 to only toggle the active class, because after the first time your code runs the voice_btn class is removed, and your live function is no longer attached to your element:
$(".voice_btn").live( 'click', function(){
$(this).toggleClass('active'); // <- notice the change in this line
$(this).closest('.element').children('.voice_box').toggle(300);
$('.tipsy').hide();
$(this).attr("title", ($(this).hasClass("active")?"Close":"Open") + " voicebox");
return false;
});