1

i have this piece of html, which is under a dropdown, and which appears after selecting somthing in the dropdown element:

<div class="mx-0 w-100 row">
    <textarea id="notes" placeholder="Write here..." required="" class="form-control"> </textarea>
</div>

I want to use Selenium to click on it, write something and exit from the textarea. And actually I did it, but results vary depending on which selector I use, and I don't know why:

Here's my code actually working: I use wait for element visible and enabled because the above dropdown, when opened, covers the textarea. If I don't use them it gives a "not interactable" error.

const notes = await driver.wait(until.elementsLocated(By.css('textarea')), delay)
await driver.wait(until.elementIsVisible(notes[0]), delay)
await driver.wait(until.elementIsEnabled(notes[0]), delay)
await notes[0].sendKeys('Something to write')
// this TAB is for exiting from textarea, which let a button to appear
await notes[0].sendKeys(Key.TAB)

Now, if instead of the first line I use

const notes = await driver.wait(until.elementLocated(By.id('notes')), delay)

or

const notes = await driver.wait(until.elementLocated(By.xpath('//*[@id="notes"]')), delay)

and replacing obviously notes[0] with notes,it gives me

ElementNotInteractableError: element not interactable

The question is: Why does this happens? I do not like so much selecting an array element with numbers, but actually I am forced to and I don't get why the other selectors aren't working.

Don Diego
  • 912
  • 1
  • 11
  • 29

1 Answers1

1

This line of code...

const notes = await driver.wait(until.elementsLocated(By.css('textarea')), delay)

...works as notes is a list of all the elements identified as By.css('textarea') inducing a certain delay for elementsLocated() and fortunately the the first matching element i.e. notes[0] is your desired element and you are through.

Definitely, the first matched element using either By.id('notes')or By.xpath('//*[@id="notes"]') isn't your desired element.


Solution

The best solution would be to make the Locator Strategies more finer as follows:

  • css:

    const notes = await driver.wait(until.elementLocated(By.css("textarea.form-control#notes")), delay)
    
  • xpath:

    const notes = await driver.wait(until.elementLocated(By.xpath("//textarea[@class='form-control' and @id='notes']")), delay)
    
DebanjanB
  • 118,661
  • 30
  • 168
  • 217
  • Wow, thanks so much, I am new to selenium (I started a week ago) and I totally didn't figure out this. Still, is not very clear why the first matched element using `By.id('notes')` doesn't return me the correct element, I mean, it's an ID, it should be unique! – Don Diego Jan 04 '21 at 09:33
  • 1
    @Diego There are other elements present on top the desired element with `id` attribute as `notes` and is invisible and hence not your desired element. – DebanjanB Jan 04 '21 at 11:02