user8465989
user8465989

Reputation:

*Problems finding specific element on page

I know there are existing questions on this topic, but none of them seems to help me with this:

I've got a lightbox with several elements. I can find and access all of these elements, except ONE, using the XPath.

These are the items:
Text header: No problem
Text: No problem
Input field: No problem
Text: No problem
Text: No problem
Button (upload file): THIS IS SEEMINGLY IMPOSSIBLE FOR Selenium TO FIND
Button (cancel): No problem
Button (send): No problem

The XPaths for all the elements:

.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[1]    /content-placeholder/h1
.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/ul[1]/li[1]/label/span
.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/ul[1]/li[1]/div/div/input
.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/label
.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/span
.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input
.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[5]/content-placeholder/button[1]
.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[5]/content-placeholder/button[2]

The problematic element is this:

.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input

As far as I can see, there's no reason why it should be different from the other elements (textfield, button, text)?

I'm accessing all these elements with an implicit wait, to check that they've all loaded before continuing.

GCDriver.WaitForVisible("//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input");

From the GCDriver (Selenium Driver) class:

public static void WaitForVisible (string xpath) {
        var wait = new WebDriverWait(GCDriver.Instance,  
                   TimeSpan.FromSeconds(10));
        wait.Until(driver => 
        driver.FindElement(By.XPath(xpath)).Displayed);
}

Now, as mentioned, this works for all the other elements, as well as accessing them directly. For this, the wait times out with WebDriverTimeoutEsception:

Result Message: 
Test method Tests.Regression_tests.VerifyOverlays.Verify_Update_Ticket_OverlayContent threw exception: 
OpenQA.Selenium.WebDriverTimeoutException: Timed out after 10 seconds

Also, of course, trying to ACCESS the button with .Click() also fails:

GCDriver.Instance.FindElement(By.XPath(".//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input")).Click();

Result Message: 
Test method Tests.Regression_tests.VerifyOverlays.Verify_Update_Ticket_OverlayContent threw exception: 
System.InvalidOperationException: unknown error: Element is not clickable at point (-208, 307)

Here's the html code for the element:

<a class="btn btn-grey file-input-container btn-small" data-bind="enable: !uploading() "
   style="margin-top: 10px; padding: 7px 12px; "data-tooltipped=""
   aria-describedby="tippy-tooltip-32" 
   data-original-title="Add Attachment">
   <i class="fa fa-cloud-upload"/>
   <span class="mq-for-small-hide">
      <span localize-me="">Add Attachment</span>
   </span>
   <input data-bind="upload: addAttachments, 
    enable: !uploading()" type="file"/>
</a>

I've tried some other ways of getting the element, but since this is quite (imo) "messy" html, with no unique ID's or good class names, I've been unable to figure out how.

And it REALLY bugs me that I cannot find it by the XPath. There are 8 elements on the page, all visible and accessible, but this ONE element is impossible to find with Selenium.

The element is there; I can manually click the button on the page while Selenium runs it.

UPDATE: I also tried using .Enabled instead of .Displayed. Same result.

UPDATE 2: There are two answers below, and I have to select one as the "winner".

Shubham Jain gives an answer that, while not the exact thing I was trying to to, is a very good work-around. By using JavaScriptExecutor to try clicking the button, it also checks if the button is visible. However, the answer given doesn't do what it tries to do; Clicking doesn't work quite that way. See Solution below to see the correct/working code to click a button using JavaScriptExectutor.

smit9234's answer is exactly what I'm trying to do, although clicking doesn't work that way. To click the button, JS is necessary in this case. However, the question was how to check .Displayed, and that works with the modified XPath he gave me from the code excerpt.

Solution

The XPath of the element (button) is, according to FirePath:

.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/input

This, however, doesn't work. Selenium simply cannot find it, even though it's clearly there.

THIS XPath, however, does work:

.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/span/span

However, it works with reagards to the .Displayed check. It does NOT work with Click(). To be able to click the button, I began with Shubham Jain's code example and created this method in the Driver class, to be able to use JavaScript (with Selenium's JavaScriptExecutor) to click the button:

 using OpenQA.Selenium.Interactions;

 public static void JSClick (string xpath) {
        IWebElement icon = Instance.FindElement(By.XPath(xpath));
        Actions ob = new Actions(Instance);
        ob.Click(icon);
        IAction action = ob.Build();
        action.Perform();
    }

Upvotes: 1

Views: 782

Answers (4)

smit9234
smit9234

Reputation: 361

Looking at the html snippet you posted, it seems like this is a file attachment function. Based on the html structure of the snippet, try using the following xpath:

.//*[@id='overlays']/overlay--master/div/div/overlay-lightbox/div/div[3]/content-placeholder/a/span/span

You should then be able to use the click(); method to click the "Add Attachments"

I assume that clicking on the input doesn't do anything, however you should be able to use the sendKeys(); method for sending the "file path" to the input element.

Upvotes: 1

chris-crush-code
chris-crush-code

Reputation: 1149

It seems like it's not clickable. It looks like there's some javascript on the page with a function called "uploading()".

since you're button has this on it

  enable: !uploading()

just a test to verify if this is actually the cause, put a breakpoint before your click. on the browser dev tools stick a breakpoint in the uploading() function on the javascript file and see what it's returning.

If this is the case you'll have to use the javascript executor to bypass this.

Upvotes: 0

Shubham Jain
Shubham Jain

Reputation: 17593

Use below XPath :-

//input[@type='file' and contains(@data-bind,'upload: addAttachments')]

You can use javascriptexecutorof selenium to click on button. It operated directly on JS of page.

In java :-

WebElement element = driver.findElement(By.id("gbqfd"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);

I don't know more about c# but I believe it something like

IWebElement clicks = driver.FindElement(By.Id("gbqfq"));
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("arguments[0].click();", clicks);

Change the locator in above elements as per your convenience.

Below you will find more details of javascriptexecutor

https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/JavascriptExecutor.html

Hope it will help you :)

Upvotes: 1

Murthi
Murthi

Reputation: 5347

May be input element is not visible on the page. you may not use displayed function for that element and try with enabled as given below.

public static void WaitForEnabled (string xpath) {
        var wait = new WebDriverWait(GCDriver.Instance,  
                   TimeSpan.FromSeconds(10));
        wait.Until(driver => 
        driver.FindElement(By.XPath(xpath)).Enabled);
}

if the above is not working, you try to click on anchor tag instead of input.

Upvotes: 0

Related Questions