【问题标题】:How to test input file with Jest and vue/test-utils如何使用 Jest 和 vue/test-utils 测试输入文件
【发布时间】:2018-08-06 04:23:11
【问题描述】:

我想使用 Jest 和 vue/test-utils 测试文件上传器组件。

我有这个:

 describe('show progress bar of uploading file', () => {
    const wrapper = mount(FileUploaderComponent)

    // create csv file
    let csv = new Blob([''], { type: 'text/csv;charset=utf-8;' })
    csv.name = 'myFile.csv'

    let input = wrapper.find('input')
    input.element.value = csv // || csv.error value, Error here
    input.trigger('change')

    // Update current status
  })

我在 FileUploaderComponent 的哪个位置:

<template>
  <form action="POST" enctype="multipart/form-data">
    <label class="btn btn-primary" for="input-file">
      <input class="input-file" id="input-file" name="file" type="file" accept=".xlsx, .xls, .csv">
      UPLOAD FILE
    </label>
  </form>
</template>

抛出此错误:

InvalidStateError: 这个输入元素接受一个文件名,它可能 只能以编程方式设置为空字符串。

  49 |
  50 |     let input = wrapper.find('input')
> 51 |     input.element.value = csv
  52 |     input.trigger('change')
  53 |
  54 |     // Update current status

所以,问题是:如何使用文件输入值触发事件更改?在这种情况下,一个 csv 文件作为值?

【问题讨论】:

    标签: unit-testing vuejs2 jestjs


    【解决方案1】:

    如果您只是想模拟 input.element.files 中的值并在 Jest 中更改为 input.element.value,但不一定准确模拟每个 DOM 行为,您可以通过为这些字段定义 getter/setter 来实现。这对我有用:

    let localImageInput
    let localImageInputFiles
    let localImageInputValueGet
    let localImageInputValueSet
    let localImageInputValue = ''
    
    beforeEach(function() {
      localImageInput = wrapper.find('#local-image-input')
      localImageInputFilesGet = jest.fn()
      localImageInputValueGet = jest.fn().mockReturnValue(localImageInputValue)
      localImageInputValueSet = jest.fn().mockImplementation(v => {
        localImageInputValue = v
      })
    
      Object.defineProperty(localImageInput.element, 'files', {
        get: localImageInputFilesGet
      })
    
      Object.defineProperty(localImageInput.element, 'value', {
        get: localImageInputValueGet,
        set: localImageInputValueSet
      })
    })
    
    it('should do the thing', function() {
      localImageInputValue = 'some-image.gif'
      localImageInputFilesGet.mockReturnValue([{
        size: 12345,
        blob: 'some-blob',
        width: 300,
        height: 200
      }])
    
      localImageInput.trigger('change')
    
      return Vue.nextTick().then(() => {
        // Assuming the component sets input.value = '' when this event is triggered
        // and calls someFn with the image data
        expect(localImageInputValue).toEqual('')
        expect(someFn.mock.calls[0][0]).toEqual({
          size: 12345,
          blob: 'some-blob',
          width: 300,
          height: 200
        })
      })
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用DataTransfer 对象来执行此操作。不幸的是,它还没有被添加到 JSDOM,所以你不能在 Jest 中测试。添加对象有一个未解决的问题—https://github.com/jsdom/jsdom/issues/1568

      如果您使用 Karma 在浏览器中运行测试,您可以像这样进行测试:

      const wrapper = shallow(FormComponent)
      const input = wrapper.find('input[type="file"]')
      const dT = new ClipboardEvent('').clipboardData || new DataTransfer()
      dT.items.add(new File(['foo'], 'programmatically_created.txt'))
      input.element.files = dT.files
      input.trigger('change')
      

      【讨论】:

      • 这方面有什么变化吗?
      • 同样的问题,我不关心测试进度,只关心设置文件输入值的能力
      • 我需要导入什么才能使用 ClipboardEvent 吗?我的程序抛出一个找不到它的错误,即使我安装了 npm typescript 模块。
      • @Anand 不幸的是还没有
      猜你喜欢
      • 2019-05-28
      • 2020-11-25
      • 2019-03-11
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 2019-04-02
      • 2020-02-13
      • 2019-09-26
      相关资源
      最近更新 更多