Using Selenium to imitate dragging a file onto an upload element

后端 未结 4 662
轻奢々
轻奢々 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:16

    You can use Blueduck Sda (http://sda.blueducktesting.com) Is an OSS that has implemented ALL selenium functions (It works with selenium RC) but it allows you to automate Windows actions. So you can test web, and interact with the OS. So you can make your test, and then, just tell the mouse to click on the element and drop it where you want!

    Nice testing!

    0 讨论(0)
  • 2020-12-05 11:17

    Note: you should also add

        e.originalEvent.dataTransfer.types = [ 'Files' ];
    
    0 讨论(0)
  • 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.$('<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
    

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

    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   
    
    0 讨论(0)
  • 2020-12-05 11:37

    As @Shmoopy asked for it, here's a C# translation of the code provided by @micred

    private void DropImage(string dropBoxId, string filePath)
    {
       var javascriptDriver = this.Driver as IJavaScriptExecutor;
       var inputId = dropBoxId + "FileUpload";
    
       // append input to HTML to add file path
       javascriptDriver.ExecuteScript(inputId + " = window.$('<input id=\"" + inputId + "\"/>').attr({type:'file'}).appendTo('body');");
       this.Driver.FindElement(By.Id(inputId)).SendKeys(filePath);
    
       // fire mock event pointing to inserted file path
       javascriptDriver.ExecuteScript("e = $.Event('drop'); e.originalEvent = {dataTransfer : { files : " + inputId + ".get(0).files } }; $('#" + dropBoxId + "').trigger(e);");
    }
    
    0 讨论(0)
提交回复
热议问题