0

EDIT: Not sure if it really helps to figure it out, but this is Sharepoint based.

I have an element with special character which the Webdriver can't locate.

var element = wait.Until(x => x.FindElement(By.Id("Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte")));
element.SendKeys("foo");

I guess it is the $ that causes the problem.

On the contrary , I found it by using :

var element = wait.Until(x => x.FindElements(By.CssSelector("div[id*='Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592']")));
element[2].FindElement(By.TagName("p")).SendKeys("foo");

The test passes that way(seemingly), but the value isn't really being sent to the field. Unfortunately, there is no input tag on the element's hierarchy, and when inserting the text manually , I can then see that the value was inserted to the <p> tag. But , as shown, when using the <p> tag , it doesn't really help.

The HTML:

<div class="ms-rtestate-write ms-rteflags-0 ms-rtestate-field" id="Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte" role="textbox" aria-haspopup="true" aria-labelledby="Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte_label" style="min-height: 84px;" contenteditable="true" aria-autocomplete="both" aria-multiline="true" RteDirty="true">
  <p>
    <span id="ms-rterangecursor-start" RteNodeId="1"></span>
    <span id="ms-rterangecursor-end"></span>
  ​</p>
</div>
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
JumpIntoTheWater
  • 1,306
  • 2
  • 19
  • 46

3 Answers3

1

Instead of implementing two FindElement* you can do it in single step as follows:

  • CssSelector:

    wait.Until(x => x.FindElement(By.CssSelector("div.ms-rtestate-write.ms-rteflags-0.ms-rtestate-field[id^='Tasrit_'][aria-labelledby$='_inplacerte_label']>p"))).SendKeys("foo");
    
  • XPath:

    wait.Until(x => x.FindElement(By.XPath("//div[@class='ms-rtestate-write ms-rteflags-0 ms-rtestate-field' and starts-with(@id,'Tasrit_')][contains(@aria-labelledby,'_inplacerte_label')]/p"))).SendKeys("foo");
    

Update

However the element looks dynamic to me so you need to induce WebDriverwait for the desired element to be clickable and you can use either of the following solutions:

  • CssSelector:

    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("div.ms-rtestate-write.ms-rteflags-0.ms-rtestate-field[id^='Tasrit_'][aria-labelledby$='_inplacerte_label']>p"))).SendKeys("foo");
    
  • XPath:

    new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//div[@class='ms-rtestate-write ms-rteflags-0 ms-rtestate-field' and starts-with(@id,'Tasrit_')][contains(@aria-labelledby,'_inplacerte_label')]/p"))).SendKeys("foo");
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • nice one, but the result is still the same. The test passes, but value wasn't really sent to the field. – JumpIntoTheWater Dec 06 '18 at 11:03
  • @YanivEliav Checkout my answer update and let me know the status – undetected Selenium Dec 06 '18 at 11:07
  • on it . let you know soon – JumpIntoTheWater Dec 06 '18 at 11:08
  • for some reason, the text("foo") was sent to a different field and not the one I'm pointing to.. maybe because they have the same class(?) – JumpIntoTheWater Dec 06 '18 at 11:14
  • There are 3 elements have the same class and contains the same part of id you mentioned: `TextField_inplacerte` – JumpIntoTheWater Dec 06 '18 at 11:17
  • @YanivEliav Checkout my answer update and let me know the status – undetected Selenium Dec 06 '18 at 11:22
  • thanks for the efforts, unfortuately the result is still the same..very strange behavior – JumpIntoTheWater Dec 06 '18 at 13:14
  • @YanivEliav Your comments are not helping me either. Sorry, the answer didn't help you to solve your problem but how am I going to improve my post with that feedback? Where are you seeing the error now? Does the line of code identifies the element at all? Or the identification is fine but `SendKeys()` is non-functional? Please update the main question with your detailed observation. – undetected Selenium Dec 06 '18 at 13:18
  • the identification is ok. it was ok from the very first begining. I would update my original post but nothing really changed. So, the identification is good, but the `SendKeys()` isn't really sedning any data. and if it does, for some reason it sends data for a whole different object which has a different identifiers. – JumpIntoTheWater Dec 06 '18 at 13:22
  • For some reason I wasn’t able to see this post until you marked another post of mine (with link to this one) as duplicate. Thanks – JumpIntoTheWater Dec 09 '18 at 18:47
0

And I guess there is extra space in that element's id :) Try this:

wait.Until(x => x.FindElement(By.Id("Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_$TextField_inplacerte")));
element.Click();

Either that or the Id value of that element in the DOM is different, $TextField_inplacerte being a variable that parses to eg. spaceMonkey, undefined, 5 etc. Open up the dev tools, find the element, right-click, inspect and confirm the actual Id of the element in the DOM.

You can use dev tools API to search for text in DOM of the currently opened page (with that element in it) if it matches the Id matches if not there is a difference in it. It could be any part eg. 6th character in Id being different :)

Just to make sure that space between 1st part of id and 24 you mention is the problem you can either:

  1. look at webdriver's code and see internally what is used to access DOM elements

  2. load jquery before testing this out:

    var element = wait.Until(x => x.FindElements($('#id containing spaces')).SendKeys("foo");

Basically, instead of using webdriver way to find element, you use jQuery to obtain the element reference. If that works it's the space problem due to bad design of the application having space in element's id

Possibly that is why CSS selector route worked.

DanteTheSmith
  • 2,937
  • 1
  • 16
  • 31
  • when using dev tools API the id now is `#Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_\24 TextField_inplacerte` – JumpIntoTheWater Dec 06 '18 at 11:09
  • So put in exactly that instead of what you putting in. wait.Until(x => x.FindElement(By.Id("Tasrit_6aecdca9-e3b9-4141-ae36-d537784f9592_\24 TextField_inplacerte"))); if it is always the same. – DanteTheSmith Dec 06 '18 at 11:13
  • did you notice there is a space between the `24` and `TextField`? I should use it exactly the same? – JumpIntoTheWater Dec 06 '18 at 11:15
  • nice notice. Here is info about it: https://stackoverflow.com/questions/6802765/jquery-dealing-with-a-space-in-the-id-attribute So it depends on how the element is selected internally in webdriver library. Bottom line here is technically space is not allowed in DOM element's id and should be avoided. I would consider this a bad design of the app / library / whoever gives that id to that element – DanteTheSmith Dec 06 '18 at 12:23
0

If SendKeys() doesn't work you can try using JavaScript

IWebElement webElement = element[2].FindElement(By.TagName("p"));
driver.ExecuteJavaScript("arguments[0].setAttribute('value', 'arguments[1]')", webElement, "foo");
Guy
  • 46,488
  • 10
  • 44
  • 88