I'm using Laravel Lumen 8.0. And building the Unit Tests for the endpoints. But got pretty fast stuck.
<?php
class ExampleTest extends TestCase
{
public function testShouldReturnAllUsers(){
$parameters = [
'first_name' => 'First_name',
'last_name' => 'TestUser',
'locale' => 'nl',
'email' => 'First_name#test'.rand(0,11111111111).'com',
'password' => 'asdasfasfgasgrresdfsgrwe'
];
//$this->json('post', 'users', $parameters)
// ->seeStatusCode(200);
$this->get('/users/b11d4d56-00ff-4af8-84c2-f1a14c8724c7');
$this->seeStatusCode(200);
}
}
There was 1 failure:
1) ExampleTest::testShouldReturnAllUsers
Expected status code 200 but received 404.
Failed asserting that 200 is identical to 404.
/Users/Sites/App/Services/users/vendor/illuminate/testing/TestResponse.php:186
/Users/Sites/App/Services/users/vendor/laravel/lumen-framework/src/Testing/Concerns/MakesHttpRequests.php:426
/Users/Sites/App/Services/users/vendor/laravel/lumen-framework/src/Testing/Concerns/MakesHttpRequests.php:437
/Users/Sites/App/Services/users/tests/ExampleTest.php:19
Going through endless questions here on SO. The answer has always been te same, check your APP_URL in the .env file and ensure that this is accessible and the it represents the actual URL of the application.
I check this 100 times and it is the actual URL and accessing this in the browser works.
How to move forward? Can I see where the request was pointed to?
Related
I was working on a register page for an application. And everything works fine, except for this one small bit.
Whenever something doesn't match these requirements that I have in a custom http request it just throws an 422 error.
public function rules()
{
return [
'first_name' => 'required|string|max:255',
'middle_name' => 'nullable|string|max:255',
'last_name' => 'required|string|max:255',
'email' => 'required|email|unique:user|max:255',
'password' => 'required|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*#?&])[A-Za-z\d#$!%*#?&]{8,}$/',
];
}
My question is, how can I send it the error to my front-end, so I can display it for the user?
Some additional info that may be important:
using Laravel 9
using Axios
using Vuejs
Thanks to everyone who is taking their time to read this!
in request you can add custome message using
public fucntion message(){
"name.required" => "Name is required.",
//like this for each validation you will get different message which you can apply on page
}
I am using PHPUnit with Laravel 5 to functionally test my API endpoints.
I noticed my tests are very slow when my laptop is connect to the internet! So I thought it could be the DNS lookup causing this delay.
I required PHPUnit Bridge to Mock the DNS but I don't know what to pass in the parameter inorder to mock my API's subdomain api.insa.dev due to the lack of documentaion.
That's what I have so far in my TestCase Class setUp() function:
\Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts([
'insa.dev' => [
[
'ip' => '127.0.0.1',
// ... ?!?!?
],
],
]);
I think to get this working, first of all you need to call the register method on the DnsMock class.
\Symfony\Bridge\PhpUnit\DnsMock::register(App\ClassBeingTested::class);
Then, to mock the subdomain, you just put it straight in the mocked hosts:
\Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts([
'api.insa.dev' => [
[
'ip' => '127.0.0.1',
// ... ?!?!?
],
],
]);
I am testing POSTing data to an API endpoint we've created using Laravel 5.2, but none of the parameters seem to be reaching the application in the test. The endpoint expects json and responds with json and uses a FormRequestValidator which has required rules for active and make parameters. The test fails with status code 422 and the examining the response body it states the active and make parameters are required even though they are being passed in the call so therefore for some reason when the request reaches the the Form Request Validator, the input is not there.
However, when I invoke the endpoint with json body including make and active from Postman or the UI app we've built it works fine, it is only failing in the PHPUnit tests therefore it must be something with PHPUnit or the test setup being incorrect. Here is the test:
public function testItStoresCars()
{
// Arrange
$user = User::first();
//Act
$this->json(Request::METHOD_POST, '/v1/cars', [
'active' => true,
'make' => 'Audi'
],
['Authorization' => 'Bearer '.\JWT::fromUser($user)]));
// Assert
$this->assertResponseOk();
}
I know the Authorisation header is set correctly from other tests passing.
I've tried disabling middleware, using the $this->post helper method and manually setting the headers as well as using the $this->call method with setting the Headers and encoding the data using json_encode but I always get the same 422 response. I'm wondering has anyone encountered this issue or can see an error?
Controller Code
public function store(CreateCarRequest $request)
{
$car = $this->carRepo->save($request->all());
return response()->json(car);
}
FormRequest
class CreateCarRequest extends Request
{
public function rules()
{
return [
'active' => 'required|boolean',
'make' => 'required',
];
}
}
422 is the error response for validation errors.. which means either your data is not posted or it doesn't pass server validation, try
$this->json(Request::METHOD_POST, '/v1/cars', [
'active' => true,
'make' => 'Audi'
],
['Authorization' => 'Bearer '.\JWT::fromUser($user)]))->dump();
dump() should show you the errors
I have an application stack in Laravel that we're going to go ahead and switch to a SaaS model. In order to do this, I just assumed I could wrap all my routes in a group with dynamic domain properties, fire a filter, and then observe the $route parameters to make this occur.
I should note that this is actually a Multi-Tenancy application but we've actually decided to separate the databases out for this one.
So here we go:
In my routes.php file, I've got the following:
Route::group(array('domain' => '{domain}.{tld}', 'before' => 'database.setup'), function()
{
Route::group(array('prefix' => 'backend', 'before' => 'auth'), function () {
//all of my routes
});
});
As you can see from the above, when any route is requested, it's going to the database.setup filter that I've got defined in filters.php:
Route::filter('database.setup', function($route, $request){
$domain = $route->getParameter('domain').'.'.$route->getParameter('tld');
$details = DB::table('my_table')->where('domain', '=', $domain)->first();
if($details){
Config::set('database.connections.account', [
'driver' => 'mysql',
'host' => 'my_host',
'database' => Encryption::decrypt($details->db_hash, 'my_salt'),
'username' => 'my_username',
'password' => 'my_password',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'charset' => 'utf8',
]);
//these are things I was doing to get the URL-permalink working.
Config::set('app.url', 'http://' . $domain);
Config::set('app.domain', $domain);
Config::set('session.domain', '.' . $domain);
//This actually works exactly as I've intended
Config::set('database.connections.default', 'account');
DB::setDefaultConnection('account');
}
});
Now initially I thought this was working fine. The correct record was pulled from the table, and the database switched on the fly without issue while destroying the previous instance. Great.
However, I noticed that I've lost all of my model binding relationships in the routes.
A route such as this:
Route::get('/shipping/packages/{package}', 'PackageController#get');
With a model defined as such:
Route::model('package', 'Package');
Unfortunately always results in this:
No query results for model [Package].
Now, if I remove my filter from the Route, everything works fine, but the default database will be used a big nono for my application.
Lastly, all of the permalink structure seems to be completely broken. Instead of seeing my domain when I hover over a link, such as:
http://example.com/shipping/packages/package
I instead see:
%7Bdomain%7D.%7Btld%7D/shipping/packages/package
I have no idea why this is occurring.
I've tried overloading the response object, altering the settings for the site Configuration within the filter, and a host of other things, but I always end up having the same issue in some way or another.
I'd be greatly appreciative if anyone has any clue's on how to solve this issue.
Okay, I've figured out what the issue is.
I've apparently not read over the documentation well enough. If you walk through the router group call it will eventually invoke mergeGroup(), which in this particular function, you can observe the following code:
$new['where'] = array_merge(array_get($old, 'where', []), array_get($new, 'where', []));
Here, we can see that they're just using a stack to keep track of these values, so the literal interpretation of {domain}.{tld} was being pushed onto the stack.
This was working fine initially because my filter actually grabs them explicitly:
$domain = $route->getParameter('domain').'.'.$route->getParameter('tld');
To resolve this, I just needed to create my own helper function that would grab the $host (this is an extremely rudimentary implementation, but should help for clarity)
$domain = get_domain();
Route::group(array('domain' => $domain, 'before' => 'database.setup'), function()
Then in my helpers file, I've added the get_domain() function:
if ( ! function_exists('get_domain'))
{
function get_domain()
{
$url_parts = parse_url(Request::root());
return $url_parts['host'];
}
}
Then I can simply call get_domain() in my filter as well and it'll always be in sync:
Route::filter('database.setup', function($route, $request){
$domain = get_domain();
This works perfectly now.
So I am working with a Laravel 5 installation and like a good programmer I am trying to get the validation logic out of my controller using the new Form Requests feature in Laravel.
So I went ahead and created a form request called CreateTenantRequest like so:
php artisan make:request CreateTenantRequest
By default it returns a false in the authorize method and it works correctly. If I fire a request, it says forbidden. But then I updated the rules and I set the authorize method to true and now when I fire the same request from Postman, it says:
NotFoundHttpException in RouteCollection.php line 161:
Which is ridiculous because when I change it to false, it returns forbidden fine?
What am I missing or doing wrong?
And although this wouldn't matter I guess but my rules array is as follows:
return [
// Tenant details
'name' => 'required|max:255',
'username' => 'required|max:255|unique:tenant',
// Tenant Admin details
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email|max:255',
'password' => 'required|confirmed|min:6',
];
Routes file:
<?php
Route::group(['prefix' => 'api'], function(){
Route::post('authenticate', 'Auth\AuthController#authenticate');
// SuperAdmin Group
Route::group(['namespace' => 'Archive', 'middleware' => 'superadmin'], function(){
Route::resource('tenants', 'TenantController');
Route::get('tenants/{id}/users', 'TenantController#showUsersForTenant');
});
// Tenant Group
Route::group(['namespace' => 'Tenant'], function(){
Route::resource('roles', 'RoleController');
Route::resource('users', 'UserController');
});
// Remove before production
// Only for testing purposes
Route::get('test', function(){
// return JWTAuth::parseToken()->getPayload()->get('username');
});
});
So after a bid discussion with shock_gone_wild, I realized that the request was not ajax and hence laravel was rerouting to the a url with the errors in session.
I was testing the API with Postman REST client and by default it sends basic HTTP requests but when a header is added like so:
X-Requested-With:XMLHttpRequest
It makes the request Ajax and then laravel checks to see if it is indeed ajax, so instead of routing to a url, it gave back the validation errors in JSON.
So anytime if anyone is creating a decoupled web service and trying to test it using Postman, do it with the header so that you can simulate actual ajax requests at your application.