How to click on a deeply buried button in div classes via protractor. No id - angularjs

I am trying to click a button that is buried in div classes in the code via protractor.
I am pioneering a protractor project for my work and have reached a point where I no longer know what to do. I have a button that is buried in div classes and is not allowing me to click. I have tried using mouseMove to get over to the coordinates of the button, I have tried using the className of the specific button, etc. The button does not have an id. The id is not the issue as I have tried clicking a different button, equally buried in divs, by it's id. I need to know how to get through the layers of divs in order to click the button because the rest of the tests will be dependent on it.
APPLICATION CODE:
::before
<dashboard-label>
<div class="att-topic-analysis-tabs">
<div class="att-button-group">
<button class="btn btn-default btn-lg att-close-topic ng-scope"
role="presentation" tabindex="-1"
ng-click="removeTopic(currentTopic.id)" translate>
Close Topic
</button>
</div>
</div>
PROTRACTOR TEST:
it('Closes Topic Successfully', function(){
//opens the first available topic
openTopic.click();
//checks that the URL contains 'topics' after 5 seconds
browser.wait(proExpect.urlContains('topics'), 5000);
var closeTopic = element(by.className('att-close-topic'));
//browser.wait(proExpect.elementToBeClickable(closeTopicButton), 5000);
console.log(closeTopic);
closeTopic.click();
browser.wait(proExpect.urlContains('home'), 5000);
});
As you can see, the Close Topic button is kind of buried in div classes and the standard click isn't working. Any info would be greatly appreciated

If the closeTopic locator is finding the element, but failing to click it, check to make sure there's only one matching element in the DOM, and that it's visible. My favorite way to check the DOM is just ctrl-F in Chrome inspector and paste the exact CSS that the test is using (.att-close-topic). And to check that what it's getting is visible, use
console.log(closeTopic.isDisplayed());
This can be a big gotcha in protractor, because it doesn't fail (only warns) when there are multiple matches on the page, and it defaults to the first match rather than the first visible match, which drives me nuts, because it's very rare that you want to do anything with a non-visible element on the page.
This will be partly opinion, but just to add a layer to the conversation...
Sometimes the solution to locating a troublesome element on the page is to go back to the developers and make the page more testable. I've seen testers spend hours or days crafting brilliant workarounds to access a stubborn element, and the end result was a fragile, complicated end-to-end test (and aren't they fragile enough already?).
Sometimes a 5-minute conversation with a developer can result in a quick change in the production code (e.g. add a unique ID) that avoids all that effort and yields a much better result, more stable, more simple. But this requires open conversation between the dev and test team, and a culture that values testing as a primary activity enough to make those testability changes to production code that is otherwise working just fine.

This is what you want to read to help you debug why your test doesn't work.
Also, you might want to start adopting await/async since the control flow will go away in the future.
http://www.protractortest.org/#/debugging

try this
var closebutton=element(by.css("[ng-click="removeTopic(currentTopic.id)"]"),
EC = protractor.ExpectedConditions;
Waits for the element to be clickable.checks for display and enable state of button
browser.wait(EC.elementToBeClickable(closebutton), 10000);
now use : closebutton.click();

Related

Testing workflow with Cypress and React

I have question regarding the development and testing workflow. I am using Cypress but this topic is suitable for any end to end test.
The question is how do you selecting the elements in the browser?
1, Explicit selectors like data-cy or automation-id on each element or component.
2, Selecting the elements by visible text on the screen and then navigate to specific element by DOM hierarchy.
Every test you write will include selectors for elements. To save yourself a lot of headaches, you should write selectors that are resilient to changes.
Oftentimes we see users run into problems targeting their elements because:
Your application may use dynamic classes or ID's that change
Your selectors break from development changes to CSS styles or JS behavior
Luckily, it is possible to avoid both of these problems.
Don't target elements based on CSS attributes such as: id, class, tag
Don't target elements that may change their textContent
Add data-* attributes to make it easier to target elements
<button
id="main"
class="btn btn-large"
name="submission"
role="button"
data-cy="submit"
>
Submit
</button>
And then for example clicking to button
cy.get("[data-cy=submit]")
.should("be.visible")
.click()
You can also search for specific text in dom.
cy.get("button")
.should("be.visible")
.contains("Submit")
.click()
Custom commmands commands.js
Cypress.Commands.add("sendBtn", () => {
cy.get("[data-cy=cy_send_btn]")
.should("be.visible")
.click()
})
And in test file
it("Add test description here", function() {
.
.
.
.
cy.sendBtn()
})
Custom command shown above you will be able to use multiple times in other test files for all send buttons. Your tests will be more isolated and efficient.

How to create my own xpath on website- Selenium

I'm writing a small application to go on to twitter.com select the login button and then enter username and password.
I've been able to inspect the log in button and copy the XPath from chrome but I've been unsuccessful in create my own XPath from the information given. The XPath used when copied does work but it doesn't look tidy in my code therefore I'm keen to write my own.
WebDriver driver = new ChromeDriver();
driver.get("http://www.twitter.com");
driver.findElement(By.xpath("//*[#id=\"react-root\"]/div/div/div/main/div/div/div[1]/div[1]/div/div[3]/a[2]/div")).click();
Below is what is given when I inspect the log in button.
<div dir="auto" class="css-901oao r-1awozwy r-13gxpu9 r-6koalj r-18u37iz r-16y2uox r-1qd0xha r-a023e6 r-b88u0q r-1777fci r-ad9z0x r-dnmrzs r-bcqeeo r-q4m81j r-qvutc0">
<span class="css-901oao css-16my406 css-bfa6kz r-poiln3 r-bcqeeo r-qvutc0">
<span class="css-901oao css-16my406 r-poiln3 r-bcqeeo r-qvutc0">Log in</span>
</span>
</div>
You can identify the login button based on his parent unique attributes.
Then using the xpath axe /descendant, to selects all the descendants (children, grandchildren, etc.) of the current node, you can navigate down to the span that has the text Log in
driver.findElement(By.xpath("//a[#data-testid='loginButton']/descendant::span[text()='Log in']")).click();
Or
driver.findElement(By.xpath("//a[#href='/login']/descendant::span[text()='Log in']")).click();
If you want to study the xpath/css selector have a look here: https://devhints.io/xpath
I'm not sure what answer you are looking for so here are several possibilities:
Just give me the codez!
A: Try //a[#data-testid='loginButton']
How do I read the source of a page so that I can craft proper XPath?
A: That comes from experience. As a start, open your devtools and hover around with your mouse to see what element highlights what on the page. Read carefully through the attributes.
Where do I learn proper XPath?
A: Search on the Internet for some tutorials. Personally I started with this one, and then build up from there.

Element not visible with button click in selenium chrome driver

I'm trying to click the continue button after filling in the fields on this webpage. But an exception is thrown saying element is not visible even though I maximize the screen and you can clearly see the button.
I have tried the following even with waiting 10 seconds for the page:
driver.findElement(By.xpath("//*[#id=\"submitButton\"]/span")).click();
driver.findElement(By.cssSelector("#submitButton > span")).click();
driver.findElement(By.partialLinkText("Continue")).click();
driver.findElement(By.className("caret_rebrand")).click();
driver.findElement(By.name("submitButton")).click();
driver.findElement(By.xpath("//span[contains(#class,'red') and contains(text(), 'Continue')]")).click();
Here is the part of the html I am trying to access:
<button style="padding-left: 0px;" type=button" "id=submitButton" class = "nbutton" title = "Continue" onclick=_hblicnk('continue,'continue'); goFeaturePage('true');">
<span style = "padding-right: 12px;" class="red"
"Continue"
<img class="caret_rebrand">
</span>
I expect the continue button to be found and clicked. attached is the picture of the webpage
UPDATE: 8-3-19: I've tested the following pieces of code and it is able to find the element in all cases. But when adding the .click() function to any one of them, it causes a no such element exception.
driver.findElement(By.name("submitButton")).click();
driver.findElement(By.id("submitButton")).click();
driver.findElement(By.cssSelector("#submitButton")).click();
driver.findElement(By.xpath("//*[#id=\"submitButton\"]")).click();
My expectation is that you need to click the <button> element as this <span> might be not clickable at all. You can use i.e. title attribute to uniquely identify the element on the page
It's better to use Explicit Wait to ensure that the button is present and clickable as it might be the case it's not available in DOM right away. Check out How to use Selenium to test web applications using AJAX technology article for more details
Assuming all above I believe you should be able to use below code for clicking the button:
continue_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//button[#title='Continue']")))
continue_button.click()

Selenium Web driver - Button is getting clicked but the next processing is not happening

My HTML code for a NEXT button which I am trying to click is:
<input type="submit" name="ctl00$ctl00$MainContent$ChildContent1$btnStep2_Submit" value="Next" onclick="waitBtn(event,'df_step2');
OverlayProgressPanel_NoSub('ctl00_ctl00_MainContent_ChildContent1_fsLoanData','ctl00_ctl00_upProgress');
" id="ctl00_ctl00_MainContent_ChildContent1_btnStep2_Submit" class="btn" onmouseover="hov(this,'btn btnhov');" onmouseout="hov(this,'btn')" />
Am using the below code to click that next button:
xpath = ".//*[#id='ctl00_ctl00_MainContent_ChildContent1_btnStep2_Submit' and #type='submit']"; // Next Button
Function_Classes.field_click(driver,xpath); // Click on Next button
driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
But,it looks like the button is getting clicked but not going to the next page where there is one more NEXT button
I am getting below exception :
Unable to locate element: {"method":"xpath","selector":".//*[#id='ctl00_ctl00_MainContent_ChildContent1_btnStep3_Submit' and #type='submit']"}
ctl00_ctl00_MainContent_ChildContent1_btnStep3_Submit = this is the button on the next page and since I am not getting the next page on clicking the first NEXT button ,I would think that might be the reason..
Can you please help me here?
IDs by HTML standards should be unique on the page so you shouldn't need to specify anything other than the ID in the locator. That will simplify your locators. So, in this case you can use By.id().
You've added an implicit wait in the middle of your script. That leads me to believe that you don't understand how implicit waits work. An implicit wait is set once for the driver instance and lasts the life of the driver. Generally you would put this statement near the top of your script. I would advise against using implicit waits and instead prefer explicit waits (WebDriverWait). I've rewritten the code. I think the below should work.
By next2Locator = By.id("ctl00_ctl00_MainContent_ChildContent1_btnStep2_Submit");
By next3Locator = By.id("ctl00_ctl00_MainContent_ChildContent1_btnStep3_Submit");
driver.findElement(next2Locator).click();
new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(next3Locator)).click();
Suggestion: Don't overcomplicate your code by adding wrapper functions around .click(), etc. There's really no need for it. It makes your code harder to read and introduces unnecessary complexity. Keep it as simple as you can.
There is a problem inside your html, Because Threre are few functions are available inside your html, and you didn't call all functions properly. so your button click event was not fire. functions name like this waitBtn, hov.
See image for more details.

angular typeahead/autocomplete for contenteditable

Basically, what my client asked me to do is similar to tag friends in Facebook/youtube comment.
must start with #
a popup suggesting a list, upon selected, the value is appended back to the original contenteditable
I have tried
https://angular-ui.github.io/bootstrap/
and ngTagsInput , they are close but not enough... thanks
I bet this is what you are looking for http://angular-ui.github.io/ui-mention/example/ . I have to admit it took me quite a few days to find it (via google)
Good luck
You're building autocomplete for tags. If you plan to reuse it, then you'll need to write a custom directive. If not, then you can do a messy implementation inside of your controller.
You'll need the html element you are editing to look like this:
<div ng-model="newtag" ng-change="tagchanged()" ng-bind="newtag"></div>
ng-change will fire on change, so your function will need to have a debounce (wait a period of time) in order to wait until the user finishes typing. You can accomplish this with a setTimeout of 500ms. If it changes during that time period, kill the timeout. But if it doesnt, do your api call to get the list of potential tags and show them in a list below the field. You'll want the css for the results to let them align to the search field and hover above the rest of your page.

Resources