DevExpress / testcafe

A Node.js tool to automate end-to-end web testing.
https://testcafe.io
MIT License
9.82k stars 671 forks source link

File upload problem with Excel Files in Latest Version of Chrome 125 #8198

Closed ShamaGarg closed 3 months ago

ShamaGarg commented 4 months ago

What is your Scenario?

Started facing an issue with the end to end tests using Test Cafe. These tests check for cases where we have an upload button that accepts excel files sends it to server. We use setFilesToUpload to mimic this behavior in the test environment.

They used to work fine but with a recent update of Chrome, these tests suddenly started failing. We have other tests that upload other file types (pdf, json) which are working perfectly fine.

Also, it's only problem with the e2e tests, when we normally check that functionality in the same version of chrome it works fine.

What we have noticed is file size is different when uploaded in test environment than in a real scenario.

What is the Current behavior?

-

What is the Expected behavior?

-

What is the public URL of the test page? (attach your complete example)

-

What is your TestCafe test code?

-

Your complete configuration file

No response

Your complete test report

No response

Screenshots

No response

Steps to Reproduce

  1. - 2.- 3.-

TestCafe version

3.3.0

Node.js version

20.9.0

Command-line arguments

-

Browser name(s) and version(s)

Chrome 125

Platform(s) and version(s)

Windows, Ubuntu

Other

No response

Jisco commented 4 months ago

We have the same problem regardless of the file extension. The upload stream is cut off at 768kb.

github-actions[bot] commented 4 months ago

Thank you for submitting a bug report. We would love to help you investigate the issue. Please share a simple code example that reliably reproduces the bug. For more information, read the following article: How To Create a Minimal Working Example When You Submit an Issue. We look forward to your response.

ShamaGarg commented 4 months ago

@ PavelMor25, It's a bit difficult to share working example due to privacy concerns. But as @Jisco also mentioned it looks like its a a normal upload test that is just making either the stream cut off in the latest version of chrome. Is it possible to check that first with a simple upload test with testcafe? Apart from that we are not doing any extra logic, it just takes the excel file and then sends the form data to the server. I have added a simple screenshot of File object that we receive in both cases.

Normal normal_browser_upload

TestCafe testcafe_upload

PavelMor25 commented 4 months ago

I tried to reproduce the described scenario and did not encounter any issues.

It's a bit difficult to share a working example due to privacy concerns.

We understand that there are reasons why you cannot share an example. However, the article describes how to create a minimal working example while avoiding the use of any private information that cannot be published. Additionally, if there is any information that can help us reproduce the issue, please share it.

My example:

import { Selector, ClientFunction } from 'testcafe';
import fs from 'fs';

let fileSize = 0;

fs.stat('./upload/stats.xlsx', (err, stats) => {
    if (err) {
        console.error(err);
        return;
    }

    fileSize = stats.size;
});

const getSizeUploadFile = ClientFunction(() => document.querySelector('#file').files[0].size);

fixture `Upload`
    .page `./index.html`;

test('Upload the file', async t => {
    const finput = Selector('#file');

    await t.setFilesToUpload(finput,'stats.xlsx');

    const uploadSize = await getSizeUploadFile();

    await t.expect(uploadSize).eql(fileSize);
});
Jisco commented 4 months ago

Sorry, but in our case it's a bit more complicated.

We use a .NET Core 6 server as a backend and to execute the tests we use the json files generated by TestCafe Studio. So we didn't write the test "manually", maybe that helps in any way.

So i could share the backend code with you, but as already said it works "in the real world" but not when executing the tests.

BTW: The file needs to be larger than 768kb to fail, was your test file large enough?!

Gandhi11 commented 4 months ago

Same problem on my side, all the upload tests are falling regardless of the project since Latest Version of Chrome 125 and using native-automation.

When using --disable-native-automation it is working.

On our side, we make an XHR request when the input file change to upload the file and that is what get truncated.

PavelMor25 commented 4 months ago

So i could share the backend code with you, but as already said it works "in the real world" but not when executing the tests.

We need a complete application and test where this issue is reproduced so we can investigate it. If you can share the test or create a reproducible example, it will be very helpful.

The file needs to be larger than 768kb to fail, was your test file large enough?!

My test file is 10MB.

Additionally, please specify the following information:

ShamaGarg commented 4 months ago

We need a complete application and test where this issue is reproduced so we can investigate it

@PavelMor25 Its not possible to do that, also we are close to our release so difficult for now to work on a shareable test/reproducible example for now.

Additionally, please specify the following information:

Node.js version: 20.9.0 TestCafe version: 3.3.0 We also checked it with 3.6 and found same problem OS version: Windows 10, but we also faced this on Ubuntu which we use on our CI/CD Any other relevant information that might help us.: What we could notice is something wrong with file data, it changes so better not only look for size but other properties that are being sent and try to see what changes when sent in normal browser vs test cafe.

Jisco commented 4 months ago

@PavelMor25

We need a complete application and test where this issue is reproduced so we can investigate it. If you can share the test or create a reproducible example, it will be very helpful.

This is our backend code. The first stream here has always 786kb in the test context, no matter how large the file is.

[HttpPost("api/BackupManagement/BackupFile/{name}")]
[RequestFormLimits(ValueLengthLimit = Int32.MaxValue, MultipartBodyLengthLimit = Int64.MaxValue, MemoryBufferThreshold = Int32.MaxValue)]
[RequestSizeLimit(100_000_000_000)]
[MultipartFormData]
[DisableFormValueModelBinding]
public async Task UploadAsync(String name, CancellationToken cancellationToken)
    {
        var fileIdentifier = Guid.NewGuid().ToString();

        try
        {
            var streams = Request
                .ReadSectionsAsync(ModelState, cancellationToken)
                .Select(x => x.Stream);

          using (var targetStream = File.Open(name, FileMode.Create, FileAccess.Write))
          {
              await foreach (var sourceStream in streams)
              {
                  await sourceStream.CopyToAsync(targetStream, cancellationToken);
              }

              targetStream.Close();
          }

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            return;
        }
        catch (Exception ex)
        {
            return BadRequest(ModelState);
        }
    }

In frontend we used TestCafe Studio to produce the test and in code we simply use the angular devextreme file-uploader component.

Node.js version: 18.18.2 TestCafe version: 3.4.0 we tried 3.6.0 but it makes no difference OS version: Windows 11, Windows Server 2022

Michael-Dawkins commented 4 months ago

We have the same issue, it is breaking our entire test suite. I cannot share an easy reproduction scenario but this is the error we are now getting: "Invalid header signature; read 0x0000001AB1A1E011, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document" on our Java backend.

PavelMor25 commented 4 months ago

Since we haven't been able to reproduce the issue yet, we ask you to try this workaround. If it helps, it will assist us in addressing the issue.

Add a custom action to your configuration file:

// .testcaferc.js
module.exports = {
    customActions: {
     async uploadFileNativeAutomation (selector, file) {
        const cdpClient  = await this.getCurrentCDPSession(); // for TestCafe version lower 3.6.0 use this.testRun.browserConnection.getNativeAutomation()._client
        const { root }   = await cdpClient.DOM.getDocument();
        const { nodeId } = await cdpClient.DOM.querySelector({
            nodeId: root.nodeId, 
            selector
        })

        await cdpClient.DOM.setFileInputFiles({
            files: [file], 
            nodeId
        })
      }, 
    }
};

Use this action in your test instead of the setFilesToUpload action:

// test.js
import path from 'path';

fixture `Upload`
    .page `https://page.test`;

test('Upload the file', async t => {
// code
    await t.customActions.uploadFileNativeAutomation(
        '#file', 
        path.join(__dirname,'./file1.txt') // path to file must be absolute
    );
// code
});

Please let us know your results.

Gandhi11 commented 4 months ago

I just tried it out and the same problem occurred.

Here's the header of a WORKING file upload XHR request made via Chrome directly.

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 9667
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBpjhnMLnFCMcjVgW
Cookie: REDACTED
Host: REDACTED
Origin: REDACTED
Referer: REDACTED
Sec-Ch-Ua: "Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "macOS"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

NOT WORKING file upload XHR request made via Chrome with testcafe.

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 5953
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarygufuFBG0T8nofzwb
Cookie: REDACTED
Host: REDACTED
Origin: REDACTED
Referer: REDACTED
Sec-Ch-Ua: "Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "macOS"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

The main difference as you can see is that the Content-Length get truncated to 5953.

ShamaGarg commented 4 months ago

Hi @PavelMor25,

I tried with the above workaround and got this error, hope this might be helpful for you in investigating it further:

image image image

michailtsiropoulos commented 4 months ago

Hello, I am working on the same team with @ShamaGarg. Additionally, I would like to inform you that this issue can also be reproduced manually on the Chrome browser of testCafe after unlocking the browser when the test fails. This problem occurs only on the browser tab that the test runs, not if we open a new tab.

PavelMor25 commented 4 months ago

Unfortunately, we didn't manage to reproduce the issue. As soon as we receive a reproducible example, we will start working on it immediately. We understand the importance of this issue and are actively trying to find a way to replicate it so we can investigate and resolve it.

Gandhi11 commented 4 months ago

@PavelMor25 I was able to make a small repo to help you guys solving the problem.

Please have look at https://github.com/Gandhi11/testcafe-test and let me know if you have any questions.

The .env file was committed to help you with the configuration.

Bayheck commented 4 months ago

Hello,

Thank you for sharing the sample.

For some reason, I get the following error after trying to run ./vendor/bin/sail migrate:

image

Could you please check it?

In addition, it will be easier for us to work on the issue if the sample setup is as simple as possible. This is because we need to reproduce the issue as well as investigate it.

Gandhi11 commented 4 months ago

Hi @Bayheck, I made a typo in the command. I am sorry for that. It should be ./vendor/bin/sail artisan migrate.

I understand that a simple setup is the better, but in this case you guys need to have a backend to retrieve and store the uploaded file. That is why I provided you with a Laravel Sail setup. It may be possible to achieve the same result with a nodejs backend but I am not in the position to provide a working setup.

github-actions[bot] commented 3 months ago

We appreciate you taking the time to share information about this issue. We reproduced the bug and added this ticket to our internal task queue. We'll update this thread once we have news.

Bayheck commented 3 months ago

Hello, we have created a fix for this issue. Could you please check your tests with this build?

https://github.com/Bayheck/Builds/blob/main/testcafe-3.6.1.tgz

I look forward to your results.

gforepsly commented 3 months ago

Hello, we have created a fix for this issue. Could you please check your tests with this build?

https://github.com/Bayheck/Builds/blob/main/testcafe-3.6.1.tgz

I look forward to your results.

I had the same exact issue, and now when I ran the test with this build - it seems ok! The upload worked, and my tests is green :) When can we expect this to be in the official version we can download using NPM/Yarn?

michailtsiropoulos commented 3 months ago

fix for this issue. Could you pleas

Hello, the fix is also working for our team. Thank you!

Bayheck commented 3 months ago

Hello,

Thank you for testing the build.

Unfortunately, we cannot give an ETA on when we will introduce this fix. If everything goes as planned, it will be in the next TestCafe release.

github-actions[bot] commented 3 months ago

Release v3.6.2-rc.1 addresses this.