Unable to Click on a <div> button using Selenium WebDriver - google-chrome

I want to click a button which is actually a <div> tag. I am unable to click on it.
HTML snippet
<div id="search_product" class="ng-scope" ng-init="init({ searchPath: { simple: '/marketing/campaigns/search_product', advanced: '/marketing/campaigns/search' }, searchLimit: 5000 })" rms-modal="">
Here is Selenium Webdriver code for the click operation:
driver.findElement(By.className("ng-scope")).click();

Have you tried driver.findElement(By.id("search_product")).click();
the problem seems to be with the locator you have selected. There can be multiple div elements with the same class name. Selenium finds the first element which matches the locator and fires the action upon it.

Related

Cypress or Puppeteer: How to test page with a react select popup/popover?

Request:
Either with Cypress (preferably) or using extending Cypress with Puppeteer via cy.task(), being able to perform a test on a system-generated popup menu?
This popup menu element cannot be inspected by Chrome Devtools and is thereby not navigatable by either CSS selectors or XPath.
Details: I am using Cypress for UX testing and extend in limited cases with custom cy.task() with Puppeteer.
The web page under test has a dropdown selection that generates a popup menu, source is this npm module:
npm react-select-async-paginate
Under inspections, the popup menu is generated from an and it has these two attributes:
aria-haspopup="true"
role="combobox"
Appreciate assistance, thank you
22 Feb, Updated
This is the generated react-select-async-paginate:
<div>
<div class="***-singleValue">Offer Letter w/ Signature</div>
<div class=" css-ackcql" data-value="">
<input
id="react-select-2-input"
aria-autocomplete="list"
aria-expanded="false"
aria-haspopup="true"
aria-controls="react-select-2-listbox"
aria-owns="react-select-2-listbox"
role="combobox">
</div>
</div>
This is the attempt for selecting an option, but it does not loads selected option into <div class="***-singleValue">.
This Cypress script selects an option:
cy.get(`${selectorReactSelectPaginate}`)
.find('input[role="combobox"]')
.focus()
.type($valueSelect, { force: true })
.then(() => {
cy.wrap(true);
});
As would able to validated using this Cypress script:
cy.get(selectorReactSelectPaginate)
.find('div[class*="-singleValue"]')
.contains($valueSelectContains)
.then(() => {
cy.wrap(true);
});
Yes, the option list is tricky to get at in devtools because of the blur event (which comes from the library itself). One approach is open devtools and watch carefully as you click open the select.
Using react-select-async-paginate - Simple Example, when I click open the select I can see this div appearing and disappearing
<div id="react-select-2-listbox">
So I can use Cypress to get a look inside that
cy.get('[role="combobox"]').click()
cy.get('#react-select-2-listbox')
.then($listbox => {
console.log($listbox)
})
Now in devtools console, check out children property (has one child), then the child's children - these look like the options to be tested.
The common selector is an id starting with react-select-2-option, so I can test like so
cy.get('[role="combobox"]').click()
cy.get('#react-select-2-listbox')
.find('[id^="react-select-2-option"]') // all div's with id starting react-select-2-option
.should('have.length', 10)
.eq(3) // check out the 4th option
.invoke('text')
.should('eq', 'Option 4') // passes
Selecting an option by typing into the box
Two things affect this method of selecting
the dropdown list changes (reloads) as you type characters
the element 'div[class*="-singleValue"]' only appears after you confirm the typed value (either enter key or blur(), I'm not sure which).
This worked for me
// Type in the option
cy.get(selectorReactSelectPaginate)
.find('[role="combobox"]')
.type(valueToSelect)
// Wait for the listbox to respond
cy.get('#react-select-2-listbox')
.should('contain', valueToSelect)
// Blur or enter will set the value
cy.get(selectorReactSelectPaginate)
.find('[role="combobox"]')
.type('{enter}')
.blur()
// Check the value
cy.get(selectorReactSelectPaginate)
.find('div[class*="-singleValue"]')
.should('contain', valueToSelect)
A neat trick with test runner is to add a .wait() after the dropdown selection appears. A snapshot of the DOM will be created and you can click on the .wait() to view the snapshot and use dev tools to inspect the dropdown selection.

Selenium IDE clicking checkbox doesn't work after downloading file

Using the Selenium IDE in Chrome I am making a test for a process on a website.
I have a website, where I need to click a checkbox to accept the terms of use, privacy terms etc. after the login. I can check those boxes without a problem through Selenium, but I can't check the box for the client terms. I have to download those first, what works without a problem. Selenium then doesn't check the accept box though.
I am using the whole xpath and when I tell Selenium to show me the element in the website, it shows me the correct one. I copied the xpath directly out of Chrome. I'm using following command.
Command: click
Target: xpath=/html/body/div[1]/div[2]/main/div/div[3]/div[3]/div[3]/label
I also tried following other targets, none of them worked. Nevertheless Selenium always showed the right label when I clicked the option "Find Target in Page".
css=.terms-client label
xpath=//div[3]/div[3]/label
xpath=//label[contains(.,'Ich akzeptiere die Prüfungsbestimmungen')]
I tried check instead of click too, what didn't work. This is the HTML-code of the affected element, after the client terms have been downloaded already.
<div class="terms-client card" ng-repeat="role in data.roles" style="">
<div class="header">Kandidat/-in: Elektroniker/in EFZ CH</div>
<div class="content">
<p ng-bind-html="(role.description || ('terms.client.terms'|trans))|nl2br">Bitte studieren Sie die Prüfungsbestimmungen sorgfältig.</p>
<span iv-ipa-dokument="role.url" btn-class="btn-fill" download-state="role.downloaded" btn-label="Bestimmungen herunterladen"><button ng-click="download(url)" class="btn btn-fill" ng-disabled="disabled"><i class="icon icon-check-square-o" ng-class="class"></i> Bestimmungen herunterladen</button></span>
</div>
<div class="accept">
<!---->
<input id="client-accept-0" class="checkbox-new client-accept ng-pristine ng-untouched ng-valid ng-empty" type="checkbox" ng-model="role.state" ng-disabled="!data.agb || role.accepted || !role.downloaded">
<label for="client-accept-0">Ich akzeptiere die Prüfungsbestimmungen</label>
<!---->
</div>
</div>
The label at the end is the part I would like to click. I don't understand why Selenium is able to check the other boxes and accept those terms, but not this one.
I noticed, the issue is, that the click stops working after downloading the terms. Before that it works.
I think the issue is the locator being used to locate the checkbox. With the information provided, I guess the click event isn't handled for the label used.
Instead of getting the XPATH of the label, you need to select the input tag of the checkbox you need to click.
In this case the xpath of the element to select should be :
//label[contains(.,'Ich akzeptiere die Prüfungsbestimmungen')]/../input
Clicking using this element selector should perform the intended click.
I didn't find a proper solution but a workaround. A simple reload of the page after the download managed to solve my issue.

html Button on top of link

Hey I have a div which is wrapped by a Link component, and inside that div I have more buttons, but the problem is, when I click on the inner smaller buttons, I actually click on the Link component as well, so I get redirected which is not what I want... How do I fix this?
it seems as though both the link and the button get clicked but if i am intending to click the button only i want to avoid the parent link.
What I mean is, the Link is used to navigate to some URL when you click on it. Putting elements inside that for other tasks. like a blog post, you click on the parent it will redirect you, but on the child the button will allow you to delete it
was coding this in nodejs react so i was using onClick events
example
<Link to="/blog-post">
<div className="link-post-container">
...blog
<button className='deleteButton'></button>
</div>
</Link>
I have tried event.stopPropagation on the button but it still doesn't seem to do anything. Is it because the Link is an href instead of a onClick?
SOLUTION
so using some of the possible solutions below i started messing around and noticed by in the onClick of the deleteButton, if i add the following in, it works:
event.preventDefault()
with this, the redirect because of the href does not occur anymore and only the button click event will take place
const handleClick = event => {
event.stopPropagation()
// then write rest of your onclick code
}
<button className='deleteButton' onClick={handleClick}></button>
The click event propagates from the button upwards in the DOM tree until it reaches the root (simplified explanation - you can learn more about event propagation here). This is why the link also registers it and runs its onclick handler, redirecting you to another site.
You can call event.stopPropagation() inside your button's onClick handler to stop the event from reaching the encapsulating link.
source

headless chrome + rspec not able to select option form select list it gives error capybara element not found

I am using headless chrome, rspec - 3.6.0, capybara - 2.15.1
select('apple',from: 'fruits', visible: false)
page.find('#apple', visible: false).click
within 'results' do
page.find('.option', text: 'apple').click
end
Error:
Capybara::ElementNotFound: Unable to find visible css "#fruits .chosen-drop .chosen-results"
The error shown in your question is not from any of the other lines of code you show, however based on the error message it's pretty clear what's going on.
Attempting to perform any action on an element you've found using visible: false makes no sense because the user can't interact with a non-visible element (99% of time if you specify visible: false you're doing something wrong). In the current case you are using the chosen library which hides the normal HTML <select> element and replaces it with a JS driven widget made up of <ul> and <li> elements. Because of this you can't use the normal select method and instead need to interact with the page just like a normal user would (click on the 'chosen' field and then click on the element from the list). You haven't provided the actual HTML generated for your page, but based on your attempts and the output generated by the chosen demo page - https://harvesthq.github.io/chosen/ - it will be something like
<select id="fruits" ... style="display: none;>
...
</select>
<div class="chosen-container" ... >
...
<div class="chosen-drop">
...
<ul class="chosen-results">
<li ...>Apple</li>
<li ...>Orange</li>
...
</ul>
</div>
</div>
So to work with that the user would first need to click on the .chosen-conatiner element (sibling of the hidden select) to open the .chosen-drop element and then click on the correct <li> from the .chosen-results element which translates into something like
chosen_container = find('select#fruits + .chosen-container').click
chosen_container.find('.chosen-results li', exact_text: 'Apple').click
If that doesn't work for you then you'll need to add the exact HTML from your live page to your question.
Note: if you're dealing with a lot of chosen widgets in your site you may want to look into writing custom Capybara selectors -https://www.rubydoc.info/github/teamcapybara/capybara/Capybara#add_selector-class_method - to make the tests read a lot better

Selenium WebDriver - no such element: Unable to locate element

I have a problem with simple click on button. It's button is CSS.
<div id="rightBtn">
<input type="submit" class="mainButton" id="dodajTrenera" value="Dodaj" name="dodaj_trenera">
</div>
I would like to perform click action and I use this code:
WebElement addTrainer = driver.findElement(By.name("dodaj_trenera"));
addTrainer.click();
I get error:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"name","selector":"dodaj_trenera"}
Why I get this error? It should work perfect.
This button is located at the bottom of web. Maybe I should scroll page down?
Most commonly such error is a synchronization issue: try to wait for element to be present and clickable before clicking on it, like this:
WebElement addTrainer = (new WebDriverWait(driver, 10)).until(ExpectedConditions.elementToBeClickable(By.name("dodaj_trenera")));
addTrainer.click();
Of course the time you wait can be changed from 10 to whatever makes sense for your page.
WebElement element = driver.findElement(By.name("dodaj_trenera"));
((JavascriptExecutor)driver).executeScript("arguments[0].click();", element);