419 Page Expired with Laravel Octane, Sail, Sanctum and Dusk - laravel

After migration to Laravel Octane, the dusk tests fails with 419 Page Expired. Before the migration, everything was fine...
I made the following change to the name file docker/8.1/supervisord.conf
-command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan octane:start --server=swoole --host=0.0.0.0 --port=80
+command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80
Laravel Version: 8.82.0
Laravel Sanctum: 2.14.0
Octane Version: 1.2.0
Dusk Version: 6.22.0
PHP Version: 8.1.1
Database Driver & Version: MySQL 8
OS: macOS 12.2
My part of .env.local.dusk file:
APP_ENV=local
OCTANE_SERVER=swoole
BROADCAST_DRIVER=pusher
CACHE_DRIVER=memcached
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=redis
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_DOMAIN=laravel.test
My the dusk test:
$this->browse(function (Browser $browser) use ($user) {
$browser
->visit(new Login())
->loginUser($user->email, 'password')
->assertSee('Dashboard')
->assertPathIs('/dashboard')
->assertAuthenticatedAs($user)
;
});
class Login extends Page
{
public function loginUser(Browser $browser, string $email, string $password)
{
$browser
->type('#email', $email)
->type('#password', $password)
->press('#button')
;
}
}
Regards! :)

I solved. A small change to the .env.dusk.local file helped:
from:
SESSION_DRIVER=array
to:
SESSION_DRIVER=file
and adding to the tests/DuskTestCase.php file:
'--enable-file-cookies',
diff:
$options = (new ChromeOptions())->addArguments(collect([
'--window-size=1920,1080',
+ '--enable-file-cookies',
])->unless($this->hasHeadlessDisabled(), function ($items) {

Related

Laravel Lumen function env() returns null sometimes

I am developing api with Lumen 6.2.0 which gets GET request with certain parameters and token. When it gets parameters it process it in a certain way and then encode with a secret key which is in my .env file and then compares result with the token which was provided with the request, if comparison result is true then user is authenticated else he is not. So the problem is sometimes env() function returns null. It doesn't happen pretty often, just like 1 request out of 15, but it's still a serious problem for me.
I googled a lot but found just few approaches. Firstly I found out that env() function should be only invoked in config file and since Lumen doesn't have a config directory and config files I have created it, but the issue remains the same. The second advice was for Laravel specifically - php artisan config:clear and php artisan config:cache but Lumen doesn't have such commands, although I ran the php artisan cache:clear command to no avail. So here is my code:
.env file
APP_NAME=Example
APP_ENV=local
APP_KEY=ApPkEyHeRe
APP_DEBUG=true
APP_URL=https://example.com
APP_TIMEZONE=UTC
LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=dbname
DB_USERNAME=dbuser
DB_PASSWORD=dbpass
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
VK_APP_SECRET=SoMeFaNcYkEy
config/config.php
<?php
return [
'vk_app_secret' => env('VK_APP_SECRET'),
'events_per_page' => 16
];
And UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class UsersController extends Controller
{
public function check(Request $request) {
$query_params = $request->all();
$sign_params = [];
foreach ($query_params as $name => $value) {
if (strpos($name, 'vk_') !== 0) {
continue;
}
$sign_params[$name] = $value;
}
ksort($sign_params);
$sign_params_query = http_build_query($sign_params);
$secret = config('config.vk_app_secret');
$hash_hmac = hash_hmac('sha256', $sign_params_query, $secret, true);
$base_encode = base64_encode($hash_hmac);
$trim_chars = strtr($base_encode, '+/', '-_');
$sign = rtrim($trim_chars, '=');
$status = $sign === $query_params['sign'];
return json_encode($status);
}
}
I also logged every line of this algorithm, and noticed an interesting thing, the failing case contains [date] production.INFO: prefix before log's rows, and every successful case [date] local.INFO: So maybe it's affecting env() function somehow? I also don't get it why it sometimes logged as production when I have APP_ENV=local

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 Dusk 2.0 / Laravel 5.5 returns an empty page

I'm in the midst of upgrading my Laravel 5.3 website to 5.5 and unable to get Dusk working properly against my localhost. I have other unit tests working properly against my localhost but for some reason, Dusk returns "<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body></body></html>" for any local page. Local pages seem to work fine browsing it on my desktop.
My DuskTestCase
protected function driver()
{
$options = (new ChromeOptions)->addArguments([
'--disable-gpu',
'--headless',
'--no-sandbox',
'--ignore-certificate-errors'
]);
return RemoteWebDriver::create(
'http://localhost:9515',
DesiredCapabilities::chrome()
->setCapability(WebDriverCapabilityType::ACCEPT_SSL_CERTS, true)
->setCapability('acceptInsecureCerts', true)
->setCapability(
ChromeOptions::CAPABILITY, $options
)
);
}
My Sample Test
public function testBasicExample()
{
$this->browse(function (Browser $browser) {
$result = $browser->visit('http://localhost');
$browser->screenshot('test');
$browser->dump();
});
}
chrome driver works fine calling google.com and dumps content
hardcoded the url to localhost for testing
page is http not https
tried php artisan serve before calling test, same result
tried cache / config clear
created an .env.dusk.local file, didn't seem to affect it
chromedriver -v is ChromeDriver 2.44.609551
tried 127.0.0.1 no dice
The only way I could make it working:
public function testBasicExample()
{
$this->browse(function (Browser $browser) {
$browser->visit(env('APP_URL').'/home')
->assertSee('Laravel');
});
}

Laravel dusk chrome driver timeout

Can anyone help, I am unable to get Laravel dusk to run the default sample test in my current Laravel 5.6 project on mac high sierra.
Error message
Time: 2.5 minutes, Memory: 14.00MB
There was 1 error:
1) Tests\Browser\ExampleTest::testBasicExample
Facebook\WebDriver\Exception\WebDriverCurlException: Curl error thrown for http POST to /session with params: {"desiredCapabilities":{"browserName":"chrome","platform":"ANY","chromeOptions":{"binary":"/Users/keith/Desktop/dusk/vendor/laravel/dusk/bin/chromedriver-mac","args":["--disable-gpu"]}}}
Operation timed out after 30002 milliseconds with 0 bytes received
/Users/keith/Desktop/dusk/vendor/facebook/webdriver/lib/Remote/HttpCommandExecutor.php:286
/Users/keith/Desktop/dusk/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:126
/Users/keith/Desktop/dusk/tests/DuskTestCase.php:40
/Users/keith/Desktop/dusk/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:189
/Users/keith/Desktop/dusk/vendor/laravel/framework/src/Illuminate/Support/helpers.php:770
/Users/keith/Desktop/dusk/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:190
/Users/keith/Desktop/dusk/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:92
/Users/keith/Desktop/dusk/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:64
/Users/keith/Desktop/dusk/tests/Browser/ExampleTest.php:21
I have already done the following :
added the following to app\Providers\AppServiceProvider.php
use Laravel\Dusk\DuskServiceProvider;
...
public function register()
{
if ($this->app->environment('local', 'testing')) {
$this->app->register(DuskServiceProvider::class);
}
}
ran 'php artisan dusk:install' in terminal
set App_URL in .env to http://localhost:8000
specified the location of chromedriver in DuskTestCase
start 'php artisan serve' before running 'php artisan dusk'
Repository : https://github.com/KKOA/dusk
If your function extends from DuskTestCase.php, then you need to increase connection_timeout_in_ms.
Do this by changing driver method to the following:
DuskTestCase.php
protected function driver()
{
$options = (new ChromeOptions)->addArguments([
'--disable-gpu',
'--headless',
'--window-size=1920,1080',
]);
return RemoteWebDriver::create(
'http://localhost:9515', DesiredCapabilities::chrome()->setCapability(
ChromeOptions::CAPABILITY, $options
), 90000, 90000
);
}
If that dosen't work for some reason then try to set_time_limit before $this->browse
set_time_limit(0);
try this while you instantiate your browser.. the most important is
$driver = retry(5, function () use ($capabilities) {
return RemoteWebDriver::create('http://localhost:9515', $capabilities, 60000, 60000);
Below is how i instantiate my browser
$options = (new ChromeOptions)->addArguments(['--disable-gpu', '--headless', '--no-sandbox']);
$capabilities = DesiredCapabilities::chrome()
->setCapability(ChromeOptions::CAPABILITY, $options)
->setPlatform('Linux');
$driver = retry(5, function () use ($capabilities) {
return RemoteWebDriver::create('http://localhost:9515', $capabilities, 60000, 60000);
}, 50);
$browser = new Browser($this->driver, new ElementResolver($driver, ''));
You really need to have latest google-chrome and latest chrome driver installed. I used to have only chromium browser and it doesn't work with it. To install latest chrome driver run php artisan dusk:chrome-driver.

Laravel forgot password emails not being sent

I have an extremely odd issue with Laravel emails.
Generally speaking I can send emails fine like so:
Mail::send('foo', $templateData,
function (Message $message) use ($name, $email) {
$message
->from('admin#example.com', 'My Example Company')
->to($email, $name)
->subject('Blah');
}
);
However, when trying to reset password, an email is not sent on my production server, despite acting like it has sent (i.e. no exceptions!). It is however sent when using mailtrap.io.
This is how my .env file looks like:
APP_ENV=prod
APP_KEY=XXXX
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://example.co.uk
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=XXX
DB_USERNAME=XXX
DB_PASSWORD=XXX
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=XXX
MAIL_PORT=XXX
MAIL_USERNAME=XXX
MAIL_PASSWORD=XXX
MAIL_ENCRYPTION=ssl
MAIL_FROM=admin#example.com
MAIL_FROM_NAME="My Example Company"
GOOGLE_API_KEY=XXX
I also tried:
composer dump-autoload
php artisan clear-compiled
php artisan config:clear
But to no avail.
Interestingly, when I use Mailer as opposed to the Mail facade, the email is again not sent with no exceptions raised.
public function foo(Illuminate\Mail\Mailer $mailer)
{
$mailer->send('ViewName', [],
function (Message $message) {
$message
->from('admin#example.com', 'My Example Company')
->to('you#example.com', 'John Smith')
->subject('Blah');
}
);
}

Resources