How to test file upload in Behat

This app has this new export feature, and I'm trying to test it with Behat / Mink. The problem here is that when I click on the export link, the data on the page is exported to CSV and stored in / Downloads, but I do not see any response code or anything on the page.

Is there a way to export CSV and go to the / Downloads folder to check the file?

+6
source share
4 answers

Assuming you are using the Selenium driver, you could click the link and $this->getSession()->wait(30) until the download is complete, and then check the Files folder for the file.

That would be the easiest solution. Alternatively, you can use a proxy server, such as BrowserMob , to view all requests, and then check the response code. But that would be a very painful way for that.

The easiest way to check the file upload is to define another step with a basic statement.

 /** * @Then /^the file ".+" should be downloaded$/ */ public function assertFileDownloaded($filename) { if (!file_exists('/download/dir/' . $filename)) { throw new Exception(); } } 

This can be problematic in situations where you download a file with the same name and the browser saves it under a different name. As a solution, you can add the @BeforeScenario hook to clear the list of knowledge files.

Another problem will be the boot disk itself - it may be different for other users / machines. To fix this, you can pass the loading directory to behat.yml as an argument to the context constructor, read the docs for this.

But the best option would be to pass the configuration to Selenium, specifying a loadable directory so that it is always clear, and you know exactly where to look. I'm not sure how to do this, but from a quick googling it seems possible.

+3
source

Checkout this blog: https://www.jverdeyen.be/php/behat-file-downloads/

The main idea is to copy the current session and execute the Guzzle request. After that, you can check the answer as you like.

 class FeatureContext extends \Behat\Behat\Context\BehatContext { /** * @When /^I try to download "([^"]*)"$/ */ public function iTryToDownload($url) { $cookies = $this->getSession()->getDriver()->getWebDriverSession()->getCookie('PHPSESSID'); $cookie = new \Guzzle\Plugin\Cookie\Cookie(); $cookie->setName($cookies[0]['name']); $cookie->setValue($cookies[0]['value']); $cookie->setDomain($cookies[0]['domain']); $jar = new \Guzzle\Plugin\Cookie\CookieJar\ArrayCookieJar(); $jar->add($cookie); $client = new \Guzzle\Http\Client($this->getSession()->getCurrentUrl()); $client->addSubscriber(new \Guzzle\Plugin\Cookie\CookiePlugin($jar)); $request = $client->get($url); $this->response = $request->send(); } /** * @Then /^I should see response status code "([^"]*)"$/ */ public function iShouldSeeResponseStatusCode($statusCode) { $responseStatusCode = $this->response->getStatusCode(); if (!$responseStatusCode == intval($statusCode)) { throw new \Exception(sprintf("Did not see response status code %s, but %s.", $statusCode, $responseStatusCode)); } } /** * @Then /^I should see in the header "([^"]*)":"([^"]*)"$/ */ public function iShouldSeeInTheHeader($header, $value) { $headers = $this->response->getHeaders(); if ($headers->get($header) != $value) { throw new \Exception(sprintf("Did not see %s with value %s.", $header, $value)); } } } 
+2
source

Little modified iTryToDownload () function using all cookies:

 public function iTryToDownload($link) { $elt = $this->getSession()->getPage()->findLink($link); if($elt) { $value = $elt->getAttribute('href'); $driver = $this->getSession()->getDriver(); if ($driver instanceof \Behat\Mink\Driver\Selenium2Driver) { $ds = $driver->getWebDriverSession(); $cookies = $ds->getAllCookies(); } else { throw new \InvalidArgumentException('Not Selenium2Driver'); } $jar = new \Guzzle\Plugin\Cookie\CookieJar\ArrayCookieJar(); for ($i = 0; $i < count($cookies); $i++) { $cookie = new \Guzzle\Plugin\Cookie\Cookie(); $cookie->setName($cookies[$i]['name']); $cookie->setValue($cookies[$i]['value']); $cookie->setDomain($cookies[$i]['domain']); $jar->add($cookie); } $client = new \Guzzle\Http\Client($this->getSession()->getCurrentUrl()); $client->addSubscriber(new \Guzzle\Plugin\Cookie\CookiePlugin($jar)); $request = $client->get($value); $this->response = $request->send(); } else { throw new \InvalidArgumentException(sprintf('Could not evaluate: "%s"', $link)); } } 
0
source

There is a problem in the project that we have two servers: one with web drivers and browsers, and the second with a selenium hub. As a result, we decided to use the curl query to fetch the headers. So I wrote a function that is called in the step definition. Below you can find a function that uses the standard php functions: curl_init ()

 /** * @param $request_url * @param $userToken * @return bool * @throws Exception */ private function makeCurlRequestForDownloadCSV($request_url, $userToken) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $request_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $headers = [ 'Content-Type: application/json', "Authorization: Bearer {$userToken}" ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $output = curl_exec($ch); $info = curl_getinfo($ch); $output .= "\n" . curl_error($ch); curl_close($ch); if ($output === false || $info['http_code'] != 200 || $info['content_type'] != "text/csv; charset=UTF-8") { $output = "No cURL data returned for $request_url [" . $info['http_code'] . "]"; throw new Exception($output); } else { return true; } } 

As you can see, I have authorization using a token. If you want to understand which headers you should use, you should download the file manual and see the request and response in the network browser tab

0
source

Source: https://habr.com/ru/post/972759/


All Articles