Behat-Laravel-Extension icon indicating copy to clipboard operation
Behat-Laravel-Extension copied to clipboard

UploadedFile is invalid

Open lisfox1 opened this issue 7 years ago • 5 comments

Hi, I am not sure if this is a right place to ask about it but when trying to test file upload I am getting an validation failure when Illuminate\Validation\Validator::validateAttribute is called. I have an FormRequest with rules as follow:

return [
    'name' => [
        'required',
        'max:100',
    ],
    'images.*' => [
        mimes:jpeg,png,jpg,gif,svg.
        max:2048'
    ],
    'description' => 'max:256',
];

I traced the problem to the Symfony\Component\HttpFoundation\File\UploadedFile::isValid function which return false. It class have an option to set an UploadedFile to test mode but it seems that the test flag is not preserve from my FeatureContext. I am using UploadedFile::fake()->image('test.png') to generate a test image with a test flag but the flag is not preserve when the request is made.

lisfox1 avatar Jun 16 '17 08:06 lisfox1

can you try not using the facade to do the test setting. I think this example might help https://github.com/alnutile/recipes/blob/master/features/bootstrap/ProfileImageDomainContext.php

alnutile avatar Jun 28 '17 20:06 alnutile

@alnutile @laracasts @JeffreyWay I'm having the same problem, I'm dumping what isValid is parsing it gets parsed 2 times during the request for some reason.

1st time: test flag is set to true, error = 0 (fine, it should pass) 2nd time: test flag is set to false (?), error = 0. Ends with the error message 'The file "iLean.pdf" was not uploaded due to an unknown error.'

        $pathToFile = base_path('features/fixtures/iLean.pdf');
        $files = [
            'file' => new \Illuminate\Http\UploadedFile($pathToFile, 'iLean.pdf', filesize($pathToFile), 'application/pdf', null, true)
        ];

        $this->sendRequest('post', $uri, [], $files);
      │ string(4) "test"
      │ bool(true)
      │ string(5) "error"
      │ int(0)
      │ string(4) "test"
      │ bool(false)
      │ string(5) "error"
      │ int(0)
      │ string(4) "file"
      │ string(62) "The file "iLean.pdf" was not uploaded due to an unknown error."
      │ object(stdClass)#5447 (1) {
      │   ["file"]=>
      │   array(1) {
      │     [0]=>
      │     string(19) "validation.uploaded"
      │   }
      │ }

happyDemon avatar Sep 29 '17 07:09 happyDemon

I never actually managed to fix this problem. What I found out is that the test flag is not preserved when the request is created and send. When the request is being created it is recreating a file object but its not preserving the test flag.

lisfox1 avatar Sep 29 '17 08:09 lisfox1

Allright, so I've found the bottleneck.

There's a Illuminate\Http\Concerns\InteractsWithInput trait, this is used to build the input data that gets validated in form requests.

This happens in convertUploadedFiles(array $files).

It loops over the files and creates a new UploadedFile, ignoring the $testing private property.

I've overwritten it in the form request that was giving me trouble:

protected function convertUploadedFiles(array $files)
    {
        return array_map(function ($file) {
            if (is_null($file) || (is_array($file) && empty(array_filter($file)))) {
                return $file;
            }

            return is_array($file)
                ? $this->convertUploadedFiles($file)
                : UploadedFile::createFromBase($file, in_array(env('APP_ENV'), ['behat', 'testing']));
        }, $files);
    }

It's strange though, since normally (if I go through the code) it should just copy the provided UploadFile object instead of creating a new one.

happyDemon avatar Oct 10 '17 08:10 happyDemon

@happyDemon is this a patch you want to sumbit for me to roll in?

alnutile avatar Oct 11 '17 08:10 alnutile