I have the following two files: .env and .env.dusk.local
.env:
APP_ENV="local"
APP_KEY=base64:358E4UyIq+Zbg+H+Pm03dYA2B/vz3ViPJ+U48ikg6qE=
APP_DEBUG=true
APP_LOG_LEVEL="debug"
APP_URL="http://localhost"
DB_CONNECTION="mysql"
DB_HOST="127.0.0.1"
DB_DATABASE="homestead"
DB_USERNAME="homestead"
DB_PASSWORD="secret"
CACHE_DRIVER="redis"
SESSION_DRIVER="redis"
QUEUE_DRIVER="sync"
.env.dusk.local
APP_ENV="local"
APP_KEY=base64:358E4UyIq+Zbg+H+Pm03dYA2B/vz3ViPJ+U48ikg6qE=
APP_DEBUG=true
APP_LOG_LEVEL="debug"
APP_URL="http://localhost"
DB_CONNECTION="sqlite"
CACHE_DRIVER="file"
SESSION_DRIVER="file"
QUEUE_DRIVER="sync"
But when I run php artisan dusk I get errors about the sqlite database not existing.
Illuminate\Database\QueryException: Database (homestead) does not exist. (SQL: select * from sqlite_master where type = 'table' and name = migrations)
So, I suspect that the env files are not correctly being copied and swapped into place. It seems they are simple being merged together, which is causing issues for tests not working.
I am currently using this on Manjaro Linux, and have not tried it on any other OS.
What version of Dusk are you using? Is it the latest one (1.0.5) ?
Yes. v1.0.5
I'm also having the same issue. I now set DB_DATABASE as :memory: for the testing environment and I didn't get the above error. Now I'm getting:
testing.ERROR: PDOException: SQLSTATE[HY000]: General error: 1 no such table: table_name in ......../vendor/laravel/framework/src/Illuminate/Database/Connection.php:445
I also tried adding $this->artisan('migrate'); to the setUp method, but still the same.
I had a similar issue using Homestead, which was permissions related. Dusk would dump the contents of .env.dusk.local into my .env but fail to perform the backup/replace, leaving my .env over-written with test settings.
In your case, I don't think it can write into your .env period, which means it'll just be using your local settings.
I believe the issue is in the code below, as well as restoreEnvironment(). For example, given you have a .env.dusk.local (returned by $this->duskFile()), the code assumes this gets written into .env, and moves on with the tests:
protected function backupEnvironment()
{
// this can fail due to permissions
copy(base_path('.env'), base_path('.env.backup'));
// this can also fail. In my case, since the file exists, the write did succeed
copy(base_path($this->duskFile()), base_path('.env'));
}
// at this point restoreEnvironment() will obviously fail since no backup was made
I would personally prefer this code to throw an exception if the backup/replace is not working.
That might be causing your issue - to verify, run a test php script from the command line which copies files in the app root, writes into an existing file, and performs an unlink. My fix was a vagrant reload, but it will depend on your setup.
Your .env file is replaced with .env.dusk.local before the browser is "opened", so when the browser starts, the DB_DATABASE is not defined on your temporary .env file (copy of .env.dusk.local).
At this moment you will need to define all variables in your .env.dusk.local same as .env and then change only the values you need.
A better solution is make a merge instead of a replacement, but I think this need changes on the laravel core and not the dusk package.
I have a similar problem. If you create a .env.dusk.testing/local, and you dont define a DB_DATABASE, assuming it would just default to the database.php env('DB_DATABASE', database_path('database.sqlite')), things dont work as expected. I was suddenly seeing the DB_DATABASE from my .env file (which pointed to a pgsql database name), as if the .env.dusk file was read on top of my .env file.
If I defined a DB_DATABASE filename in the .env.dusk file, things started working fine.
For those trying to use :memory, that wont work. You need to use a normal sqlite file.
I opted for making another database array entry in config/database.php
'dusk-sqlite' => [
'driver' => 'sqlite',
'database' => database_path('database.sqlite'), // env() in sqlite option was using .env value
'prefix' => '',
],
and used this in my .env.dusk.local
DB_CONNECTION=dusk-sqlite
@taylorotwell Looks like env() is being used from .env file before dusk file is loaded. Is the environment loaded via .env before .env.dusk.local is copied to .env?
@bbashy I am not sure about your last assumption. Or maybe we're talking about different issues.
But anyway, I tried running Dusk today while overriding some of the env values and as a result I don't even have APP_KEY from main .env file loaded in tests and my APP_DEBUG is assumed to be false while .env explicitly states it to be true. 馃槃
Indeed, it seems like Dusk replaces the contents of .env file in it's entirety rather than performing merge and the working workflow is as follows:
cp .env .env.dusk.local
sed -i "s/DB_CONNECTION=.*/DB_CONNECTION=sqlite/" .env.dusk.local
sed -i "s#DB_DATABASE=.*#DB_DATABASE=/opt/project/database/database.sqlite#" .env.dusk.local
But this all sounds very confusing to me after overriding env variables in phpunit.xml. I think it should be clearly stated in the docs how exactly Dusk processes .env file.
I'm using Homestead on a Windows machine. When running php artisan dusk, the .env's content is replaced by .env.dusk.local's content. However, the tests still use the "old" .env.
My .env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:6R5VxSoy2djjIQ0ah6BUCgBmrLNpdOcr37LemBag8wg=
APP_URL=http://laravel-boilerplate.dev
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
My .env.dusk.local
APP_NAME=Laravel_test
APP_ENV=local
APP_KEY=base64:6R5VxSoy2djjIQ0ah6BUCgBmrLNpdOcr37LemBag8wg=
APP_URL=http://laravel-boilerplate.dev
DB_CONNECTION=testing
config/database.php
'testing' => [
'driver' => 'mysql',
'host' => '127.0.0.1',
'port' => '3306',
'database' => 'testing',
'username' => 'homestead',
'password' => 'secret',
'unix_socket' => '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
LoginTest.php
use DatabaseMigrations;
private $user;
public function test_login_interact()
{
var_dump(env('APP_NAME'));
$this->user = factory(User::class)->create([
'password' => bcrypt('secret')
]);
$this->browse(function (Browser $browser) {
$browser->visit('/login')
->waitForText('Remember Me')
->type('email', $this->user->email)
->type('password', 'secret')
->click('input[type="submit"]')
->waitFor('.panels')
->assertPathIs('/home');
});
}
The var_dump of APP_ENV is Laravel_test, which is fine.
However, the DatabaseMigrations trait is doing its migrations on the homestead database instead of testing.
Also, in my blade file, I'm doing the following:
<h1>{{ config('app.name') }}</h1>
The output on the dusk screenshot is "Laravel" instead of "Laravel_test".
Adding this line in tests/Browser/CreatesApplication.php to force the database change worked for me:
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
$app['config']->set('database.default','testing');
return $app;
}
However, it seems chrome is still using the old database connection since I still see "Laravel" instead of "Laravel_test" in the <h1>.
As @bbashy said, it looks like env() is being used from .env file before dusk file is loaded.
Edit
It worked perfectly on anoter machine (Windows 10, similar specs, vagrant 1.9.2, Homestead 5.2.3). Still trying to figure out what's wrong on the first machine.
@bbashy @adiachenko @francoislevesque are you all using php artisan serve prior to running Dusk?
@deleugpn No, never use it.
@deleugpn I am using Docker. It's not that I treat this as a bug, it's just that the specifics aren't emphasized in documentation, hence confusion.
@deleugpn No, not using it. Should we?
@francoislevesque not necessarily. Dusk will backup your .env and move .env.dusk.{APP_ENV} to .env so the browser can match the same environment as yours. This, however, fails to happen when using php artisan serve because serve will cache your env variables the moment of starting to serve. This can be solved by running php artisan serve --env=dusk.local (switch local for anything you use locally). But all of you are suffering from different kinds of problem somewhat related to the same thing. If everyone were using serve, it would make sense to implement a dusk:serve, perhaps.
@deleugpn agree. Running a separate artisan serve with specifying environment in a different port --env=dusk.local works well. php artisan dusk:serve will be very good.
@mustafaaloko I already did and got #249 and then I tried #250 to make it possible to easily extend, but also no luck because of the construct actions. Furthermore, I tried https://github.com/laravel/framework/pull/18973 to make #250 look better, but also no. Now I just gave up.
I have the same problem,
thanks @deleugpn for pointing that out so clearly.
In case this helps anyone, here is the problem I was having: https://github.com/laravel/dusk/issues/211#issuecomment-322835162
I came by a very similar problem. I had DB_DATABASE as homestead in .env.dusk.local and when any of my tests accessed a route that was querying the database, I would get:
Database (homestead) does not exist.
I finally solved by changing:
'sqlite' => [
'driver' => 'sqlite',
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
],
To this:
'sqlite' => [
'driver' => 'sqlite',
'database' => database_path(env('DB_DATABASE', 'database.sqlite')),
'prefix' => '',
],
It's all explained in this answer.
Closing this issue because it's already solved, old or not relevant anymore. Feel free to reply if you're still experiencing this issue.
Having a similar/related issue
I'm using Homestead on a Windows machine. When running
php artisan dusk, the.env's content is replaced by.env.dusk.local's content. However, the tests still use the "old" .env.My .env
APP_NAME=Laravel APP_ENV=local APP_KEY=base64:6R5VxSoy2djjIQ0ah6BUCgBmrLNpdOcr37LemBag8wg= APP_URL=http://laravel-boilerplate.dev DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secretMy .env.dusk.local
APP_NAME=Laravel_test APP_ENV=local APP_KEY=base64:6R5VxSoy2djjIQ0ah6BUCgBmrLNpdOcr37LemBag8wg= APP_URL=http://laravel-boilerplate.dev DB_CONNECTION=testingconfig/database.php
'testing' => [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'port' => '3306', 'database' => 'testing', 'username' => 'homestead', 'password' => 'secret', 'unix_socket' => '', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => null, ],While running the tests
LoginTest.php
use DatabaseMigrations; private $user; public function test_login_interact() { var_dump(env('APP_NAME')); $this->user = factory(User::class)->create([ 'password' => bcrypt('secret') ]); $this->browse(function (Browser $browser) { $browser->visit('/login') ->waitForText('Remember Me') ->type('email', $this->user->email) ->type('password', 'secret') ->click('input[type="submit"]') ->waitFor('.panels') ->assertPathIs('/home'); }); }The var_dump of
APP_ENVisLaravel_test, which is fine.However, the DatabaseMigrations trait is doing its migrations on the
homesteaddatabase instead oftesting.Also, in my blade file, I'm doing the following:
<h1>{{ config('app.name') }}</h1>The output on the dusk screenshot is "Laravel" instead of "Laravel_test".
Partial Solution
Adding this line in
tests/Browser/CreatesApplication.phpto force the database change worked for me:public function createApplication() { $app = require __DIR__.'/../bootstrap/app.php'; $app->make(Kernel::class)->bootstrap(); $app['config']->set('database.default','testing'); return $app; }However, it seems chrome is still using the old database connection since I still see "Laravel" instead of "Laravel_test" in the
<h1>.As @bbashy said, it looks like env() is being used from .env file before dusk file is loaded.
Edit
It worked perfectly on anoter machine (Windows 10, similar specs, vagrant 1.9.2, Homestead 5.2.3). Still trying to figure out what's wrong on the first machine.
I had the same problem and solved by this solution ... 馃憤
Fixed this issue today by adding into the phpunit.dusk.xml file
</testsuites>
<php>
<env name="APP_ENV" value="testing" force="true"/>
<env name="CACHE_DRIVER" value="redis" force="true"/>
<env name="SESSION_DRIVER" value="redis" force="true"/>
<env name="QUEUE_DRIVER" value="redis" force="true"/>
<env name="DB_CONNECTION" value="mysql" force="true"/>
<env name="DB_DATABASE" value="testing" force="true"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>
UPDATE
I also had to change my .env.dusk.local to .env.dusk.testing
php artisan cache:clear --env=testingphp artisan cache:clear
Most helpful comment
@francoislevesque not necessarily. Dusk will backup your
.envand move.env.dusk.{APP_ENV}to.envso the browser can match the same environment as yours. This, however, fails to happen when usingphp artisan servebecauseservewill cache yourenvvariables the moment of starting to serve. This can be solved by runningphp artisan serve --env=dusk.local(switch local for anything you use locally). But all of you are suffering from different kinds of problem somewhat related to the same thing. If everyone were usingserve, it would make sense to implement adusk:serve, perhaps.