Преглед
Работя върху приложение 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> изглежда трябва да работи. Но не е така.
Всеки съвет ще бъде много ценен. Всякакви решения, много повече!