Тестване на плъзгане и пускане с пълен календар с помощта на 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 е просто низ, който може да се използва, вмъкнат директно във функция find() на Capybara, за да се получи този елемент.

Примерна употреба:

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

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

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

Използване на напълно уникална страница за тестване, несвързана с приложението, базирана силно на отговорът на robertc тук Потвърдих, че drab_by на Capybara/Poltergeist също функционира. (За да изградя тестовата среда, презаписах страницата #edit, на която се случва всичко това, с примера на robertc, добавих неговия страничен стил към 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 като отмествания от първоначалното елемент, третирайки ги като абсолютни от произхода на страницата и дори хвърляйки полупроизволни стойности в 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