使用Capybara / Poltergeist

时间:2016-12-15 00:16:11

标签: javascript ruby-on-rails rspec capybara poltergeist

概述

我正在使用Ruby on Rails应用程序,其中一部分使用Fullcalendar将事件拖放到日历空间之内,之外和之内以设置日程安排。

这一切都很美妙,但测试它是另一回事。最初,我通过模拟通过拖放方法收集的数据的控制器规范测试了功能,但不幸的是,发现控制器规格已经破坏了整个测试套件。因此,我不得不使用功能规格来测试它,并实际上将面板拖放到日历上。

测试尝试失败#1

最初我尝试使用Capybara的Node :: Element#drag_to,尽可能地将一个元素指定为日历的深处(结果是时间段的第二个<td>子元素&#39 ; s <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注册为droppable的区域之外,因此该元素返回给它#39;回家。

我认为我需要一种指定像素水平偏移的方法来解决这个问题。

测试尝试失败#2

Capybara / Poltergeist附带了一个看似方便的drag_by(x, y)(参见文档here)。因为我需要从给定的div元素计算我自己的x和y偏移量,所以我将该操作封存在我的规范中自己的函数中:

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}插入到evaluate_script参数中,因此我必须在调用它们之前构建这些字符串。你可能会注意到我只是得到了脚本中的<tr>个元素,而不是第二个<td>子元素;这是因为我无法让.offset()处理子元素; 100-像素水平偏移是为了比左边开始更远的左边开始)

使用binding.pry我确认所有变量都设置正确,所有脚本都正常运行,并且最后的所有算法都正常运行。

使用一个与应用程序无关的完全独特的测试页面robertc's answer here我确认Capybara / Poltergeist的drab_by也正常运行。 (为了构建测试环境,我用robertc的例子覆盖了#edit页面,并将其旁边的样式添加到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);
}

这表明Capybara / Poltergeist的drag_by操作完全与用鼠标拖动元素一样。

然而,当所有这些功能元素汇集在一起​​时,规范仍然无法正常运行。在一个binding.pry环境中,我使用我能想到的每个嬗变来测试拖动:使用负值(如果我进入镜像宇宙,其中+ x表示左)晃动x和y,将x和y视为初始偏移元素,将它们视为页面原点的绝对值,甚至将半随机值投入x和y,希望足够的飞镖可能最终击中飞镖板。没有任何效果。这两个元素都没有被拖动(不太可能,考虑到上述情况),或者fullcalendar没有注册掉落。

评估

认为问题问题在于Fullcalendar,或者在Poltergeist和Fullcalendar之间的交互中,Fullcalendar没有认识到任何事情被丢弃。通过Chrome的调试工具查看事件监听器,似乎mousedown,mouseup和mousemove是Javascript唯一与拖放相关的东西,因此是Fullcalendar可以寻找的唯一东西,并且< em>因此似乎 它应该正常工作。 但它不是。

非常感谢任何建议。任何解决方案,更是如此!

1 个答案:

答案 0 :(得分:0)

以下代码显示了在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中看到拖动开始之前有一个可配置的延迟,你有没有设置它?