0
votes

I'm currently playing around with Exception Handler, and creating my own custom exceptions.

I've been using PHPUnit to run tests on my Controller Resource, but when I throw my custom exceptions, Laravel thinks it's coming from a regular HTTP request rathen than AJAX.

Exceptions return different response based on wether it's an AJAX request or not, like the following:

<?php namespace Actuame\Exceptions\Castings;

use Illuminate\Http\Request;

use Exception;

use Actuame\Exceptions\ExceptionTrait;

class Already_Applied extends Exception 
{

    use ExceptionTrait;

    var $redirect = '/castings';
    var $message = 'castings.errors.already_applied';

}

And the ExceptionTrait goes as follows:

<?php

namespace Actuame\Exceptions;

trait ExceptionTrait 
{

    public function response(Request $request)
    {
        $type = $request->ajax() ? 'ajax' : 'redirect';

        return $this->$type($request);
    }

    private function ajax(Request $request)
    {
        return response()->json(array('message' => $this->message), 404);
    }

    private function redirect(Request $request)
    {
        return redirect($this->redirect)->with('error', $this->message);
    }

}

Finally, my test goes like this (excerpt of the test that's failing)

public function testApplyToCasting()
{
    $faker = Factory::create();

    $user = factory(User::class)->create();

    $this->be($user);

    $casting = factory(Casting::class)->create();

    $this->json('post', '/castings/apply/' . $casting->id, array('message' => $faker->text(200)))
        ->seeJsonStructure(array('message'));
}

My logic is like this although I don't think the error is coming from here

public function apply(Request $request, User $user)
{
    if($this->hasApplicant($user))
        throw new Already_Applied;

    $this->get()->applicants()->attach($user, array('message' => $request->message));

    event(new User_Applied_To_Casting($this->get(), $user));

    return $this;
}

When running PHPUnit, the error I get returned is

1) CastingsTest::testApplyToCasting PHPUnit_Framework_Exception: Argument #2 (No Value) of PHPUnit_Framework_Assert: :assertArrayHasKey() must be a array or ArrayAccess

/home/vagrant/Code/actuame2/vendor/laravel/framework/src/Illuminate/Foundation/T esting/Concerns/MakesHttpRequests.php:304 /home/vagrant/Code/actuame2/tests/CastingsTest.php:105

And my laravel.log is over here http://pastebin.com/ZuaRaxkL (Too large to paste)

I have actually discovered that PHPUnit is not actually sending an AJAX response, because my ExceptionTrait actually changes the response on this. When running the test it takes the request as a regular POST request, and runs the redirect() response rather than ajax(), hence it's not returning the correspond.

Thanks a bunch!

1

1 Answers

0
votes

I have finally found the solution!

As I said, response wasn't the right one as it was trying to redirect rathen than return a valid JSON response.

And after going through the Request code, I found out that I need to use also wantsJson(), as ajax() may not be the case always, so I have modified my trait to this:

<?php

namespace Actuame\Exceptions;

trait ExceptionTrait 
{

    public function response(Request $request)
    {
        // Below here, I added $request->wantsJson()
        $type = $request->ajax() || $request->wantsJson() ? 'ajax' : 'redirect';

        return $this->$type($request);
    }

    private function ajax(Request $request)
    {
        return response()->json(array('message' => $this->message), 404);
    }

    private function redirect(Request $request)
    {
        return redirect($this->redirect)->with('error', $this->message);
    }

}