Testing Laravel Cached Routes - laravel

I ran into an issue where Laravel's cached routes were not the same as uncached, so I am attempting to write a unit test which compares the two.
/** #test */
public function cached_and_uncached_are_identical()
{
Artisan::call('route:clear');
Artisan::call('route:list', ['--compact' => true]);
$uncached = Artisan::output();
Artisan::call('route:cache');
Artisan::call('route:list', ['--compact' => true]);
$cached = Artisan::output();
$this->assertSame($cached, $uncached);
}
The call to route:list after route:cache throws a LogicException: "Route is not bound."
I don't get that error when executing those commands on the command line. My searches haven't turned up any good hints for tracking down the issue.
How do I find the issue and fix it?

Related

Why signedRoute is always false on hasValidSignature in Laravel 8.*

I'm trying to add users only by single unique url on register.
The problem is that hasValidSignature() in register function always returns false, no metter if i would go directly from /register or generated url.
My RegisterController:
public function register(Request $request) {
dump($request);
dump($request->_token);
dd($request->hasValidSignature());
abort_unless($request->hasValidSignature(), 403, 'That link has expired or is no longer valid!');
}
My index where I generate unique URL for registration:
public function index()
{
Gate::authorize('admin-level');
$users = User::where('admin', '0')->get();
$url = URL::temporarySignedRoute(
'register',
now()->addMinutes(30)
);
return view('backend/user/index', ['users' => $users], ['url' => $url]);
}
or just generate url:
$url = URL::temporarySignedRoute(
'register',
now()->addMinutes(30)
);
Everything is done just like in documentation, that's why I'm so mad about this. What can I do to make urls good.
Its either something wrong with my hasValidSignature(which I didnt ever change)
or with my URL.
I tried many different methods, always with same result.
Fun fact is that it worked just after implementing. Now, it doesnt.
I remade all auth with php artisan ui:auth. Whole registration works well unless it goes with hasValidSignature.
My users have to register only from unique URL, i cannot bypass that.
Sometimes there are other parameters in the query included...
Therefore you must ignore them:
$request->hasValidSignatureWhileIgnoring(['param1', 'paramX'])

Why I receive "CSRF token mismatch" while running tests in laravel?

I want to run my tests without receiving "CSRF token mismatch" exceptions. In the laravel documentation is noted that:
The CSRF middleware is automatically disabled when running tests.
the line of code where the exception is thrown looks like this:
$response = $this->json('POST', route('order.create'), [
'product_id', $product->id
]);
and for running tests I am working in my zsh terminal:
php artisan test --env=testing
This is my test class:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
class SessionCartTest extends TestCase
{
public function testExample()
{
$product = \App\Product::inRandomOrder()->first();
$response = $this->postJson(route('order.insert'), [
'product_id' => $product->id,
]);
$response->assertStatus(200); // here I receive 419
}
}
What am I doing wrong and how could I fix this? I am using laravel 7.
I ran into this problem x times now and each time I fix it by running:
php artisan config:clear
Probably the APP_ENV is not being set to testing.
You can set a ENV variable in the command line by preceding the php command.
So on your case set the environment to testing and run the artisan command by:
APP_ENV=testing php artisan test
Your data array is wrong. Try the following change:
$response = $this->postJson(route('order.insert'), [
'product_id' => $product->id, // use the arrow notation here.
]);
When you are running tests on Docker where the APP_ENV is hard coded with other values than testing (dev, local) in docker-compose.yaml file, phpunit cannot execute tests properly.
You will need to delete the all APP_ENV in docker files.
This works by setting a custom csrf-token
$this
->withSession(['_token' => 'bzz'])
->postJson('/url', ['_token' => 'bzz', 'other' => 'data']);

Laravel 404 Not Found - But Route Exists

Hello im trying to get information about user on my view.
Here is my UserController
public function getUser(Request $request, $id)
{
$user = User::findOrFail($id);
return view('admin.user', ['user' -> $user]);
}
here is my web.php
Route::get('admin/user/{id}', "UsersController#getUser");
and my user view
#extends('admin.layouts.app')
#section('contents')
<h1>User {{ $user }} </h1>
#endsection
I am trying to display user information in this view, like name etc, but im recives 404
Not Found page. What im doing wrong. Im using Laravel 6
404 error may refer to a User not being found, since you have a findOrFail() query. It may have nothing to do with your routes.
Just double check with:
php artisan route:list
just to make sure the route is being registered correctly.
I think you firstly use any prefix for this route.For this it will give you an error.To check route list.
php artisan route:list
it will give you all route.
And Here you don't need (Request $request) because here you just need the id.it not the problem..i give you just this suggestion
public function getUser($id)
{
$user = User::findOrFail($id);
return view('admin.user', ['user'=> $user]);
}
why you use '-> ' you should use '=>'

PHPUnit - post to an existing controller does not return an error

I am new to PHPUnit and TDD. I just upgrade my project from Laravel 5.4 to 5.5 with phpunit 6.5.5 installed . In the learning process, I wrote this test:
/** #test */
public function it_assigns_an_employee_to_a_group() {
$group = factory(Group::class)->create();
$employee = factory(Employee::class)->create();
$this->post(route('employee.manage.group', $employee), [
'groups' => [$group->id]
]);
$this->assertEquals(1, $employee->groups);
}
And I have a defined route in the web.php file that look like this
Route::post('{employee}/manage/groups', 'ManageEmployeeController#group')
->name('employee.manage.group');
I have not yet created the ManageEmployeeController and when I run the test, instead of get an error telling me that the Controller does not exist, I get this error
Failed asserting that null matches expected 1.
How can I solve this issue please?
The exception was automatically handle by Laravel, so I disabled it using
$this->withoutExceptionHandling();
The test method now look like this:
/** #test */
public function it_assigns_an_employee_to_a_group() {
//Disable exception handling
$this->withoutExceptionHandling();
$group = factory(Group::class)->create();
$employee = factory(Employee::class)->create();
$this->post(route('employee.manage.group', $employee), [
'groups' => [$group->id]
]);
$this->assertEquals(1, $employee->groups);
}
You may not have create the method in the Controller but that doesn t mean your test will stop.
The test runs.It makes a call to your endpoint. It returns 404 status because no method in controller found.
And then you make an assertion which will fail since your post request
wasn't successful and no groups were created for your employee.
Just add a status assertion $response->assertStatus(code) or
$response->assetSuccessful()

Laravel dusk reports "General error: 5 database is locked" and "Operation timed out"

I am running the script
namespace Tests\Browser;
use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\RefreshDatabase;
class RegistrationTest extends DuskTestCase
{
use RefreshDatabase;
/** #test */
public function a_user_registers_for_an_account()
{
$this->browse(function (Browser $browser)
{
$browser->visit(route('app-registration-create'))
->type('name', 'John')
->type('lastName', 'Doe')
->type('email', 'john.doe#ps.com')
->type('password', 'password')
->type('password_confirmation', 'password')
->click('#dusk-accept')
->click('#register-button') //
->assertDontSee('The name field is required.');
});
$this->assertDatabaseHas('users', [
'email' => 'john.doe#ps.com',
'verified' => 0
]);
}
/** #test */
public function a_user_confirms_a_email_address()
{
$this->browse(function (Browser $browser)
{
$user = User::where('email', 'john.doe#ps.com')->first();
var_dump(route('app-registration-confirm-email', ['token' => $user->token])); // "http://ps.dev/app/registration/confirm/aPAWN1QlGyl8Id2vXIJU9Fn8G6bsef"
$browser->visit(route('app-registration-confirm-email', ['token' => $user->token]));
});
$this->assertDatabaseHas('users', [
'email' => 'john.doe#ps.com',
'verified' => 1
]);
}
}
and when it hits the line
$browser->visit(route('app-registration-confirm-email', ['token' => $user->token]));
it stops working. The idea behind that step is to verify that the user provided a valid e-mail address. Therefore the application will grab the token from the URL and check if there is a user in the database with that token. If so, set the verified property to 1 and set the token to null.
But I get the following errors:
Inside the laravel.log file I can see:
[2017-10-17 13:24:30] testing.ERROR: SQLSTATE[HY000]: General error: 5
database is locked (SQL: update "users" set "verified" = 1, "token" = ,
"updated_at" = 2017-10-17 13:23:30 where "id" = 1)
On the terminal I can see:
There was 1 error:
1) Tests\Browser\RegistrationTest::a_user_confirms_a_email_address
Facebook\WebDriver\Exception\WebDriverCurlException: Curl error thrown for http GET to /session/856dbb7e7769ec0a369e44e13b6b676d/screenshot
Operation timed out after 30000 milliseconds with 0 bytes received
/home/vagrant/ps/vendor/facebook/webdriver/lib/Remote/HttpCommandExecutor.php:286
/home/vagrant/ps/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:535
/home/vagrant/ps/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:333
/home/vagrant/ps/vendor/laravel/dusk/src/Browser.php:244
/home/vagrant/ps/vendor/laravel/dusk/src/TestCase.php:160
/home/vagrant/ps/vendor/laravel/framework/src/Illuminate/Support/Collection.php:341
/home/vagrant/ps/vendor/laravel/dusk/src/TestCase.php:161
/home/vagrant/ps/vendor/laravel/dusk/src/TestCase.php:94
/home/vagrant/ps/tests/Browser/RegistrationTest.php:51
Maybe I don't apply dusk properly, but I couldn't find a solution on the web.
This is a already somewhat old question but I found a solution to this problem when having it myself.
The problem was that the connection was not closed between tests. My tests would work if i would call only 1 at a time but running a batch of tests would throw the database locked error.
The solution was that I was missing the parent::tearDown(); in my own teardown function. This means connections are not closed in between tests.
For the question that was asked there is most likely a tearDown function in the DuskTestCase or in another test without the parent::tearDown(); in there. Check this out and you should be able to find the problem somewhere.
TLDR: Check your tearDown functions and make sure they contain the parent::tearDown();. Otherwise after a test the connection will not be closed.
In my case, i was using this line of code
Artisan::call('migrate');
in my setUp() method and this below in my tearDown() method
Artisan::call('migrate:rollback');
parent::tearDown();
I had to comment them out. Apparently the database connections are not closed in between tests and RefreshDatabase trait already takes care of this.

Resources