Firefox C# Selenium Невозможно установить значение с помощью sendKeys, и JavaExecutor, похоже, не влияет на него - PullRequest
0 голосов
/ 05 августа 2020

Привет всем,

Здесь для меня немного головоломка, я уже давно пытался решить эту проблему, но, похоже, я просто застрял. Я пытаюсь написать стратегию автоматизации для торговой платформы (в данном случае Trading212) и пытаюсь использовать для этого C# с Selenium.

Все шло хорошо, пока я не добрался до оверлея, который занимается размещением заказа. Как и обычно, я пробовал sendKeys, но все попытки дали плохой ответ:

Errors

-Error ElementNotInteractableException (Невозможно прокрутить до просмотра) -Error ElementNotInteractableException (элемент недоступен с клавиатуры) - js .ExecuteScript ("arguments [0] .value = '12345';", TargetPriceInput); (Изменяет значение, но не значение)

Бит, который я пытаюсь настроить, - это цена, которую, по-видимому, нельзя изменить никаким способом, который я могу найти, и было достаточно сложно выбрать, поскольку он имеет динамическое изменение идентификатора, ни один класс, на котором можно было бы держаться, смог получить его только путем поиска ввода с помощью «Текст».

Элемент, который я пытаюсь обновить:

    <div class="spinner _focusable" tabindex="-1" data-dojo-attach-event="onkeydown: onKeyDown" id="uniqName_0_131" widgetid="uniqName_0_131">
        <span class="spinner-placeholder" data-dojo-attach-point="placeholderNode">Price</span>
        <input type="text" autocomplete="off" id="uniqName_0_132" widgetid="uniqName_0_132">
        <div class="spinner-arrow-container">
            <div class="spinner-arrow spinner-down svg-icon-holder" data-dojo-attach-point="spnLeftNode"><svg class="svg-icon dropdown-arrow-down-icon" width="32" height="32" viewBox="0 0 32 32">
        <g fill="none" fill-rule="evenodd">
            <polyline stroke="#6F6F7F" points="20.5 14.5 16 19 11.5 14.5" stroke-linecap="round"></polyline>
        </g>
    </svg>
    </div>
            <div class="spinner-arrow spinner-up svg-icon-holder" data-dojo-attach-point="spnRightNode"><svg class="svg-icon dropdown-arrow-up-icon" width="32" height="32" viewBox="0 0 32 32">
      <g fill="none" fill-rule="evenodd">
        <polyline stroke="#6F6F7F" points="20.5 18.5 16 14 11.5 18.5" stroke-linecap="round"></polyline>
      </g>
    </svg></div>
        </div>
        <div class="spinner-disabled-click-catcher" data-dojo-attach-point="clickCatcherNode"></div>
    </div>

Похоже, что это связан с Javascript для обновления, когда нажата клавиша и поле выбрано, но я не могу получить селен для выбора поля или данные pu sh в нем. Есть события, связанные с полем ввода, но, похоже, не удается найти способ сделать это go.

                    TargetPrice.Click();
                    TargetPrice.SendKeys("05485.00000");

Оба просто выдают ошибки и отказываются выполнять работу. оригинальный вид панели

Firefox Инспектор также показывает мне, что значение элемента действительно является строковым значением: «1.31407», которое скрыто, но я определенно смог обновить с помощью ExecuteScript, но не проверяет его. Я вижу, что значение обновляется, но когда я нажимаю где-нибудь еще, оно просто сбрасывается.

Если заглянуть в него дальше, кажется, что есть несколько скриптов, JavaScript которые вручную оценивают, какие кнопки я нажимаю, и разрешают их. Не знаю, как это обойти.

Событие OnKeyDown

function, o = i.checkIntegerPartLength, s = i.onKeyPressed, l = this.state, d = l.currentValue, u = l.maxInputLength, h = this.getPrecision(), f = !1;
for (var p in r.default)
  if (void 0 === v[p] && r.default[p] === t.keyCode) {
    f = !0;
    break
  }(t.altKey || 18 === t.keyCode) && (t.stopPropagation(), t.preventDefault());
var g = String.fromCharCode(t.keyCode);
!f && isNaN(parseInt(g, 10)) && 190 != t.keyCode && 110 != t.keyCode && 109 != t.keyCode && 189 != t.keyCode && (t.stopPropagation(), t.preventDefault()), 190 != t.keyCode && 110 != t.keyCode || 0 != h && -1 === this.domNode.value.indexOf(".") || (t.stopPropagation(), t.preventDefault()), 189 != t.keyCode && 109 != t.keyCode || (this.onMinusPress(), t.stopPropagation(), t.preventDefault()), t.shiftKey && !isNaN(parseInt(g, 10)) && (t.stopPropagation(), t.preventDefault());
var m = (g = t.keyCode || t.charCode) == r.default.HOME || g == r.default.END || g == r.default.DELETE || g == r.default.BACKSPACE || g >= 37 && g <= 40;
if (!m && !o && c.default.getLength(this.domNode.value.replace(/\s/g, "")) >= u + h && this.domNode.selectionStart == this.domNode.selectionEnd && t.preventDefault(), !(a || t.keyCode !== r.default.NUMPAD_0 && f)) {
  var C = this.domNode.value.split("."),
    y = n(C, 1)[0],
    b = 48 == t.keyCode || 96 == t.keyCode,
    w = this._getTextSelection(this.domNode),
    T = w.start,
    L = w.length,
    _ = this.domNode.value.length === L;
  0 === T && "." !== this.domNode.value.charAt(L) && !_ && y.length && b && t.preventDefault()
}
if (o && !m && 190 !== t.keyCode && 110 !== t.keyCode) {
  var N = this.domNode.value.split("."),
    S = n(N, 2),
    E = S[0],
    I = S[1],
    x = this.domNode.value.indexOf("."),
    M = this._getTextSelection(this.domNode),
    O = M.start,
    P = M.length,
    A = E.substr(O, P),
    D = A && (A.length > 1 || 160 !== A.charCodeAt(0));
  E.replace(/\s/g, "").length >= u && !D && (!I && -1 === x || O <= x) && t.preventDefault()
}
"0" != d || h || m || 48 != t.keyCode && 96 != t.keyCode || t.preventDefault(), 65 == g && t.ctrlKey && this.domNode.select(), setTimeout((function() {
  e._destroyed || (s(), e.updateState(e.domNode.value, {
    isUserTyping: !0,
    keepCursorPosition: !0
  }))
}), 5)
}, onFocusEvent: function() {
    var t = this.props,
      e = t.o

Рад предоставить столько деталей, сколько необходимо. Страница, с которой я имею дело, - это демонстрационная веб-страница для trading212, которая является общедоступной, если вы случайно знаете, как ее сделать go.

Уже пробовали делать виртуальные нажатия клавиш, используя отдельную библиотеку, но даже windows based, похоже, не воспринимается странно.

РЕДАКТИРОВАТЬ: после долгого пристального изучения и некоторого приличного повторного тестирования с использованием системы XPath, рекомендованной в ответе ниже, мне удалось выяснить, что причина, по которой все это не имело смысла если, потому что, несмотря на все мои усилия, элемент, который пытались изменить, был НЕ правильным, а похожим.

Чтобы разрешить, даже если временно я вошел в firefox осмотрел, выбрал целевое поле ввода и щелкнул правой кнопкой мыши, затем я щелкнул копировать -> XPath.

Это дало мне прямой путь к правильному XPath. IWebElement XPathInput = driver.FindElement(By.XPath("/html/body/div[7]/div[2]/div[3]/div[2]/div[1]/div[3]/div/div[2]/div/input"));

1 Ответ

0 голосов
/ 05 августа 2020

EDIT: вы должны попробовать XPATH следующим образом:

IWebElement XPathSpan = driver.FindElement(By.XPath("descendant::span[@class='spinner-placeholder' and text()='Price']")); //verify it found the span
IWebElement XPathInput = driver.FindElement(By.XPath("following-sibling::input")); //this should be your input

XPATH, который у вас есть, в порядке, но если dom изменится так, что в иерархии появится дополнительный div, он сломает тот, который у вас есть. Ключевыми частями здесь является то, что потомок говорит ему проходить через детей, внуков и так далее. Поскольку вы используете driver.FindElement (), он будет начинаться с root документа. Вторую строку мы начинаем с диапазона и говорим ему найти первого брата, имеющего тип input, который должен быть тем, который вы ищете.

Ну, сначала я бы попытался найти его с помощью XPATH: "Потомок :: span [text () = 'PRICE'] / follow-sibling :: input"

Мне это кажется более надежным, если они добавят еще один ввод или что-то в этом роде.

Учитывая, что его родительский элемент имеет класс spinner _focusable и некоторые javascript для onkeydown, я предполагаю, что вы сначала найдете этот элемент и начнете с ним взаимодействовать, а затем сможете взаимодействовать с ценовым.

Итак, ваши шаги будут следующими:

  1. найти ввод с помощью XPATH выше
  2. найти родительский ввод, такой как var inputParent = input.FindElement (By.XPath ("parent :: div ")) // предполагаем, что ввод - это имя переменной из шага 1
  3. inputParent.Click ();
  4. Thread.Sleep (500); // что-то подобное, чтобы дождаться javascript, вы также можете использовать webdriverwait
  5. input.SendKeys (...);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...