4

In my project I have a piece of my form that sends an AJAX request:

 $.ajax({
     url: '/bio_control/sample',
     type: 'POST',
     dataType: 'json',
     data: {sample_number: $(input_field).val()}, 
 });

Which activates the following controller method:

/**
 * @Route("/bio_control/sample", name="get_bio_control_sample")
 */
public function getBioControlSampleAction(Request $request)
{

    $sample_number = $request->request->get('sample_number');

    /**
     * Additional logic not shown for brevity.
     */

    $user_id = $user->getId();
    $response = array("code" => 100, "success" => true, "sample_number" => $sample_number, "sample_data" => $sample[0], "new_user" => false, "user_id" => $user_id);

    return new JsonResponse($response);
}

I'd like to be able to test this request in isolation, but I'm unsure how to write the request object.

So far my first attempt:

public function testGetBioControlSample()
    {
        $helper = $this->helper;
        $client = $this->makeClient();
        $crawler = $client->request('POST', "/bio_control/sample", array(), array('sample_number' => 67655), array(
            'CONTENT_TYPE' => 'application/json',
            'HTTP_X-Requested-With' => 'XMLHttpRequest'
        ));
        $this->assertStatusCode(200, $client);
    }

Fails because it appears to be submitting the form (I get an error related to a form field completely unrelated to the AJAX request being blank).

Can anyone demonstrate how to correctly write such a test?

3 Answers 3

3

Does this URL need authentication?

I like to use LiipFunctionalTestBundle for my functional tests and they usually looks like this:

<?php

declare(strict_types=1);

namespace Tests\Your\Namespace;

use Liip\FunctionalTestBundle\Test\WebTestCase;

class PostResourceActionTest extends WebTestCase
{
    public function testShouldReturnResponseWithOkStatusCode(): void
    {
        $credentials = [
            'username' => 'user',
            'password' => 'pass'
        ];
        $client = $this->makeClient($credentials);

        $payload = ['foo' => 'bar'];
        $client->request(
            'POST',
            '/the/url/',
            $payload,
            [],
            ['HTTP_Content-Type' => 'application/json']
        );

        $this->assertStatusCode(200, $client);
    }
}

Maybe the error you are getting is the login form asking for authentication?

Sign up to request clarification or add additional context in comments.

1 Comment

I'm using the same bundle, and am authenticating fine in all my other tests using the same flow. However, I tried your syntax and it worked perfectly - so thanks!
3

Symfony 4.1 has a new way of testing AJAX requests:

// Before
$crawler = $client->request('GET', '/some/path', [], [], [
    'HTTP_X-Requested-With' => 'XMLHttpRequest',
]);

// After
$crawler = $client->xmlHttpRequest('GET', '/some/path');

Comments

2

The exact syntax I used to solve this problem was:

public function testGetBioControlSample()
    {
        $helper = $this->helper;
        $client = $this->makeClient();

        $crawler = $client->request(
            'POST',
            "/bio_control/sample",
            array('sample_number' => 67655),
            array(),
            array('HTTP_Content-Type' => 'application/json')
        );

        $JSON_response = json_decode($client->getResponse()->getContent(), true);

        $this->assertStatusCode(200, $client);
        $this->assertNotEmpty($JSON_response);

        $this->assertEquals($JSON_response["code"], 100);
        $this->assertEquals($JSON_response["success"], true);
        $this->assertEquals($JSON_response["sample_number"], 67655);
    }

I believe I didn't need: 'HTTP_X-Requested-With' => 'XMLHttpRequest' in the final array argument.

Additionally, I had array('sample_number' => 67655) in the wrong argument.

1 Comment

Previously you was incorrectly sending the payload as the fourth argument in the $client->request() method also, which is for $files.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.