How to force element state using cypress - cypress

i have a link which gets a text-decoration:underline when hovering. But i can´t reproduce it using cypress.
I´ve tried ex. cy.get('a').trigger('mouseover') but nothing happens.
Is there a way to force the element to have :hover state?

Cypress does not support hovering. But in a previous question this workaround has been suggested:
it('hovering over button', () => {
cy.visit("http://www.qaclickacademy.com/practice.php");
cy.get('.mouse-hover-content').should('be.hidden').invoke('show');
})

Related

I can't access a pop-up with Cypress

i'm trying to run a simple Cypress scenario.
Access this url : https://www.harmonie-mutuelle.fr/ and close the pop-up that appears.
But the pop-up seems to have a weird behavior. It doesn't appear in the navigator on the right when i run my test but it appears in the middle of the screen as if it was a Cypress pop-up (i don't know if i'm clear)
Here is a my code :
cy.viewport(1920, 1080);
cy.visit('https://www.harmonie-mutuelle.fr/');
cy.get('#popin_tc_privacy_container_button > button').eq(2).click();
Any ideas as to how i can close that pop-up ?
ok managed to find a solution. Here's a way to do it using wrap if anyone needs this :
cy.visit('https://www.harmonie-mutuelle.fr/').then(() => {
cy.wrap(window.top.document.querySelector('#popin_tc_privacy_button_3')).click();
});
Nothing really wrong with your approach, but to explain what's happening -
Cypress commands like cy.get() starts searching at the <body> element. You can modify it using the .within() command.
Most commonly used to set the root element to a descendant element of <body> but should also work to move it to the parent <html> element, which is what your test requires.
cy.visit('https://www.harmonie-mutuelle.fr/');
cy.document()
.find('html')
.within(() => {
cy.get('#popin_tc_privacy_container_button > button').eq(2).click()
})

Broken cy.select() after cy.session() (cypress 10.09)

I think I've found an issue with cy.session(), but before opening one in the GitHub wanted to hear your ideas on my problem itself:
Implemented cy.session(), and it worked! For most of the pages...
The issue is with pages with <select> elements. After session() was implemented, the cy.select() stopped working. It chose the right option, and then it went right back to the previously selected option. The strangest thing is that is not seen even in the DOM snapshots. Removing cy.session() made everything work again.
So, my question is:
Does it feel like a cypress bug? Has anyone encountered this issue and got it somehow resolved? Cannot imagine any way how cy.selecting elements is related to sessions.
EDIT:
After further investigation, I found that selecting a page option changes one specific cookie value. This cookie has the page type code, thus I think that the new value is not saved to the cookie as it was before without cy.session()
Manually selecting in the browser from cypress open doesn't work either! After discovering that, I am pretty sure that it is the cypress bug.
As it was requested, here is my code:
commands.ts
Cypress.Commands.add('login', (user: User) => {
return cy.session(
[user.api_key],
() => {
cy.request({
...
});
},
{
validate() {
cy.visit('/');
cy.contains(user.username, { matchCase: false });
},
cacheAcrossSpecs: true,
}
);
});
e2e.ts
beforeEach(() => {
cy.getCurrentUser().then((user) => {
cy.login(user);
});
});
This issue gets resolved in Cypress 10.10!
Opened issue in cypress' GitHub and got an answer:
https://github.com/cypress-io/cypress/issues/24149

Mouseover in cypress

I am a newbie in cypress and trying to create some basic scripts for my learning, Handling dropdown by clicking the elements is fine, but hovering on the element is not working in this case, I can see the required element is getting hovered but the sub-menu is not appearing.
it.only('Mouse hover using trigger ', () => {
cy.visit('https://www.puregrips.com/pages/custom-grips')
cy.contains("a", "Custom").trigger('mouseover')
})
You can use the cypress-real-events plugin and this worked with your webpage.
To install use the command:
npm i cypress-real-events
Then inside your cypress/support/index.{js,ts}, write:
import "cypress-real-events/support";
And in your code you can directly write:
cy.contains("a", "Custom").realHover('mouse')
Note: Since the above plugin uses Chrome DevTools Protocols to simulate native events, hence this will only work with Chromium-based browsers, so no firefox.
Things I tried that didn't work -
cy.contains("a", "Custom").trigger('mouseover')
cy.contains("a", "Custom").invoke('show')
Just try this, it should work:
cy.get('.locater').invoke('show').click({ force: true })
cy.get('[your selector]')
.eq(0).invoke('show')
.trigger('mouseenter')
.wait(1000)
.should('have.attr','your-selector','Active tooltip')
.trigger('mouseleave');
This worked for me for the above problem.
Issue:
Timed out retrying after 5000ms: cy.trigger() failed because this element is not visible: CUSTOM
This element <a.header__linklist-link.link--animated> is not visible because its parent <ul.header__linklist.list--unstyled.hidden-pocket.hidden-lap> has CSS property: display: none
it.only("Mouse hover using trigger ", () => {
cy.viewport(1440, 660); //setting viewport as site is responsive web design
cy.visit("https://www.puregrips.com/pages/custom-grips"); //visit url
//used within to get parent and children to get the desired web-element
//and used invoke("show") to show the hidden elements
cy.get(".header__linklist").within(() => {
cy.get("li").contains("CUSTOM").invoke("show");
});
});
Added final screenshot:

Custom child command in cypress doesn't perform click

Background:
I'm writing test automation for a React web application, using Cypress. In the application I have a dialog box in which there are elements I need to click. When I try to click any of these elements normally, Cypress gives me an error that the element in not visible because its content is being clipped by one of its parent elements, which has a CSS property of overflow: 'hidden', 'scroll' or 'auto'. Because these DOM elements are generated by some 3rd party React components, I cannot change this, and the only way I can work-around it is to use {force:true} in the click command.
The problem:
Because I have few of these elements and in order to keep the DRY principle, I wanted to create a custom child command named forceClick that simply wraps subject.click({force:true}). However, for some reason, when I do that, Cypress does not perform the click command at all!
Note: For debugging purposes I added a cy.log command to the custom command as well, and strangely enough, I see that this log command is executed and only the click command doesn't.
Here's the code:
Cypress.Commands.add('forceClick', {prevSubject:'element'}, subject => {
cy.log('forceClick was called!');
subject.click({force:true})});
And inside my test I have the following line:
cy.get("[data-test='panel-VALUES']").forceClick();
Note that if I change it to the following line, it works as expected:
cy.get("[data-test='panel-VALUES']").click({force:true});
Any idea why the click command isn't executed by the forceClick custom command?
You are almost there, you just missed that you have to wrap the subject if you want to work with it.
Cypress.Commands.add('forceClick', {prevSubject: 'element'}, (subject, options) => {
// wrap the existing subject and do something with it
cy.wrap(subject).click({force:true})
})
I never saw a solution with subject.click({force:true}), I'm not saying it won't work, but I just never saw it before. What works anyway is this:
Custom command:
Cypress.Commands.add('forceClick', {prevSubject:'element'}, subject => {
cy.log('forceClick was called!');
cy.get(subject)
.click({force:true})});
}
Test step:
cy.forceClick('[data-test="panel-VALUES"]');
If you only use the forceClick you could even shorten it further to this:
Custom command:
Cypress.Commands.add('forceClick', {prevSubject:'element'}, subject => {
cy.log('forceClick was called!');
cy.get(`[data-test=${subject}]`)
.click({force:true})});
}
Test step:
cy.forceClick('panel-VALUES');

Selenium webdriver can't find button

EDIT:
I have cleaned this up a bit.
I have a button that looks like this:
<input id="applyRuleButton" class="Button" name="filtersContainer:applyRuleButton"
value="Apply" onclick="wicketShow('applyRuleButton--ajax-indicator');var
wcall=wicketSubmitFormById('id256', '?wicket:interface=:23:form:filtersContainer:applyRuleButton:
:IActivePageBehaviorListener:0:&wicket:ignoreIfNotActive=true',
'filtersContainer:applyRuleButton' ,function() { ;wicketHide('applyRuleButton--
ajax-indicator');}.bind(this),function() { ;wicketHide('applyRuleButton--
ajax-indicator');}.bind(this), function() {return
Wicket.$$(this)&&Wicket.$$('id256')}.bind(this));;; return false;" type="submit">
Firebug:
<input id="applyRuleButton" class="Button" type="submit"
onclick="wicketShow('applyRuleButton--ajax-indicator');var
wcall=wicketSubmitFormById('id2ee',
'?wicket:interface=:29:form:filtersContainer:applyRuleButton::IActivePageBehaviorListener:0
:&wicket:ignoreIfNotActive=true', 'filtersContainer:applyRuleButton' ,function() {
;wicketHide('applyRuleButton--ajax-indicator');}.bind(this),function() {
;wicketHide('applyRuleButton--ajax-indicator');}.bind(this), function() {return
Wicket.$$(this)&&Wicket.$$('id2ee')}.bind(this));;; return false;" value="Apply"
name="filtersContainer:applyRuleButton">
I'm trying to click it and have tried pretty much everything for 2 days, webdriver does not find the element, IDE does find it:
//This was my first approach, it should work.
It works in IDE, but not Webdriver:
driver.findElement(By.id("applyRuleButton")).click();
//then perhaps this should do the trick, hint: It doesn't:
WebElement element3 = driver.findElement(By.id("applyRuleButton"));
JavascriptExecutor executor3 = (JavascriptExecutor)driver;
executor3.executeScript("arguments[0].click();", element3);
Ok, Id not working, I get it.
Then this should work at least:
driver.findElement(By.xpath("//table/tbody/tr/td/div/div/table/tbody/tr[6]/td/input[#id='applyRuleButton']")).click();
It feels like I am missing something obvious here, some help please?
Additional information:
I have added a 5 second wait, the page is completely loaded.
This button is located in a table:
The Xpath is
/html/body/div[4]/div[2]/form/div[3]/div/div/table/tbody/tr/td/div/div/table/tbody/tr[6]/td/input
Webdriver error, no matter what I throw at it, is: Unable to locate element
I have used both 'click' and 'submit', still no success.
I think in this case there are two possibilities :
Either there is another element having same id/xpath.
OR Element present in another iframe.
Is the button visible. Selenium click (latest firefox 26 and latest webdriver 2.39.0) does not sometimes implicitly scroll; Or it may not scroll it fully. So scroll it into view - Scroll Element into View with Selenium and then it should work.
Note Selenium Best Practise try to use By.Id,By.CSSSelector and if nothing gets use By.Xpath in the order of priority. ( Use the FireFinder, FireBug plugin to test XPath or CSS)
This might be a synchronization issue. Such issues can be solved using smart waits.
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.ElementExists((By.Id("applyRuleButton"))));
WebElement element3 = driver.findElement(By.id("applyRuleButton"));
And that should work perfectly fine.
There is absolutely nothing wrong with your selector. I just don't think you're invoking the click correctly.
Try:
driver.findElement(By.id("applyRuleButton")).click();
If this doesn't work, then you might have to invoke a WebDriverWait since you have this question marked as [ajax]
Could you post the entire html?
As a simple experiment, I took the html snippet that you posted and wrote a short python script that invokes selenium:
from selenium import webdriver
br = webdriver.Firefox()
br.get("put your path to snippet here")
button = br.find_element_by_id("applyRuleButton")
print button.get_attribute("name")
button.click()
br.close()
I can find the button and extract the attribute "name" which prints "filtersContainer:applyRuleButton". This is admittedly a very limited experiment, but it suggests that the issue is related to not being where you think you are on the page.
Try this:
driver.findElement(By.Name("filtersContainer:applyRuleButton"));
If this doesn't help, check whether this button is located in any other frame. If so, you may have to find and move your focus to that frame and then locate this button.
First try to identify the button by writting correct xpath using firebug, if you are able to identify button by that xpath then use that xpath while writing your script.
driver.findElement(By.xpath("//input[# type='submit' and # id='applyRuleButton'")).click();
This is ajax application use proper explicit/ webdriver wait till the button gets downloaded
I see that this thread is old, but I was looking at it today (Sept/2021) as I was having the same problem: I could see the name / id/ type of the button, but it would never be found.
I discovered that when I had clicked in a prior link, it opened a new tab in my browser, but Selenium did not change the focus to the new tab, so it couldn't find the ID of the button I was looking for.
I solved it with :
driver.find_element_by_id("export").click() #driver
time.sleep(2)
driver.switch_to.window(driver.window_handles[1]) # Change focus to the new tab
driver.find_element_by_id("0001btn").click() #click
driver.close() #close new tab
switching to a specific frame helped me to resolve the same issue. (python + selenium)
I installed the Selenium Recorder extension on chrome and recorded my steps, and found out that the recorder had a step to select a frame = 0, so adding
self.home_page.driver.switch_to.frame(0)
self.home_page.click_on_element_by_id("clickSubmit")
solved the problem.

Resources