0

I'm trying to write some PHPUnit tests for ajax endpoints. I can do this no sweat when the user doesn't have to be logged in. But to test the endpoint in question, the user does have to be logged in and I want to get the cookie programmatically as part of the test. Basically the test I want to run looks like:

    $url = "https://example.com/ajax/endpoint";
    $fields = array(
        'name'=>'test '.rand(),       
        'host'=>rand(0,255).'.'.rand(0,255).'.'.rand(0,255).'.'.rand(0,255),
        'port'=>rand(1,1000)
    );
    $fields_string = "";
    foreach ($fields as $key=>$value) {
        $fields_string .= $key.'='.$value.'&';
    }
    $fields_string = rtrim($fields_string, '&');
    ob_start();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
    curl_setopt($ch, CURLOPT_COOKIE, $userCookie);
    curl_setopt($ch, CURLOPT_URL, $url);
    $response = curl_exec($ch);
    $this->assertEquals(true, $response);
    $json = ob_get_contents();
    $return = json_decode($json);
    $this->assertEquals('false', $return->success);
    $this->assertEquals('', $return->data);
    ob_end_clean();

But I don't know a good way to get $userCookie other than opening a browser, logging in, and then reading PHPSESSID from the cookies in the browser. How can I get the cookie for this without grabbing it manually? I'd like to be able to get it from a curl request to the login endpoint:

    $url = "https://example.com/ajax/login";
    $fields = array(
        'username'=>$username,
        'password'=>$password
    );
    $fields_string = "";
    foreach ($fields as $key=>$value) {
        $fields_string .= $key.'='.$value.'&';
    }
    $fields_string = rtrim($fields_string, '&');
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
    curl_setopt($ch, CURLOPT_URL, $url);
    $response = curl_exec($ch);
wogsland
  • 9,106
  • 19
  • 57
  • 93
  • 1
    I do not have a solution for your problem at hand. But when I see the words unittest ajax call in the same sentence, I get suspicious. Unittests should not access network/IO or any other system boarders. Try mocking the network access or do the test in an integration test. – lukassteiner Nov 12 '15 at 14:52
  • You should add the curl tag. Also, like @lukassteiner said, this really is an integration test because you're both dependent on the network/IO and the session/login. – djule5 Nov 12 '15 at 15:05

2 Answers2

1

Does anything stop you to grab it programmatically?

$ch = curl_init('https://example.com/login');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "login=root&password=toor");
curl_setopt($ch, CURLOPT_HEADER, 1);

$result = curl_exec($ch);
preg_match_all('/^Set-Cookie: PHPSESSID=(.*?);/mi', $result, $matches);
$userCookie = $matches[1];
Alex Blex
  • 34,704
  • 7
  • 48
  • 75
0

You're halfway there with your login cURL request. What you need to do is retrieve the cookie from the response headers to get the PHPSESSID.

How to get response headers with cURL has been asked in another question you can find here.

Once you've got the response headers, you'll have to parse it to get the Set-Cookie header. Using the content of that header for your subsequent tests should work from there.

djule5
  • 2,722
  • 2
  • 19
  • 19