Тестирование перетаскивания с полным календарем с использованием Capybara/Poltergeist

Обзор

Я работаю над приложением Ruby on Rails, часть которого использует Fullcalendar для перетаскивания и упорядочивания событий в пространстве календаря, вне его и внутри пространства календаря для настройки дневного расписания.

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

Неудачная попытка тестирования №1

Сначала я попытался использовать Node::Element#drag_to Capybara, указав элемент как можно глубже в календаре (который оказался вторым <td> дочерним элементом <tr> элемента временного интервала (пример: $('tr[data-time="12:00:00"] td.fc-widget-content')[1]).

Точный звонок был:

find('div[data-duration="1800000"]').drag_to all('tr[data-time="12:00:00"] td.fc-widget-content')[1] find находил правильный элемент, как и all, как было проверено с помощью binding.pry

Это не удается, и я почти уверен, что это не удается, потому что левый край этого элемента <td> находится за пределами области, которую Fullcalendar регистрирует как удаляемую, и, таким образом, элемент возвращается на свое место.

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

Неудачная попытка тестирования № 2

Capybara/Poltergeist поставляется с, казалось бы, удобным drag_by(x, y) (см. документацию здесь). Поскольку мне нужно было вычислить свои собственные смещения x и y из заданных элементов div, я выделил эту операцию в отдельную функцию в своих спецификациях:

def drag_to_calendar(element_identifier, time = '12:00:00', x_off = 0, y_off = 0)
  x_buff = 100 # Number of pixels to the right of the left edge to get to the middle-area of the element
  y_buff = 10  # Number of pixels below the top to get to the middle-area of the element
  dest_x_script = "$('tr[data-time=\"#{time}\"]').offset().left"
  dest_y_script = "$('tr[data-time=\"#{time}\"]').offset().top"
  init_x_script = "$('#{element_identifier}').offset().left"
  init_y_script = "$('#{element_identifier}').offset().top"

  dest_x = page.evaluate_script(dest_x_script) + x_buff + x_off
  dest_y = page.evaluate_script(dest_y_script) + y_buff + y_off
  init_x = page.evaluate_script(init_x_script)
  init_y = page.evaluate_script(init_y_script)
  x = dest_x - init_x
  y = dest_y - init_y

  find(element_identifier).native.drag_by(x, y)
end

Я сделал функцию, позволяющую указывать любое время вместе с любыми дополнительными смещениями x и y (для более динамичного перемещения элементов внутри/вокруг календаря). element_identifier — это просто строка, которую можно вставить непосредственно в функцию Capybara find() для получения этого элемента.

Пример использования:

drag_to_calendar("div[data-duration="1800000"]", '12:00:00', 0, 0)

(Переменные *_script связаны с тем, что вы не можете напрямую вставлять #{variables} в аргументы Assessment_script, поэтому мне пришлось создавать эти строки перед их вызовом. Вы могли заметить, что вместо этого я получаю только элементы <tr> в сценариях. второго <td> дочернего элемента; это потому, что я не мог заставить .offset() работать с дочерними элементами; 100-пиксельное смещение по горизонтали должно было начинаться дальше влево, чем раньше)

С помощью binding.pry я убедился, что все переменные заданы правильно, все скрипты работают правильно, а все арифметические операции в конце работают как надо.

Использование совершенно уникальной тестовой страницы, не связанной с приложением, в значительной степени основанной на ответ robertc здесь Я подтвердил, что drab_by Капибары/Полтергейста также работает. (Для создания тестовой среды я перезаписал страницу #edit, на которой все это происходит, примером robertc, добавил его стиль aside в application.scss и добавил следующий код в файл javascript, который работает на этой странице:

$(document).on('turbolinks:load',function() {
    // Pre-existing javascript things....

    dm = document.getElementById('dragme');
    if (dm != null) {
        dm.addEventListener("mousedown", dmMouseDown, false);
    }
});

function dmMouseDown () {
    stateMouseDown = true;
    document.addEventListener ("mousemove", dmMouseMove, false);
}

function dmMouseMove(ev) {
    var pX = ev.pageX;
    var pY = ev.pageY;
    dm.style.left = pX + "px";
    dm.style.top = pY + "px";
    document.addEventListener ("mouseup", dmMouseUp, false);
}

function dmMouseUp() {
    document.removeEventListener ("mousemove", dmMouseMove, false);
    document.removeEventListener ("mouseup", dmMouseUp, false);
}

Это показало, что drag_by Capybara/Poltergeist работает точно так же, как перетаскивание элемента с помощью мыши.

И все же, когда все эти функционирующие элементы собрались вместе, спецификация все еще не функционировала. В среде binding.pry я тестировал перетаскивание, используя все возможные преобразования: перестановку x и y, использование отрицательных значений (на случай, если я попал в зеркальную вселенную, где +x означает, что осталось), обработку x и y как смещения от начального element, рассматривая их как абсолютные из источника страницы и даже подбрасывая полуслучайные значения в x и y в надежде, что достаточное количество дротиков может в конечном итоге попасть в мишень для дротиков. Ничего не сработало. Либо элементы не перетаскиваются (маловероятно, учитывая вышеизложенное), либо fullcalendar не регистрирует перетаскивание.

Оценка

Я думаю, что проблема связана с Fullcalendar или во взаимодействии между Poltergeist и Fullcalendar, когда Fullcalendar ничего не распознает как отбрасываемое. Просматривая прослушиватели событий в инструментах отладки Chrome, кажется, что mousedown, mouseup и mousemove — единственные связанные с перетаскиванием вещи, которые есть в Javascript, и, следовательно, это единственные вещи, которые Fullcalendar мог бы искать, и таким образом< /em> кажется, это должно работать. Но это не так.

Любые советы будут высоко ценится. Любые решения, тем более!


person Elliott Gladden    schedule 15.12.2016    source источник


Ответы (1)


В следующем коде показано перетаскивание события, работающего на демонстрационной странице FullCalendar.

require 'capybara/poltergeist'

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, js_errors: true, phantomjs_options: ['--ssl-protocol=TLSv1.2'])
end

sess = Capybara::Session.new(:poltergeist)
sess.visit 'https://fullcalendar.io/'
event = sess.first('.fc-day-grid-event', minimum: 1)
first_day = sess.find('.fc-day-grid .fc-week:first-child .fc-content-skeleton tbody td:first-child')
first_day.assert_no_selector('.fc-day-grid-event')

event.drag_to(first_day)
first_day.assert_selector('.fc-day-grid-event')

который перетаскивает первое событие в календаре обратно в первый день календаря. Поскольку это работает, вероятно, проблема с конфигурацией FullCalendar, ваши расчеты местоположения отключены или вы перетаскиваете не тот элемент. Я вижу, что в FullCalendar есть настраиваемая задержка перед началом перетаскивания, вы случайно не установили ее?

person Thomas Walpole    schedule 15.12.2016