Reputation: 2656
I'm trying to test an image upload using Selenium/Mink with Behat in a Symfony application. The application is running in a Docker container.
I'm attaching the file directly to the NodeElement
of the input rather than use $driver->attachFileToField('#id-of-input', $filePath)
because we're dealing with a lot of inputs in the context and already have the input in the method being called:
$input->attachFile($this->filesPath . '1.jpg');
The resulting path is:
/var/www/html/src/Resources/TestImages/1.jpg
This file certainly exists at that path in the docker container but when the form is submitted, this error is thrown:
There are no helpful logs.
I've tried setting the files_path
parameter in behat.yml
but then I get error during the test running:
unknown error: path is not absolute: 3.jpg
Am I missing something? Is that file path incorrect for the container?
I've tried using the abs path on my machine to no avail (though this approach has serious drawbacks so I'm glad it wasn't the solution):
/Users/its.me/Sites/kbs/src/Resources/TestImages/1.jpg
The local Users
dir is mounted into my docker-machine too so that abs path works on the host. I thought it might be permissions related so I set them all to read/write/execute but no cigar! Relative paths don't work.
Where are my images?
Upvotes: 2
Views: 2745
Reputation: 166457
Make sure to include files_path
in your Behat.yml
file under MinkExtension
section, e.g.
default:
extensions:
Behat\MinkExtension\Extension:
files_path: %behat.paths.base%/build/dummy/
Also make sure that you have the right folder structure, e.g.
# Your application
football
build
dummy
document
hello.doc
world.xls
image
test.jpg
Example Behat Feature:
Feature: Example feature
Scenario: I can upload image
Given I am on "/"
When I attach the file "image/test.jpg" to "league_flag"
And I press "Submit"
Then I should see "Succeeded."
Here is the actual MinkExtension built method:
/**
* Attaches file to field with specified id|name|label|value
* Example: When I attach "bwayne_profile.png" to "profileImageUpload"
* Example: And I attach "bwayne_profile.png" to "profileImageUpload"
*
* @When /^(?:|I )attach the file "(?P<path>[^"]*)" to "(?P<field>(?:[^"]|\\")*)"$/
*/
public function attachFileToField($field, $path)
{
$field = $this->fixStepArgument($field);
if ($this->getMinkParameter('files_path')) {
$fullPath = rtrim(realpath($this->getMinkParameter('files_path')), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$path;
if (is_file($fullPath)) {
$path = $fullPath;
}
}
$this->getSession()->getPage()->attachFileToField($field, $path);
}
See: File uploading with Behat.
Upvotes: 1
Reputation: 2656
Based on the issue posted by @lauda at GitHub, the MinkSeleniumDriver needs some file preparation to work properly. Namely, turning it into a zip file. This comment helped:
$localFile = $this->filesPath . '01.jpg';
$tempZip = tempnam('', 'WebDriverZip');
$zip = new \ZipArchive();
$zip->open($tempZip, \ZipArchive::CREATE);
$zip->addFile($localFile, basename($localFile));
$zip->close();
$remotePath = $this->getSession()->getDriver()->getWebDriverSession()->file([
'file' => base64_encode(file_get_contents($tempZip))
]);
$input->attachFile($remotePath);
unlink($tempZip);
The above code is based on the upload()
method from facebook/php-webdriver
:
/**
* Upload a local file to the server
*
* @param string $local_file
*
* @throws WebDriverException
* @return string The remote path of the file.
*/
private function upload($local_file) {
if (!is_file($local_file)) {
throw new WebDriverException("You may only upload files: " . $local_file);
}
// Create a temporary file in the system temp directory.
$temp_zip = tempnam('', 'WebDriverZip');
$zip = new ZipArchive();
if ($zip->open($temp_zip, ZipArchive::CREATE) !== true) {
return false;
}
$info = pathinfo($local_file);
$file_name = $info['basename'];
$zip->addFile($local_file, $file_name);
$zip->close();
$params = array(
'file' => base64_encode(file_get_contents($temp_zip)),
);
$remote_path = $this->executor->execute(
DriverCommand::UPLOAD_FILE,
$params
);
unlink($temp_zip);
return $remote_path;
}
Upvotes: 2
Reputation: 4173
Add the file in your behat directory and set files_path
under Behat\MinkExtension\Extension:
The files_path
should be something like: files_path: %behat.paths.features%/bootstrap
Upvotes: 1