Cannot debug Laravel HTTP Tests - php

I have a couple of HTTP tests in a Laravel 5.6 project. I would like to debug the tests and the codepath they call. I can debug the test method but not the actual code. Meaning the debugger doesn't stop at breakpoints in the controller etc.
I'm using Xdebug 2.6.0, PhpStorm 2018.1 and PHP 7.2.

It turns out that the 500 error code came from one of the custom middleware layers and not from the controller. So the breakpoint never got hit because of the error in the middleware layer. I wish that there was an error stack trace instead of only the message "Expected status code 200 but received 500".
I ended up mocking the middleware. Just in case someone is interested how I did it:
$mockMiddleware = Mockery::mock("App\Http\Middleware\MyMiddleware");
$mockMiddleware->shouldReceive("handle")->once()
->andReturnUsing(function ($request, $next) {
return $next($request);
});
App::instance("App\Http\Middleware\MyMiddleware", $mockMiddleware);

Related

Laravel 8.x returns status code 200 instead of 404 when throwing NotFoundHttpException

After upgrading to Laravel 8.9 from 7.x, Laravel returns the wrong status code when requesting a non existing model. The response body itself contains the expected error response, however the status code is 200. Here is the corresponding controller code:
public function findOne($eventId)
{
$event = Event::withMailRecords()->withContacts()->withContingents()->findOrFail($eventId);
return new EventResource($event);
}
I only get the wrong status code when starting the server using php artisan serve and then execute our frontend tests to query the server. Within our Laravel HTTP tests, everything works fine. Moreover, the issue only appears within our bitbucket ci pipeline. Locally everything works fine, even when executing the tests within our pipeline image.
I cannot see any environment differences that could possibly result in this behavior.
Maybe this is not the source of your problem, but are you sure there is no space before any "<?php" tag or that you are not using encoding like UTF8 with BOM that would have already sent headers ?

Slim 4 error handling not catching base Exception

For some reason, my Slim 4 application error handler did not catch errors which can be caught by \Exception and I see 502 bad gateway error in the browser , here is my ErrorMiddleware configuration (I'm using PHP-DI to configure it ):
$definitions[ErrorMiddleware::class] = static function(ContainerInterface $container): ErrorMiddleware {
$middleware = new ErrorMiddleware(
$container->get(CallableResolverInterface::class),
$container->get(ResponseFactoryInterface::class),
(bool)$container->get(Config::class)->get('main.debug'), //false or true
true,
true
);
$middleware->setErrorHandler(HttpNotFoundException::class, $container->get(NotFoundHandler::class));
return $middleware;
};
I tried to add handler to handle 500 error like this $middleware->setErrorHandler(HttpInternalServerErrorException::class, $container->get(NotFoundHandler::class) );
but it's not working and I still see 502 bad gateway until I surround all controller action with try/catch(\Exception $e).
Do I need to add some other error handlers?? It's not clear for me how to correctly setup up handling in a slim 4 application.
Updated: I found that slim ErrorMiddleware by default catching slim HttpException which is extending Exception, but why not direclty Exception or even Throwable to gracefully exit application with nice error page
Okay it's my bad, adn everithing is fine with a slim, it's failing in the 'log_error()' fucntion as ErrorMiddlware is configured to log the error, but I did not install and configure Monolog yet, so it write logs to php-fpm logs and nginx alongside throwing 502 error

`php artisan down` throws uncaught 503 and yields an error page

Edit: Accepted Issue on GitHub https://github.com/octobercms/october/issues/2830
I am using OctoberCMS which is based upon the Laravel PHP framework.
(I am a newbie to both).
Ultimately, I'm trying to script as much of the site update process as possible. That is, update/upgrade the testing and live sites and upload my new code. This entails being able to put the site into maintenance mode from the command line.
The top level directory for my website (/var/www/website/) contains the artisan php script.
Running php artisan list I get:
Available commands:
down Put the application into maintenance mode
up Bring the application out of maintenance mode
Within the OctoberCMS backend I can put the frontend into maintenance mode, and the chosen maintenance page is shown as expected.
When I enter php artisan down in the console I get Application is now in maintenance mode., as expected. But when I reload the website, I get the following error:
We're sorry, but an unhandled error occurred. Please see the details below.
.../vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php line 41
Type: Undefined
Exception: Symfony\Component\HttpKernel\Exception\HttpException
\*
\* #throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance()) {
throw new HttpException(503);
}
return $next($request);
}
It would appear that Laravel/Symfony is doing what it should and throwing a 503 Service Unavailable, but there is nothing to catch it and render the maintenance page.
So, two questions
1) Is this a bug? If so, in Laravel or October? Or have I done something wrong -- config setting...?
2) Assuming it won't be 'fixed' any time soon, how and where should I catch the HttpException(503) and yield the maintenance page?
There is what might be an answer in Stackoverflow > '503 can't be overridden in L5.1', which appears to suggest editing/overriding public function handle($request, Closure $next) with a try/catch/return-if-503 sequence. But is it a good idea to override a function of the CMS/framework? If so, how and where?
I have read OctoberCMS > docs > services > Errors & Logging and, despite hoping for an easier solution, I would create a Plugin to solve the problem if that is the best/only/ideal way. Although creating a Plugin to catch what should surely already be caught seems overkill.
This looks to be the way to do it Laravel - Pass arguments to php artisan down, but I'm not confident to attempt it.
Turnkey LAMP 14.1 server
October system build 414
php --version
PHP 5.6.30-0+deb8u1 (cli) (built: Feb 8 2017 08:50:21)
php artisan --version
Laravel Framework version 5.1.46 (LTS)

How to use Codeception to test laravel 5 APIs?

I am new to Codeception and I am trying to test my web service which I have built using Laravel 5. I am following the guide here.
So I created a suite called api first:
codecept generate:suite api
api.suite.yml
class_name: ApiTester
modules:
enabled:
- REST:
url: http://localhost:8000/api/
depends: Laravel5
AuthenticateUserCept.php
<?php
$I = new ApiTester($scenario);
$I->wantTo('authenticate a user');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST('/authenticate', [
'username' => 'archive',
'email' => 'admin#admin.com',
'password' => 'password'
]);
$I->seeResponseCodeIs(200);
$I->seeResponseIsJson();
I have already tried this using Postman and it runs fine. The /authenticate route takes the 3 parameters and spits out a JWT token happily but I cannot make it work with Codeception.
1) Failed to authenticate a user in AuthenticateUserCept (tests/api//AuthenticateUserCept.php)
Step I see response code is 200
Fail Failed asserting that 500 matches expected 200.
Scenario Steps:
3. $I->seeResponseCodeIs(200)
2. $I->sendPOST("/authenticate",{"username":"archive","email":"admin#admin.com","password":"password"})
1. $I->haveHttpHeader("Content-Type","application/x-www-form-urlencoded")
Where am I going wrong? And moreover it is still blurry to me that how do I refactor this particular test in order to have a JWT for other requests that I make. Any help is appreciated.
EDIT changes in api.suite.yml
class_name: ApiTester
modules:
enabled:
- REST:
url: http://localhost:8000/api/
depends: Laravel5
config:
Laravel5:
environment_file: .env.testing
Before I answer, some comments:
on the enabled line in api.suite.yml I include: enabled: [PhpBrowser, REST, ApiHelper, Asserts].
The url in the REST line doesn't make any difference for the API suite, it's usually only used for the acceptance suite. This should be doing everything via the routes directly into your code instead of using phpbrowser mode or similar where it's making HTTP calls.
Instead of using the PhpBrowser mode you can use the Laravel5 mode -- the former will send requests through the middleware, the Laravel5 mode won't put requests through the middleware if the APP_ENV is set to testing.
In terms of how to fix this, I would start by trying to figure out what the code is doing to spit out the 500 error. One thing that you might do is try to insert some debug/log lines in your code. Another thing is to put in a line like this into the test case:
$I->seeResponseContains('blablabla');
Of course that will fail, but it will produce an output in the tests/_output directory so that you can see exactly what response your code gave back along with the 500 error (of course you need to do this the step before testing for the 200 condition, otherwise your test will bail out at that step).
One common cause of this type of error in test cases is validation applied to a custom Request class that's passed in to your controller method. If that validation fails then the controller method doesn't get hit and you will get a 500 error without being able to debug it in the controller. I consider custom Request classes of this type to be a bad idea.
Another possible line of enquiry is to build a functional test that tests the same route. Functional tests via the Laravel5 helper module are usually easier to get working and get debugged. Once you have a basic functional test in place and resolve any problems that you hit getting that going then it's easier to get the API tests working.

Magento admin category page fails on PHP 5.4

I have a Magento 1.6.2 site hosted on 1&1. Because of certain installed extensions I must have support for PHP version 5.3, but sadly the available options with 1&1 are PHP 5.2 or something they call PHP Dev. A quick phpinfo() shows that this is in fact PHP 5.4.
My problem is that when I'm set to 5.4, the Categories page of the backend throws a 500 error. Rolling back to 5.2 fixes the issue, but that breaks my product pages. In the short term I can handle having to swap between them, but this is obviously unacceptable for a long-term solution when the site is handed to the client.
Can anyone suggest where this incompatibility might lie, and what steps I might take to fix it? My biggest impediment is that the hosting is on a shared server, and so I am not allowed to look at the Apache logs.
Update:
As per CCBlackburn's suggestion in the comments, I have tried to track the point that the error originates from, but I have to admit that I don't really understand the results I'm getting. The URL of the categories page looks like this:
example.com/index.php/admin/catalog_category/index/key/blahblah
I presumed that Mage_Adminhtml_CatalogController would be the place to start looking, but a Mage::log() call as the first line in indexAction() failed to write to the log.
I decided to move up the inheritance and cut into the constructor, and so added the following to Mage_Adminhtml_Controller_Action:
function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array()) {
Mage::log('construct pre');
parent::__construct($request,$response,$invokeArgs);
Mage::log('construct post');
}
This was better, as the first log call wrote to the file, but the second did not.
Next I moved up the inheritance again, and modified the constructor of Mage_Core_Controller_Varien_Action as follows:
public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
{
Mage::log('request: '.$request);
$this->_request = $request;
Mage::log('response: '.$response);
$this->_response= $response;
Mage::log('pre set action');
Mage::app()->getFrontController()->setAction($this);
Mage::log('post set action');
$this->_construct();
}
The problem is that none of these log calls do anything. This has me stumped, as surely calling parent::__construct(); from Mage_Adminhtml_Controller_Action should execute at least one more log call before it does anything. Unless the issue exists with the incoming values, but I don't know how I can check/debug that?
I have faced the same problem under OSX Lion in Google Chrome and Apple Safari with Magento 1.7 and PHP 5.4. Suddenly Magento Category admin started giving 500 Errors and I had no clue what was happening. It seems it's a problem with PHP 5.4. At first I thought it was XDebug causing this error. Then I disabled XDebug and the problem was still there. It is weirder than weird that it works with Firefox!
My solution was to downgrade to the latest PHP 5.3, however this has now been fixed as of PHP 5.4.3.

Categories