Selenium: ввод текста в поле, у которого нет входного тега - как найти, какой это? - PullRequest
0 голосов
/ 09 января 2019

Мне нужно ввести текст в поле таблицы, в которой нет тега ввода. Этот XPath указывает на поле уникально

//div[@id="contentBody"]//div[@row="0"]/div[contains(@class, "l4") and contains(@class, "r4")]

(можно добавить трейлинг /div к этому XPath, без разницы)

Я могу использовать этот XPath для чтения этого поля, но когда я пытаюсь вставить текст в это поле, я получаю сообщение об ошибке:

InvalidElementStateException: Message: invalid element state: Element must be user-editable in order to clear it.

Это HTML для ячейки

<div class="slick-cell l4 r4  alignRight uppercase highint editable-cell active selected" aria-describedby="inforDataGrid731693C5" tabindex="-1" role="gridcell">
    <div class="edit-cell">2,0</div></div>

Я нашел этот вопрос (который, кстати, кажется, ошибочно помечен как дубликат)

Элемент должен редактироваться пользователем, чтобы очистить его исключение в селене

Кажется, что комментарии имеют смысл для моей ситуации: мой XPath указывает на div, а не на поле ввода (но, как вы можете видеть, класс div - это "edit-cell", так что ...) но я не Я думаю, у меня есть возможность указать поле ввода. Как мне обойти это - как найти целевой элемент, чтобы я мог успешно установить его текст, без исключения?

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Вывод, к которому вы пришли, является исправленным: вы не можете отправить ввод в тег <div>, это не так, как обычно работают браузеры (исключение из правила дано в " edit 2 * 1004" * ") . Исключение кода ясно говорит об этом - «Элемент должен быть редактируемым пользователем, чтобы очистить его». Независимо от того, что у div есть классовое значение «edit-cell» - это просто имя, выбранное разработчиком, для иллюстративного предложения; это не означает, что div сможет принимать данные.

Скорее всего, пользовательский интерфейс, используемый приложением, использует <div> для стилизованного представления значений, установленных пользователем; есть скрытый элемент <input>, который принимает фактические записи клавиатуры, и код JavaScript обновляет <div> вместе с ними.
Вам нужно найти этот входной тег и настроить его для своих изменений.

edit1: поиск входных тегов по их значениям с помощью JS.

Вот как найти входной тег - в браузере (вручную) установите значение для строки, которая будет уникальной для страницы, например, «myMegaSpecialString». Затем запустите следующую консоль js:

[...document.getElementsByTagName("input")].forEach(function(el){ if (el.value == "myMegaSpecialString"){console.log(el);} })

Будет напечатано <input> элементов, которые имеют это "специальное" значение.

edit2: поиск любых тегов по их значениям с помощью JS.

Согласно обсуждению в комментариях, элемент <input> не был найден с таким значением. Как я справедливо исправил @Andersson, при особых обстоятельствах другие элементы, кроме input, могут получать, khm, input - они должны иметь атрибут contenteditable, и он наследуется от родительских элементов - например, если установлен тег <body>, вы можете ввести любой элемент на странице.

Итак - модифицированная версия javascript для определения «кто держит наше значение»; к счастью, getElementsByTagName() поддерживает подстановочный знак для аргумента - это будет соответствовать любому элементу:

[...document.getElementsByTagName("*")].forEach(function(el){ if (el.value == "myMegaSpecialString"){console.log(el);} })

Это может быть немного медленнее - но должен напечатать элемент (ы) со свойством value, равным "myMegaSpecialString".

edit3: поиск любых тегов по текстовому содержимому с помощью JS.

Квест продолжается - текст, который вы вводите, не появляется ни в одном элементе value свойства? Нет проблем, давайте посмотрим на это в элементах текстового содержания.
Это может быть в том случае, если вы на самом деле редактируете содержимое <span>, <div> или подобных тегов (скрещенные пальцы ...:)) .

Это вариант предыдущей версии - вручную установите для текста значение, уникальное для всей страницы (чтобы ограничить вывод), и запустите его в консоли:

[...document.getElementsByTagName("*")].forEach(function(el){ if (el.textContent.indexOf("myMegaSpecialString") !== -1){console.log(el);} })

, который будет (должен? Может? Я больше ни в чем не уверен: D) вывести в консоль все элементы DOM, которые имеют эту строку как часть своего текста.

Разбивка, что есть в javascript, для будущих изменений:

  • document.getElementsByTagName("*")] возвращает все элементы с таким именем тега в виде массива; звездочка аргумента (*) - любое имя тега.
  • forEach - цикл над элементами коллекции, передавая каждый из них анонимной функции в ней.
  • el.textContent - возвращает текстовое содержимое узла (и его дочерних узлов).
  • indexOf() - возвращает позицию аргумента в строке, -1, если он не присутствует (используется indexOf() против contains() для совместимости, позднее в ES6).
  • если условие возвращает true, console.log(el) напечатает его в консоли.
0 голосов
/ 09 января 2019

Это сообщение об ошибке ...

InvalidElementStateException: Message: invalid element state: Element must be user-editable in order to clear it.

... подразумевает, что WebElement находится в состоянии, в котором над ним нельзя выполнить действия. В качестве примера можно привести элемент, скрываемый другим при нажатии или, возможно, не видимый в DOM.

Решение

Поскольку элемент является элементом JavaScript , вам нужно заставить WebDriverWait быть элементом , чтобы можно было нажимать , и вы можете использовать любое из следующих решений:

  • Wait Until Element Is Visible

    Wait Until Element Is Visible    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']    20  seconds
    Set Focus To Element    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']
    # invoke click
    
  • Wait Until Element Is Enabled

    Wait Until Element Is Enabled    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']    20  seconds
    Set Focus To Element    xpath=//div[contains(@class, 'slick-cell') and starts-with(@aria-describedby,'inforDataGrid')]/div[@class='edit-cell']
    # invoke click
    
...