Empty cookies jar in WebTestCase - php

I would like to test if my cookie is set correctly in controller.
class RedirectControllerTest extends WebTestCase
{
public function testSetCookie($lang, $id, $actionUrl)
{
$client = static::createClient();
$crawler = $client->request('GET', /test);
$jar = $client->getCookieJar();
}
}
Controller sets cookie, but my cookie jar in test case is empty.
Is it even possible to have access to cookies in test cases?

Accessing cookies through the cookie jar is the way to go:
/* #var \Symfony\Component\BrowserKit\Cookie $cookie */
$cookie = $client->getCookieJar()->get('foo');
It works in my projects. If your cookie jar is empty you're most likely not setting the cookie properly. Remember you need to return the response you set the cookie on.

Related

How to set and send Cookies in Symfony while the front-end is in ReactJS?

I am programming an application that uses ReactJs for the front-end in localhost:3001 and Symfony for the back-end localhost:3000, and to enable cross origin communication I use "cors-bundle" in Symfony.
Now I want to create a Cookie when a user log in, but it doesn't seem to be created !
Thanks for your help,
This is the code in Symfony the moment a user logs in :
use Symfony\Component\HttpFoundation\Cookie;
$cookie = new Cookie( 'my_cookie', 1, strtotime('tomorrow') );
$res = new Response();
$res->headers->setCookie( $cookie );
return new JsonResponse($res);
This what I also tried :
$res->headers->setCookie(Cookie::create('my_cookie', 1));
return new JsonResponse($res);
What you need is:
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class YourClass extends AbstractController {
public function yourMethod(Request $request) {
$cookie = new Cookie(
"cookie_name_here", // Cookie name
1, // Cookie content
(new DateTime('now'))->modify("+1 day"), // Expiration date
"/", // Path
"localhost", // Domain
$request->getScheme() === 'https', // Secure
false, // HttpOnly
true, // Raw
'Strict' // SameSite policy
);
$res = new JsonResponse();
$res->headers->setCookie($cookie);
return $res;
}
}
Things to note here.
Setting the "Secure" flag will mean this cookie is only transmitted on a HTTPS connection. Do not neglect this in production. You may want to use $request->getScheme() === 'https' as the parameter evaluation.
The "HttpOnly" flag is for security and stops Javascipt and Browser extensions from accessing the cookie. If you're using XHR to make requests (for instance, Axios) and include "withCredentials" then this is ok to set as true and will be sent anyway. If you want to read the value in React then set this to false
It should be
$res = new JsonResponse();
$res->headers->setCookie($cookie);
Return $res;
I've not experienced any difference in doing this from Symfony 2. This has already been answered here: How to attach cookies to JSON Response in symfony2?
Have you checked your browser's developer tools to see if a cookie is arriving in the response? Specifically look at the Network tab and monitor the headers of the AJAX response.

PHPUnit + Guzzle : Cookie persistence between test methods

I am using PHPUnit and Guzzle to make API unit test. The probleme I have is that I am not able or I can't really figure out how to persiste cookie between my test methods. Or maybe am doing it all wrong ^^
The first test testGetFirst gets the data and set a session cookie on server side. The response has a Set-Cookie header with the right cookie.
The seconde test testGetSecond should return a data set if the cookie exists. Unfortunatelly it seems that Guzzle::Client doesn't store/persiste the cookie between the methods.
use PHPUnit\Framework\TestCase;
use GuzzleHttp\Client;
class MyTest extends Testcase
{
public $guzzleClient;
/**
* #before
*/
function initVariables() {
$this->guzzleClient = new Client([
'base_uri' => 'http://apiuri.com',
'cookies' => true
]);
}
// This call get some data and set a cookie (session cookie) on server side
function testGetFirst() {
$params = [
'query' => [
'param1' => 'myparam'
]
];
$response = $this->guzzleClient->request('GET', '/', $params);
// if I print out the response headers I get my cookie in 'Set-Cookie' header
// I suppose the cookie has been set correctly
print_r($response->getHeaders());
// if I print out the client conf cookie, I get the cookie too
print_r($this->guzzleClient->getConfig('cookies')->toArray());
}
// This call get data to have access it need to use a cookie that has been set by testGetFirst
// But unfortunatelly the cookie is empty while making the request
/**
* #depends testGetFirst
*/
function testGetSecond() {
$params = [
'query' => [
'param1' => 'hello'
]
];
// if I print out the client conf cookie, cookies is empty
print_r($this->guzzleClient->getConfig('cookies')->toArray());
$response = $this->guzzleClient->request('GET', '/second', $params);
// as the request can't access to a cookie it sends an error response
}
}
I know there is CookieJar that I can use in each method and pass the Set-Cookie value in to Jar but I was hopping to avoid it.
Do you have any idea or suggestion ?
Very appreciate your help.
Due to the #before annotation for the initVariables method, this method is executed before each test. That method is creating a fresh client before each test.
To solve your particular situation, since you're using the #depends testGetFirst annotation, you could have the testGetFirst method return the client object. The testGetSecond method can then receive it as an argument. Check the Test Dependencies documentation for more info regarding passing arguments into dependent tests.

Cannot read cookie data from Cakephp phpunit test

I'm using Cakephp's build in test framework to test my controllers. I have a logout function that expires a variety of cookies that are created as the user uses the site. I am trying to read said cookies to determine if a test should pass or not, i.e. to test if the cookie is correctly expired. I have made sure that the cookie component is correctly instantiated, but I cannot read any value back from the cookie that should be there. This is the code that composes the test I am running:
public function testLogout() {
// setup the cookie component
$collection = new ComponentCollection();
$this->Cookie = new CookieComponent($collection);
$result = $this->testAction('/users/logout');
$cookie_name = Configure::read('tech_cookie_name');
$cookie_data = $this->Cookie->read($cookie_name);
debug($cookie_name);
// cookie data is returning as NULL but I'm expecting some type of value.
debug($cookie_data);
debug($result);
exit;
}
I realize that exit is killing the test early, but I'm using it to see if anything is send back from the cookie. I'm not sure why I cannot read any data from a cookie that I know is there. Does anyone know why that might be, or have a solution for how to properly read from cookies in a unit test.
You cann't read from routes.php Configure::read() in certain cases and it is not a good practice. it will work in localhost but not in live. try to configure your session properly.
by calling your session from AppController and also from your current Controller (UserController) then you should be able to see it in your testing actions.
public $components = array('Session', 'RequestHandler', 'Cookie', ...);
if you write your session like this:
$this->Session->write('Test.tech_cookie_name', 'tech_cookie_name');
then you should be able to read it like this:
$this->Session->read('Test.tech_cookie_name');

Can you get Mink to follow redirect from https to http and keep the Session?

I am trying to test my ajax scripts using codeception & PhpBrowser(which uses Mink with Goutte driver).
My ajax scripts require an authenticated session in order to execute, and the session is created via my log in page.
I am having issues with getting the PhpBrowser/Link sessions, to persist after login.
I created a PhpBrowser Helper function to overwrite _initialize so I could get https working with a self signed cert on my test server like this:
public function _initialize()
{
$client = new \Behat\Mink\Driver\Goutte\Client();
$driver = new \Behat\Mink\Driver\GoutteDriver($client);
$curl_config = array_merge($this->curl_defaults, $this->config['curl']);
array_walk($curl_config, function($a, &$b) { $b = "curl.$b"; });
$curl_config['ssl.certificate_authority']=false;
$client->setClient(new \Guzzle\Http\Client('', $curl_config));
$client->followRedirects(true);
$this->session = new \Behat\Mink\Session($driver);
\Codeception\Util\Mink::_initialize();
}
Now when I run my acceptance test it seems like the Login works correctly, and the redirect happens based on the apache access_logs, but the PHPSESSID cookie does not persist, so all of my access request after login are unauthorized.
I tried testing this in acceptance test by comparing the
$I->getCurrentUrl()
$I->getResponseHeaders()
before and after the redirect.
The currentUrl() return value never gets to the redirect destination, although apache access_logs say otherwise.
getResponseHeaders() returns a PHP_SESSID cookie after the form submission, but it does not exist for all requests after.
Any ideas/guesses why the session created during login is not persisting after the redirect?
Do I need to do any special configuration to Mink sessions to get them to follow the redirect, or am I doing something else wrong?
Thanks in advance for your help!
-Ed
I finally figured out the issue.
I had to explicitly set the cookie to be saved for the /Guzzle/Http/Client object in my overwritten _initialize function.
public function _initialize()
{
$client = new \Behat\Mink\Driver\Goutte\Client();
$driver = new \Behat\Mink\Driver\GoutteDriver($client);
$cookiePlugin = new \Guzzle\Plugin\Cookie\CookiePlugin(new \Guzzle\Plugin\Cookie\CookieJar\ArrayCookieJar());
$curl_config = array_merge($this->curl_defaults, $this->config['curl']);
array_walk($curl_config, function($a, &$b) { $b = "curl.$b"; });
$curl_config['ssl.certificate_authority']=false;
$guzzle_client = new \Guzzle\Http\Client('', $curl_config);
$guzzle_client->addSubscriber($cookiePlugin);
$client->setClient($guzzle_client);
$client->followRedirects(true);
$this->session = new \Behat\Mink\Session($driver);
\Codeception\Util\Mink::_initialize();
}

How can I persist data with Symfony2's session service during a functional test?

I'm writing a functional test for an action that uses Symfony2's session service to fetch data. In my test class's setUp method, I call $this->get('session')->set('foo', 'bar');. If I output all the session data (using print_r($this->get('session')->all());) either in setUp or in the actual test method, I get back foo => bar. But if I try outputting the session data from the action being tested, I get back an empty array. Does anyone know why this is happening, and how I can prevent it?
I should note that if I call $_SESSION['foo'] = 'bar' from within setUp() the data is persisted and I can access it from the action - this problem seems local to Symfony2's session service.
Firstly try using your client's container (I'm assuming you're using WebTestCase):
$client = static::createClient();
$container = $client->getContainer();
If it still doesn't work try saving the session:
$session = $container->get('session');
$session->set('foo', 'bar');
$session->save();
I didn't try it in functional tests but that's how it works in Behat steps.
You can retrieve the "session" service.
With this service, you can :
start the session,
set some parameters into session,
save the session,
pass the Cookie with sessionId to the request
The code can be the following :
use Symfony\Component\BrowserKit\Cookie;
....
....
public function testARequestWithSession()
{
$client = static::createClient();
$session = $client->getContainer()->get('session');
$session->start(); // optional because the ->set() method do the start
$session->set('foo', 'bar'); // the session is started here if you do not use the ->start() method
$session->save(); // important if you want to persist the params
$client->getCookieJar()->set(new Cookie($session->getName(), $session->getId())); // important if you want that the request retrieve the session
$client->request( .... ...
The Cookie with $session->getId() has to be created after the start of the session
See Documentation http://symfony.com/doc/current/testing/http_authentication.html#creating-the-authentication-token

Categories