Laravel test if the response contains errors? - php

I'm working on a legacy code and trying to use tests to cover the code for later refactoring. In one controller there's a piece of code like this:
return redirect()->route('login')->withErrors(['invalid credentials']);
Here are my assertions for the test:
$response->assertRedirect(route('login'));
$response->assertSessionHasErrors([
0 => 'invalid credentials'
]);
But the problem is I get the following output:
Session missing error: 'invalid credentials'
Failed asserting that false is true.
Any idea how can I get this done?

Looking at the source code of assertSessionHasErrors() I think it cannot be done with your use case. The problem is the unnamed array in your withErrors(...) method. I see two options for you:
Change your legacy application into:
return redirect()->route('login')->withErrors(['error' => 'invalid credentials']);
Afterwards you can run your test like so:
$response->assertRedirect(route('login'));
$response->assertSessionHasErrors([
'error' => 'invalid credentials'
]);
If you cannot change your legacy application you could use this:
$response->assertRedirect(route('login'));
$this->assertEquals(session('errors')->getBag('default')->first(),'invalid credentials');

Related

Cannot test validation errors in Lumen

When i try to validate controller response using one of the available assertions like assertJsonValidationErrors it gives the following error:
Failed to find a validation error in the response for key: 'name'
Here is my test:
Mesh::factory()->create(['name'=>'test']);
$this->post(route('meshes.store', ['name' => 'test']));
$this->response->assertUnprocessable()->assertJsonValidationErrors('name');
Validation response format in Lumen is different than Laravel which wraps the errors in errors property.
Simply pass null to the second parameter of assertJsonValidationErrors or any other methods available for validation assertion which has this parameter and you should be fine:
$this->response->assertUnprocessable()->assertJsonValidationErrors('name', null);

Class session not found while not using session

The problem is that I'm reciving Class 'session' not found error.
But the funny fact is that I'm not using session class. Anyway I'm using session namespace use Session;. I've found out that the problem occurs when I'm returning view.
If I return simple string or number it works, but when I use
return view('catering.prices')->with(['name' => 'Victoria']);
or
return view('greetings', ['name' => 'Victoria']);
I'm reciving the error.
Log:
[2016-10-06 11:38:54] local.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Class 'session' not found' in D:\app\storage\framework\views\397c6d5694d7a10e04cabd271a3359cfd11a387e.php:16
Update
I'm seeing that it's not returning new views - I have now about 40 views. The old one are working well but when I create new views I'm reciving the error.
Answer
The problem was wrongly set permissions for specific user in my database. Thank you for your effort.
Anybody has some idea?
Try like this,
return view('catering.prices',['name'=> 'Victoria']);
OR
return view('catering.prices')->with('name', 'Victoria');
check here : https://laravel.com/docs/5.2/views

Laravel: Ignore 412 error page

There's must be a very simple solution to this but I had no idea how to search for this in Google or Stackoverflow for that matter so, yeah, I did not find anything so far.
I've written a simple API route in Lumen that returns a json string containing 421 on validation fail:
{ "code": 412, "status": "error", "data": "validation failed" }
Now I wanted to call that route in another Laravel project, but then instead of the JSON string from the API I get an enormous error page saying:
Client error: POST
http://www.serellyn.net/development/game_api/public/platforms
resulted in a 412 Precondition Failed response:
{"code":412,"status":"error","data":"validation failed"}
I do think this is pretty normal behaviour since Laravel is seeing a error on its response. But all I want to do is receive my own json string with the 412 error code and be able to continue using my webpage.
How can I solve this problem?
Thank you in advance.
Edit: Forgot to add some code. I use Guzzle to call my API.
$client = new Client(['base_uri' => 'http://www.serellyn.net/development/game_api/public/', 'auth' => array('dev', '<dev>2016')]);
$res = $client->request('POST', 'platforms', array('form_params' => ['name' => $request->name]));
if($res->getStatusCode() == 201) {
Session::flash('success', $request->name . ' successfully added');
} else {
}
return redirect()->route('platforms.add.get');
I think the response is correct. What I would do is catch the error in the try-catch block and then continue how I would like.
the problem is that Guzzle thrown exception for 400 level errors if the http_errors request option is set to true. (which is the default value)
you need to put 'http_errors' => false in the request like:
$client->request('POST', 'platforms', array('http_errors' => false,'form_params' => ['name' => $request->name])); if($res->getStatusCode() == 201) {
http_errors docs
Had the same issue but with a website and I simply rewrote my mod_security module on the apache server, and it worked well with ssl again. You can read more here

Testing Exceptions in PHPUnit

I am new to unit testing and now trying to write some test cases using PHPUnit for a Laravel application. I have done one basic test which is like the following :
public function testGetPointsByApp()
{
$this
->json(
'GET',
self::URL.'/'.$value
)
->assertResponseStatus(200)
->seeJson([
'status' => 'success',
])
->seeJsonStructure([
'status',
'message',
'data' => []
]);
}
Now this is working. But I would like to know how can I test for invalid inputs and for the cases like there is not data at all with the given parameters. I am throwing corresponding exceptions in each of these cases and it will add particular messages. How can I test whether it is thrown ?
I don't want to include it to this method and would like to write some other methods to test different scenarios in the API like invalid UUID, no data etc. So for each time, I need to call the API url or this call can be done from any kind of set up function ?
I don't know laravel but in PHPUNIT you can test if exception is thrown with expectException function. For example for InvalidArgumentException
$this->expectException(InvalidArgumentException::class);
You can also use annotation #expectedException and there are also a lot of things that can be tested in exception like expectExceptionCode() etc.
More you can find here
Since you're not doing an Unit test (this kind of test you're doing is an acceptance test), you cannot check for the exception it self, you will look for a bad response:
$this
->json(
'GET',
self::URL.'/'.$BAD_VALUE
)
->assertResponseStatus(422)
->seeJson([
/* Whatever you want to receive at invalid request */
])
->seeJsonStructure([
/* Whatever you want to receive at invalid request */
]);
Laravel validation errors returns 422 - unprocessable entity HTTP code.
You can check the response also for your expected error messages or something else.

Laravel 4 always returns HTTP status code 200

I have below code in error.php, which is triggered using App::abort(404, $error) in my controller. Still my response status code is 200(ok). I tried with various error codes like 400, 403
// NotFoundException handler
App::error(function(NotFoundException $e)
{
$default_message = 'The requested resource was not found';
return Response::json(array(
'error' => $e->getMessage() ?: $default_message,
), 404);
});
For anyone still googling this problem:
I was struggling with this problem for hours. For me the problem was caused by an issue with one of my controllers.
Check all of your controllers and make sure there are no spaces in front of the <?php tag. The <?php tag should be the very first thing in the file. A single space in front of the <?php tag in any of your controllers that are routed as such:
Route::controller('example', 'ExampleController');
Will cause all status codes to be 200.
I believe, regardless, you should receive a 404 response, so there might be something else happening that's the result of code not included in your question.
That being said, the Exception class that is thrown for 404 is NotFoundHttpException rather than NotFoundException.
Since Laravel 4 uses Symfony's HttpKernal, that Exception is here.
You can see here where App::abort() throws NotFoundHttpException when a 404 is triggered.
Therefore, your code should look like:
// NotFoundHttpException handler
App::error(function(\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e)
{
$default_message = 'The requested resource was not found';
return Response::json(array(
'error' => $e->getMessage() ?: $default_message,
), 404);
});
Important: This will only fire for a 404 status, as that's the corresponding code to NotFoundHttpException. Other status codes return other Exception classes. To capture all HTTP status error codes exceptions, type hint for HttpException like so:
// HttpException handler
App::error(function(\Symfony\Component\HttpKernel\Exception\HttpException $e)
{
return Response::json(array(
'error' => $e->getMessage(),
), $e-> getStatusCode());
});
Lastly, consider using a bit of Content Negotiation when deciding to return JSON or HTML.
The solution didn't worked for me, so in case anyone is still looking for an answer, I thought it be best to put it here instead of creating another question.
After some time I had this problem too, in my app/Exceptions/Handler.php I had:
if ($e instanceof ModelNotFoundException) {
if ($request->ajax()) {
return response()
->json(['error' => ['No results']])
->header('status', 422);
}
}
This worked in my local environment, however, in the homolog environment (which reproduces the production environment, just to be clear) it didn't returned the correct status code.
After another look I started looking at Laravel's docs, and I changed the call to the following:
return response()
->json(['error' => ['No results.']], 422);
And that did the trick. Hope this can help.
In my case I found some space in front of <?php
Remove dump & other print functions
I was actively debugging when I noticed this issue. It was caused because I had dump(...) calls in the code at that time.
When I removed all my debug dump calls, the status code was correctly 404 again (using abort(404).

Categories