Using Selenium to imitate dragging a file onto an upload element

后端 未结 4 682
轻奢々
轻奢々 2020-12-05 10:47

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\

4条回答
  •  北荒
    北荒 (楼主)
    2020-12-05 11:27

    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.$('').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
    

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

    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.$('').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
    

    Usage:

    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   
    

提交回复
热议问题