Capybara attach_file不会在Firefox中触发React onChange处理程序

时间:2019-05-23 18:21:19

标签: javascript ruby reactjs selenium capybara

我正在使用React构建的页面上测试文件上传功能。 React页面有一个隐藏的文件输入字段,并带有一个onChange事件监听器。选择文件后,它将触发onChange并处理文件。我有一个使用Capybara和javascript公开隐藏输入的测试,使用Capybara的attach_file方法将文件附加到输入中,并检查以确保该文件已上传并出现在用户的文件列表中。此测试在Chrome中有效,并且使用Capybara的attach_file方法处理文件后,但在Firefox中不起作用-文件进入输入,但从未处理过。我怀疑由于某种原因,React无法在Firefox中检测到onChange或没有被触发。我需要测试才能在两种浏览器中使用。

我尝试将execute_script与适当的普通javascript(无jquery)结合使用,以在Firefox中创建和分发change和input事件,但没有运气。经过一切尝试,最终我得到的只是暴露的输入字段和其中显示的所选文件名。作为SDET,我必须按原样使用前端代码。

文件的反应输入

<input
          className={css.hiddenInput}
          onChange={event => {
            actions.uploadAttachment(event, personOneId, personTwoId);
          }}
          ref={file => (this.file = file)}
          type="file"
        />

Ruby / Capybara / javascript代码公开输入并附加文件

def expose_attachment_input
      page.execute_script(
        'document.querySelector(`input[class^=attachments__hidden-input]`)
        .setAttribute(`style`, `visibility: visible; width: auto; height: auto;`);'
      )
      page.execute_script(
        'document.querySelector(`input[class^=attachments__hidden-input]`)
        .setAttribute(`name`, `attachments`);'
      )
    end

def add_new_attachment(attachment = 'some.gif')
      expose_attachment_input
      attach_file(
        'attachments',
        File.expand_path("./spec/files/#{attachment}")
      )
    end

在attach_file完成后,我尝试触发事件的一些示例

page.execute_script("document.getElementsByName('attachments')[0].dispatchEvent(new Event('change'))")

page.execute_script("document.getElementsByName('attachments')[0].dispatchEvent(new Event('input'))")

page.execute_script("document.getElementsByName('attachments')[0].dispatchEvent(new Event('change'), { bubbles: true })")

根据@Thomas Walpole的建议,我还尝试了以下操作并收到以下错误

page.attach_file(File.expand_path("./spec/files/some.gif"), make_visible: true)
Capybara::ExpectationNotMet: The style changes in :make_visible did not make the file input visible

attach_file(File.expand_path("./spec/files/some.gif”), make_visible: {visibility: 'visible', width: 'auto', height: 'auto'})
The hidden input temporarily flashes visible, then disappears and no file attachment is processed.


attach_file(File.expand_path("./spec/files/some.gif")) do
   page.find('span', text: ‘Add Attachments’).click
 end  
Capybara::ElementNotFound: Unable to find visible file field nil with allow_self true

attach_file(File.expand_path("./spec/files/some.gif”), make_visible: true) do
   page.find('span', text: ‘Add Attachments’).click
 end  
Capybara::ExpectationNotMet: The style changes in :make_visible did not make the file input visible

1 个答案:

答案 0 :(得分:0)

它可以在Chrome中运行但不能在Firefox中运行的事实往往表明Capybara,geckodriver或您的应用程序存在错误,因此请确保您正在运行最新版本的Capybara和geckodriver。如果仍不能解决问题,您可以在附加文件后尝试单击另一个元素,以查看是否触发了模糊/更改事件(不同的浏览器可能会在不同时间生成该事件)。

除此之外,当前版本的Capybara还提供了使隐藏文件输入可见的支持,而无需诉诸自定义JS,这可能更可靠并且行为更一致。在您的情况下,可能会是这样(如果在页面上仅输入一个文件,则无需定位器)

attach_file(File.expand_path("./spec/files/#{attachment}"), make_visible: true)

如果应用的默认CSS无法使文件输入可见,则可以指定自定义CSS,例如

attach_file(File.expand_path("./spec/files/#{attachment}"), 
            make_visible: {visibility: 'visible', width: 'auto', height: 'auto'})

在最近的Capybara版本中,更清洁,更受用户喜欢的解决方案是在其阻止模式下使用attach_file,这要求您执行用户将用来触发文件选择的操作,然后尝试执行确定正在使用哪个文件输入而不必担心可见性。

attach_file(File.expand_path("./spec/files/#{attachment}")) do
  click_button('Choose files') # whatever action a user does to trigger file selection
end

注意:在测试时,使用execute_script手动生成和调度事件通常不是一个好主意,因为它可以执行用户永远无法做的事情,并且可能会在您的应用中隐藏真正的错误。