Cypress 和使用 selectFile() 进行文件上传的拖放选项

huangapple go评论71阅读模式
英文:

Cypress and file upload using selectFile() with drag n drop option

问题

我正在尝试使用Cypress测试文件上传小部件的功能。

我尝试过的Cypress测试如下:

const filePath = './cypress/fixtures/example.jpg';

cy.get('.dropzone')
  .selectFile(filePath, 
  { action: 'drag-drop',
    force: true, }).trigger('drop', {force: true})

以及

cy.get('.dropzone > input[type="file"]').should('exist').invoke('show')
  .selectFile(filePath, {
    action: 'drag-drop',
    force: true,
    log: true,
  })
  .trigger('drop', {force: true})

以及

cy.get('.dropzone')
  .children('input[type="file"]')
  .should('exist')
  .invoke('show')
  .selectFile(filePath, { force: true })
  .then(input => {
    expect(input[0].files[0].name).to.equal('example.jpg')
  })
  .wait(6000)
  .trigger('dragstart', { force: true, 
  dataTransfer: dataTransfer })
  .wait(50)
  .trigger('dragover', { force: true })
  .wait(50)
  .trigger('drop', { force: true })
  .wait(50)
  .trigger('dragend', { force: true })
  .wait(50)
  .trigger('change', { force: true });

以及

cy.document().get('.dropzone')
  .children('input[type="file"]').selectFile(filePath, { action: 'drag-drop' })

以及

cy.document().get('.dropzone')
  .children('input[type="file"]')
  .selectFile(filePath, { action: 'drag-drop', force: true })
  .trigger('drop', { force: true });

执行测试的HTML如下:

<div tabindex="0" role="button" class="dropzone  svelte-817dg2" style="">
<input accept="image/*" type="file" name="avatar" autocomplete="off" tabindex="-1" style="display: none;">
<p>Drag 'n' drop some files here, or click to select files</p>
</div>

我正在使用此Svelte组件进行拖放文件上传 - https://github.com/thecodejack/svelte-file-dropzone

然而,在两种情况下以及所有变化的情况下,测试从未成功上传文件。

但是,在Cypress Chrome浏览器中,我能够手动成功执行拖放操作。

英文:

I'm attempting to test, using cypress, the functionality of a file upload widget.

The cypress tests which I've tried are:

const filePath = &#39;./cypress/fixtures/example.jpg&#39;

    cy.get(&#39;.dropzone&#39;)
    .selectFile(filePath, 
    { action: &#39;drag-drop&#39;,
      force: true, }).trigger(&#39;drop&#39;, {force: true})

and


    cy.get(&#39;.dropzone &gt; input[type=&quot;file&quot;]&#39;).should(&#39;exist&#39;).invoke(&#39;show&#39;)
    .selectFile(filePath, {
      action: &#39;drag-drop&#39;,
      force: true,
      log: true,
    })
    .trigger(&#39;drop&#39;, {force: true})

and

cy.get(&#39;.dropzone&#39;)
    .children(&#39;input[type=&quot;file&quot;]&#39;)
    .should(&#39;exist&#39;)
    .invoke(&#39;show&#39;)
    .selectFile(filePath, { force: true })
    .then(input =&gt; {
      expect(input[0].files[0].name).to.equal(&#39;example.jpg&#39;)
    })
    .wait(6000)
    .trigger(&#39;dragstart&#39;, { force: true, 
    dataTransfer: dataTransfer })
    .wait(50)
    .trigger(&#39;dragover&#39;, { force: true })
    .wait(50)
    .trigger(&#39;drop&#39;, { force: true })
    .wait(50)
    .trigger(&#39;dragend&#39;, { force: true })
    .wait(50)
    .trigger(&#39;change&#39;, { force: true });

and

cy.document().get(&#39;.dropzone&#39;)
    .children(&#39;input[type=&quot;file&quot;]&#39;).selectFile(filePath, { action: &#39;drag-drop&#39; })

and

cy.document().get(&#39;.dropzone&#39;)
    .children(&#39;input[type=&quot;file&quot;]&#39;)
    .selectFile(filePath, { action: &#39;drag-drop&#39;, force: true })
    .trigger(&#39;drop&#39;, { force: true });

The html that the tests are executing against is:

&lt;div tabindex=&quot;0&quot; role=&quot;button&quot; class=&quot;dropzone  svelte-817dg2&quot; style=&quot;&quot;&gt;
&lt;input accept=&quot;image/*&quot; type=&quot;file&quot; name=&quot;avatar&quot; autocomplete=&quot;off&quot; tabindex=&quot;-1&quot; style=&quot;display: none;&quot;&gt; 
&lt;p&gt;Drag &#39;n&#39; drop some files here, or click to select files&lt;/p&gt;
&lt;/div&gt;

I am using this svelte component for the drag 'n' drop file upload - https://github.com/thecodejack/svelte-file-dropzone

In both cases, and every variation on these, the tests never actually upload a file.

However, in the cypress chrome browser, I'm able to manually perform the drag n drop action successfully.

答案1

得分: 4

I checked out your code and couldn't get .selectFile() to work. Just used the HTML segment you gave, ran it with VS Code live server (I know it's a svelte app, but..).

Using the simplest test, should at least be able to see the file attached to the internal <input>.

Note {action:'drag-drop'} searches for the <input> within div.dropzone.

const filePath = './cypress/fixtures/example.jpg';

cy.get('.dropzone')
  .selectFile(filePath, {action:'drag-drop'})

cy.get('.dropzone')
  .find('input')
  .then($input => $input[0].files)
  // assert some things about the input's FileList...
  .should('have.length', 1)
  .and(fileList => expect(fileList[0].name).to.eq('example.jpg'))
  .and(fileList => expect(fileList[0].size).to.eq(159355))

But this fails, which makes me think there's a bug in .selectFile(). The other weird thing is the assert is green as if passing, but actually throws an AssertionError.

Update: Adding "input" to selector

It will work if you add input to the .dropzone selector, but you also need the {force: true} option as the input is hidden.

const filePath = './cypress/fixtures/example.jpg';

cy.get('.dropzone input')
  .selectFile(filePath, {force: true})  

cy.get('.dropzone')
  .find('input')
  .then($input => $input[0].files)
  // assert some things about the input's FileList...
  .should('have length', 1)
  .and(fileList => expect(fileList[0].name).to.contain('example.jpg'))
  .and(fileList => expect(fileList[0].size).to.eq(159355))

If you swap in the older 3rd-party cypress-file-upload, it works.

// path applied is assumed to be /cypress/fixtures/
const filePathInFixtures = 'example.jpg'  

cy.get('.dropzone')
  .attachFile(filePathInFixtures, { subjectType: 'drag-n-drop' })

cy.get('.dropzone')
  .find('input')
  .then($input => $input[0].files)
  // assert some things about the input's FileList...
  .should('have length', 1)
  .and(fileList => expect(fileList[0].name).to.eq('example.jpg'))
  .and(fileList => expect(fileList[0].size).to.eq(159355))

That gets the file attached, but probably you need to trigger some event to kick off the actual upload. I can't tell what that would be from the info you gave, but try input or change to start with.

英文:

I checked out your code and couldn't get .selectFile() to work. Just used the HTML segment you gave, ran it with VS Code live server (I know it's a svelte app, but..).

Using the simplest test, should at least be able to see the file attached to the internal &lt;input&gt;.

Note {action:&#39;drag-drop&#39;} searches for for the &lt;input&gt; within div.dropzone.

const filePath = &#39;./cypress/fixtures/example.jpg&#39;

cy.get(&#39;.dropzone&#39;)
  .selectFile(filePath, {action:&#39;drag-drop&#39;})

cy.get(&#39;.dropzone&#39;)
  .find(&#39;input&#39;)
  .then($input =&gt; $input[0].files)
  // assert some things about the input&#39;s FileList...
  .should(&#39;have.length&#39;, 1)
  .and(fileList =&gt; expect(fileList[0].name).to.eq(&#39;example.jpg&#39;))
  .and(fileList =&gt; expect(fileList[0].size).to.eq(159355))

But this fails, which makes me think there's a bug in .selectFile(). The other weird thing is the assert is green as if passing, but actually throws an AssertionError.

Cypress 和使用 selectFile() 进行文件上传的拖放选项


Update: Adding "input" to selector

It will work if you add input to the .dropzone selector, but you also need the {force: true} option as the input is hidden.

const filePath = &#39;./cypress/fixtures/example.jpg&#39;

cy.get(&#39;.dropzone input&#39;)
  .selectFile(filePath, {force: true})  

cy.get(&#39;.dropzone&#39;)
  .find(&#39;input&#39;)
  .then($input =&gt; $input[0].files)
  // assert some things about the input&#39;s FileList...
  .should(&#39;have.length&#39;, 1)
  .and(fileList =&gt; expect(fileList[0].name).to.contain(&#39;example.jpg&#39;))
  .and(fileList =&gt; expect(fileList[0].size).to.eq(159355))

Cypress 和使用 selectFile() 进行文件上传的拖放选项


If you swap in the older 3rd-party cypress-file-upload
, it works.

// path applied is assumed to be /cypress/fixtures/
const filePathInFixtures = &#39;example.jpg&#39;  

cy.get(&#39;.dropzone&#39;)
  .attachFile(filePathInFixtures, { subjectType: &#39;drag-n-drop&#39; })

cy.get(&#39;.dropzone&#39;)
  .find(&#39;input&#39;)
  .then($input =&gt; $input[0].files)
  // assert some things about the input&#39;s FileList...
  .should(&#39;have.length&#39;, 1)
  .and(fileList =&gt; expect(fileList[0].name).to.eq(&#39;example.jpg&#39;))
  .and(fileList =&gt; expect(fileList[0].size).to.eq(159355))

Cypress 和使用 selectFile() 进行文件上传的拖放选项

That gets the file attached, but probably you need to trigger some event to kick off the actual upload. I can't tell what that would be from the info you gave, but try input or change to start with.

答案2

得分: 0

以下是翻译好的内容:

感谢@Fody提供了详细的示例。

然而,这些仍然没有起作用。

下面的方法有效,但不够稳定。在触发事件之前需要等待,并且我猜测不稳定性是因为等待时间不够长。

const filePathInFixtures = 'example.jpg'

cy.get('.dropzone')
  .attachFile(filePathInFixtures, { subjectType: 'drag-n-drop' })
  .wait(2000)
  .trigger('change', { force: true })

cy.get('.dropzone')
  .find('input', { timeout: 10000 })
  // .wait(1000)
  .trigger('change', { force: true })
  .then($input => $input[0].files)
  // 断言一些关于输入的 FileList 的内容...
  .should('have.length', 1)
  .and(fileList => expect(fileList[0].name).to.contain('example.jpg'))
  .and(fileList => expect(fileList[0].size).to.eq(40319));
英文:

Many thanks goes to @Fody for providing detailed examples.

However, these still did not work.

The below works, but is flaky. There is a need to wait before triggering the event. And I guess the flakiness is due to not waiting long enough.

const filePathInFixtures = &#39;example.jpg&#39;  

    

    cy.get(&#39;.dropzone&#39;)
      .attachFile(filePathInFixtures, { subjectType: &#39;drag-n-drop&#39; })
      .wait(2000)
      .trigger(&#39;change&#39;, { force: true })

    cy.get(&#39;.dropzone&#39;)
      .find(&#39;input&#39;, { timeout: 10000 })
      // .wait(1000)
      .trigger(&#39;change&#39;, { force: true })
      .then($input =&gt; $input[0].files)
      // assert some things about the input&#39;s FileList...
      .should(&#39;have.length&#39;, 1)
      .and(fileList =&gt; expect(fileList[0].name).to.contain(&#39;example.jpg&#39;))
      .and(fileList =&gt; expect(fileList[0].size).to.eq(40319));

huangapple
  • 本文由 发表于 2023年6月1日 12:30:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76378672.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定