本文介绍了使用Selenium模仿将文件拖到上传元素上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个网页,当您点击按钮时会打开div。此div允许您将文件从桌面拖到其区域;然后该文件上传到服务器。我正在使用Selenium的Ruby实现。

I have a web page that opens a div when you click a button. This div allows you to drag a file from your desktop onto its area; the file then gets uploaded to the server. I'm working with the Ruby implementation of Selenium.

通过在Firefox中使用JavaScript调试器,我可以看到一个名为drop的事件正在传递给某些JavaScript代码handleFileDrop(event)。我认为如果我要创建一个模拟事件并以某种方式触发它我可以触发此代码。

By using the JavaScript debugger in Firefox, I can see that an event called "drop" is being passed to some JavaScript code "handleFileDrop(event)". I presume that if I were to create a mock event and fire it somehow that I could trigger this code.

如果找到似乎指向了一个充满希望的方向,但我仍然没有全部搞清楚。我可以使用Selenium的get_eval方法将JavaScript传递给页面。使用this.browserbot调用方法可以获得我需要的元素。

If found an interesting article that seemed to point me in a promising direction, but I'm still short of figuring it all out. I am able to pass JavaScript to the page using Selenium's get_eval method. Calling methods using this.browserbot is getting me the elements I need.

所以:


  1. 如何构建
    需要成为模拟drop
    事件一部分的文件对象?

  2. 如何触发掉落事件
    ,以便它被拾起,好像我
    已经删除了div中的文件?


推荐答案

我发布了一个使用Selenium webdriver模拟文件拖放的RSpec测试。
它使用jQuery来制作并触发假的'drop'事件。

I post an RSpec test that simulate files drag and drop using Selenium webdriver.It use jQuery to make and trigger a fake 'drop' event.

此代码模拟单个文件的拖放。为简单起见,我删除了允许多个文件丢弃的代码。如果您需要,请告诉我。

This code simulate drag and drop of a single file. For sake of simplicity I've stripped code that allow multiple files dropping. Tell me if you need it.

describe "when user drop files", :js => true do
  before do
    page.execute_script("seleniumUpload = window.$('<input/>').attr({id: 'seleniumUpload', type:'file'}).appendTo('body');")

    attach_file('seleniumUpload', Rails.root + 'spec/support/pdffile/pdfTest.pdf')

    # Trigger the drop event
    page.execute_script("e = $.Event('drop'); e.originalEvent = {dataTransfer : { files : seleniumUpload.get(0).files } }; $('#fileDropArea').trigger(e);")
  end

  it "should ..." do
     should have_content '...'
  end

PS:请记住将#fileDropArea替换为丢弃区域的ID。

P.S.: remember to replace #fileDropArea with ID of your drop area.

PPS:不要使用evaluate_script代替execute_script,否则selenium会卡住评估复杂的jQuery对象!

P.P.S: don't use evaluate_script in place of execute_script, otherwise selenium get stuck evaluating complex jQuery objects!

更新:
我写了一个你可以重复使用的方法并执行上面写的东西。

UPDATE:I've write a method you can reuse and do the stuff written above.

def drop_files files, drop_area_id
  js_script = "fileList = Array();"
  files.count.times do |i|
    # Generate a fake input selector
    page.execute_script("if ($('#seleniumUpload#{i}').length == 0) { seleniumUpload#{i} = window.$('<input/>').attr({id: 'seleniumUpload#{i}', type:'file'}).appendTo('body'); }")
    # Attach file to the fake input selector through Capybara
    attach_file("seleniumUpload#{i}", files[i])
    # Build up the fake js event
    js_script = "#{js_script} fileList.push(seleniumUpload#{i}.get(0).files[0]);"
  end

  # Trigger the fake drop event
  page.execute_script("#{js_script} e = $.Event('drop'); e.originalEvent = {dataTransfer : { files : fileList } }; $('##{drop_area_id}').trigger(e);")
end

用法:

describe "when user drop files", :js => true do
  before do
     files = [ Rails.root + 'spec/support/pdffile/pdfTest1.pdf',
               Rails.root + 'spec/support/pdffile/pdfTest2.pdf',
               Rails.root + 'spec/support/pdffile/pdfTest3.pdf' ]
     drop_files files, 'fileDropArea'
  end

  it "should ..." do
     should have_content '...'
  end
end   

这篇关于使用Selenium模仿将文件拖到上传元素上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 05:17