Проблемы с Selenium WebDriver executeScript (с использованием watir-webdriver в Ruby)

У меня проблемы с выполнением определенного фрагмента кода JavaScript с помощью команды browser.execute_script Watir WebDriver:

Вот этот Javascript:

  var bodyFrame = document.getElementsByName("BodyFrame")[0];
  var bodyFrameDoc = bodyFrame.contentDocument || bodyFrame.contentWindow.document;
  var mainFrame = bodyFrameDoc.getElementById("MainFrame");
  var mainFrameDoc = mainFrame.contentDocument || mainFrame.contentWindow.document;
  var row = mainFrameDoc.getElementById("DETAIL_1");
  var rowNodes = row.childNodes;
  var index;
  for (index = 0; index < rowNodes.length; index++) {

        if (rowNodes[index].firstChild.id === 'ID1') {
            rowNodes[index].firstChild.value = 'ACCRUL';
        }


        if (rowNodes[index].firstChild.id === 'ID2') {
            rowNodes[index].firstChild.value = 'OP';
        }


        if (rowNodes[index].firstChild.id === 'ID3') {
            rowNodes[index].firstChild.value = 'Z';
        }


        if (rowNodes[index].firstChild.id === 'ID4') {
            rowNodes[index].firstChild.value = 'FIRST';
        }


        if (rowNodes[index].firstChild.id === 'ID5') {
            rowNodes[index].firstChild.value = 'AUT';
        }


        if (rowNodes[index].firstChild.id === 'ID6') {
            rowNodes[index].firstChild.value = 'AU1000';
        }


        if (rowNodes[index].firstChild.id === 'ID7') {
            rowNodes[index].firstChild.value = 'm tax m entity m jc';
        }


        if (rowNodes[index].firstChild.id === 'ID8') {
            rowNodes[index].firstChild.value = 'MR5001100';
        }


        if (rowNodes[index].firstChild.id === 'ID9') {
            rowNodes[index].firstChild.value = 'T';
        }


        if (rowNodes[index].firstChild.id === 'ID10') {
            rowNodes[index].firstChild.value = '453.36';
        }

  }

Почему я должен использовать такое злодеяние? Ну, потому что продукт, для которого я разрабатываю тесты, настолько плох. В каждой ячейке используется один и тот же атрибут id, поэтому я не могу напрямую зонировать объект в документе. Что еще хуже, документ в два кадра. Frameception.

Использование очевидного решения (с использованием API watir-webdriver) неосуществимо, поскольку задача заполнения 32 строк сетки занимает половину!! часа.

Я могу заставить Javascript выше работать в инструментах разработчика браузера. (В этом режиме поддерживаются только браузеры IE8, 9 в режиме совместимости.) У меня нет доступа к jQuery или какой-либо необычной библиотеке javascript. Использование этого javascript заполняет строки практически мгновенно.

Когда я запускаю это с помощью команды browser.execute_script, я получаю

  Selenium::WebDriver::Error::JavascriptError: JavaScript error

Как ни странно, если бы я просто использовал

  return document.getElementsByName("BodyFrame")[0];

Затем я получаю сообщение об ошибке с библиотекой Net::HTTP, которая используется Selenium где-то в стеке для отправки команд назад и вперед в браузер. (Более конкретно: ERRNO::ERRCONNREFUSED)

Помогите?

РЕДАКТИРОВАТЬ: Вот прямой сценарий, который я использую для выполнения кода (и генерировать небольшой кусочек Javascript):

    def quick_fill(data = {})
      reference_element.focus;
      quick_filler = ->(element_id, value) {
        "if (rowNodes[index].firstChild.id === '#{element_id}') {
           rowNodes[index].firstChild.value = '#{value}';
         }"
      }
      row_id = row.attribute(:id)
      element_ids = Hash[data.keys.map { |key| [key, send("#{key}_element").attribute(:id)] }]
      javascript = <<-JAVASCRIPT
      var bodyFrame = document.getElementsByName("BodyFrame")[0];
      var bodyFrameDoc = bodyFrame.contentDocument || bodyFrame.contentWindow.document;
      var mainFrame = bodyFrameDoc.getElementById("MainFrame");
      var mainFrameDoc = mainFrame.contentDocument || mainFrame.contentWindow.document;
      var row = mainFrameDoc.getElementById("DETAIL_1");
      var rowNodes = row.childNodes;
      var index;
      for (index = 0; index < rowNodes.length; index += 1) {
        #{element_ids.map { |method, element_id| quick_filler.call(element_id, data[method]) }.join("\n") }
      }
      JAVASCRIPT
      puts javascript
      sleep(0.500)
      browser.execute_script(javascript)
    end

Аргументом данных этого метода является хэш пар ключ-значение, где ключи - это имена методов, предоставляемых методам доступа к объектам страницы, а значения - это значения, которые я пытаюсь заполнить. Как часть промежуточного процесса Я получаю элемент id из элемента объекта страницы (который предоставляется в качестве идентификатора каждого элемента).

При настройке класса страницы происходит немного своеобразная структура. Вот основная идея:

class MyPage
  include PageObject

  table(:some_table, ...)

  def add_line_item(data = {})
    GridRow.new(some_table_element.last_row, browser).quick_fill(data)
  end

  class GridRow
    include PageObject

    #page object accessors
    text_field(:my_field) { row.text_field_element(id: 'ID1') }
    #etc

    def quick_fill(data = {})
      #see above
    end

    def initialize(row, browser, visit = false)
      @row = row
      super(browser, visit) 
    end
  end
end

Так что пример вызова будет (из теста на огурец)

on_page(MyPage) do |page|
  page.add_line_item(:my_detail => 'myValue')
end

В дополнение к этому, есть неприятная проблема, что для доступа к этой странице необходимо несколько вызовов 'attach_window' (из-за того, что страница находится в модальном диалоговом окне). Проблема может быть в значительной степени связана с этим взаимодействием. Это единственное, о чем я могу думать, что это вызовет проблемы.

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

0 ответов

Другие вопросы по тегам