Tests, Multi-DB support for incoming URLs (#2466)

* Tests for authentication

* Add db field to company table (required if we are doing jobs without an auth()->user() )

* Add Laravel Dusk for browser testing, add ability to set DB by incoming URL Hash
This commit is contained in:
David Bomba 2018-10-24 21:24:09 +11:00 committed by GitHub
parent 64041fb3cb
commit dac1aa88d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 607 additions and 90 deletions

View File

@ -44,13 +44,13 @@ before_script:
- php artisan key:generate --no-interaction - php artisan key:generate --no-interaction
- sed -i '$a NINJA_DEV=true' .env - sed -i '$a NINJA_DEV=true' .env
# create the database and user # create the database and user
- mysql -u root -e "create database IF NOT EXISTS ninja1;" - mysql -u root -e "create database IF NOT EXISTS ninja01;"
- mysql -u root -e "create database IF NOT EXISTS ninja2;" - mysql -u root -e "create database IF NOT EXISTS ninja02;"
- mysql -u root -e "GRANT ALL PRIVILEGES ON ninja1.* To 'ninja'@'localhost' IDENTIFIED BY 'ninja'; FLUSH PRIVILEGES;" - mysql -u root -e "GRANT ALL PRIVILEGES ON ninja01.* To 'ninja'@'localhost' IDENTIFIED BY 'ninja'; FLUSH PRIVILEGES;"
- mysql -u root -e "GRANT ALL PRIVILEGES ON ninja2.* To 'ninja'@'localhost' IDENTIFIED BY 'ninja'; FLUSH PRIVILEGES;" - mysql -u root -e "GRANT ALL PRIVILEGES ON ninja02.* To 'ninja'@'localhost' IDENTIFIED BY 'ninja'; FLUSH PRIVILEGES;"
# migrate and seed the database # migrate and seed the database
- php artisan migrate --database=db-ninja-1 --seed --no-interaction - php artisan migrate --database=db-ninja-01 --seed --no-interaction
- php artisan migrate --database=db-ninja-2 --seed --no-interaction - php artisan migrate --database=db-ninja-02 --seed --no-interaction
- php artisan optimize - php artisan optimize
# migrate and seed the database # migrate and seed the database

View File

@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Http\Requests\Account\CreateAccountRequest; use App\Http\Requests\Account\CreateAccountRequest;
use App\Jobs\Account\CreateAccount; use App\Jobs\Account\CreateAccount;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class AccountController extends Controller class AccountController extends Controller

View File

@ -0,0 +1,27 @@
<?php
namespace App\Http\Controllers\Traits;
use App\Models\User;
trait VerifiesUserEmail
{
public function confirm($code)
{
$user = User::where('confirmation_code', $code)->first();
if ($user) {
$user->email_verified_at = now();
$user->confirmation_code = null;
$user->save();
redirect()->route('user.dashboard')->with('message', trans('texts.security_confirmation'));
}
redirect()->route('login')->with('message', trans('texts.wrong_confirmation'));
}
}

View File

@ -2,29 +2,12 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\User; use App\Http\Controllers\Traits\VerifiesUserEmail;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class UserController extends Controller class UserController extends Controller
{ {
use VerifiesUserEmail;
public function confirm($code)
{
$user = User::where('confirmation_code', '=', $code)->get()->first();
if ($user) {
$user->email_verified_at = now();
$user->confirmation_code = null;
$user->save();
redirect('user.dashboard')->with('message', trans('texts.security_confirmation'));
} else {
return Redirect::to('/login')->with('error', trans('texts.wrong_confirmation'));
}
}
} }

View File

@ -44,6 +44,9 @@ class Kernel extends HttpKernel
'db' => [ 'db' => [
\App\Http\Middleware\SetDb::class, \App\Http\Middleware\SetDb::class,
], ],
'url-db' => [
\App\Http\Middleware\UrlSetDb::class,
]
]; ];
/** /**

View File

@ -0,0 +1,36 @@
<?php
namespace App\Http\Middleware;
use App\Libraries\MultiDB;
use Closure;
use Hashids\Hashids;
class UrlSetDb
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next, $hash)
{
if (config('ninja.db.multi_db_enabled'))
{
$hashids = new Hashids(); //decoded output is _always_ an array.
//parse URL hash and set DB
$segments = explode("-", $hash);
$hashed_db = $hashids->decode($segments[0]);
MultiDB::setDB(MultiDB::DB_PREFIX . $hashed_db[0]);
}
return $next($request);
}
}

View File

@ -18,9 +18,7 @@ class SetDb
{ {
if (config('ninja.db.multi_db_enabled')) if (config('ninja.db.multi_db_enabled'))
{ {
MultiDB::setDB(auth()->user()->db); MultiDB::setDB(auth()->user()->db);
} }
return $next($request); return $next($request);

View File

@ -41,23 +41,13 @@ class CreateAccount
$account = Account::create($this->request->toArray()); $account = Account::create($this->request->toArray());
$user = CreateUser::dispatchNow($this->request, $account);
$company = CreateCompany::dispatchNow($this->request, $account); $company = CreateCompany::dispatchNow($this->request, $account);
UserCompany::create([ $user = CreateUser::dispatchNow($this->request, $account, $company);
'user_id' => $user->id,
'account_id' => $account->id,
'company_id' => $company->id,
'is_admin' => true,
'is_owner' => true,
'permissions' => '',
]);
Auth::loginUsingId($user->id, true); Auth::loginUsingId($user->id, true);
event(new AccountCreated()); event(new AccountCreated($user));
return $user; return $user;
} }

View File

@ -2,6 +2,8 @@
namespace App\Jobs\User; namespace App\Jobs\User;
use App\Models\User;
use App\Models\UserCompany;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\Account; use App\Models\Account;
@ -15,16 +17,20 @@ class CreateUser
protected $request; protected $request;
protected $account; protected $account;
protected $company;
/** /**
* Create a new job instance. * Create a new job instance.
* *
* @return void * @return void
*/ */
public function __construct(Request $request, $account) public function __construct(Request $request, $account, $company)
{ {
$this->request = $request; $this->request = $request;
$this->account = $account; $this->account = $account;
$this->company = $company;
} }
/** /**
@ -37,7 +43,7 @@ class CreateUser
$user = new User(); $user = new User();
$user->account_id = $this->account->id; $user->account_id = $this->account->id;
$user->password = Hash::make($this->request->input('password')); $user->password = bcrypt($this->request->input('password'));
$user->accepted_terms_version = config('ninja.terms_version'); $user->accepted_terms_version = config('ninja.terms_version');
$user->confirmation_code = strtolower(str_random(RANDOM_KEY_LENGTH)); $user->confirmation_code = strtolower(str_random(RANDOM_KEY_LENGTH));
$user->db = config('database.default'); $user->db = config('database.default');
@ -45,6 +51,16 @@ class CreateUser
$user->save(); $user->save();
UserCompany::create([
'user_id' => $user->id,
'account_id' => $this->account->id,
'company_id' => $this->company->id,
'is_admin' => true,
'is_owner' => true,
'permissions' => '',
]);
return $user; return $user;
} }
} }

View File

@ -10,11 +10,9 @@ use App\Models\User;
*/ */
class MultiDB class MultiDB
{ {
const DB_PREFIX = 'db-ninja-';
const DB_NINJA_1 = 1; public static $dbs = ['db-ninja-01', 'db-ninja-02'];
const DB_NINJA_2 = 2;
public static $dbs = ['db-ninja-1', 'db-ninja-2'];
/** /**
* @param $email * @param $email

View File

@ -7,7 +7,7 @@ use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
class Contact extends Authenticatable class ClientContact extends Authenticatable
{ {
use Notifiable; use Notifiable;

0
bootstrap/cache/.gitignore vendored Normal file → Executable file
View File

View File

@ -22,6 +22,7 @@
"asgrim/ofxparser": "^1.2", "asgrim/ofxparser": "^1.2",
"davejamesmiller/laravel-breadcrumbs": "5.x", "davejamesmiller/laravel-breadcrumbs": "5.x",
"fideloper/proxy": "^4.0", "fideloper/proxy": "^4.0",
"hashids/hashids": "^3.0",
"laracasts/presenter": "^0.2.1", "laracasts/presenter": "^0.2.1",
"laravel/framework": "5.7.*", "laravel/framework": "5.7.*",
"laravel/socialite": "^3.1", "laravel/socialite": "^3.1",
@ -37,6 +38,7 @@
"beyondcode/laravel-dump-server": "^1.0", "beyondcode/laravel-dump-server": "^1.0",
"filp/whoops": "^2.0", "filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4", "fzaninotto/faker": "^1.4",
"laravel/dusk": "^4.0",
"mockery/mockery": "^1.0", "mockery/mockery": "^1.0",
"nunomaduro/collision": "^2.0", "nunomaduro/collision": "^2.0",
"phpunit/phpunit": "^7.0" "phpunit/phpunit": "^7.0"

189
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "3cec8c5c70a52bc9011baabe117ac56c", "content-hash": "8f50fadc77133971d60134045427a805",
"packages": [ "packages": [
{ {
"name": "asgrim/ofxparser", "name": "asgrim/ofxparser",
@ -662,6 +662,72 @@
], ],
"time": "2017-03-20T17:10:46+00:00" "time": "2017-03-20T17:10:46+00:00"
}, },
{
"name": "hashids/hashids",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/ivanakimov/hashids.php.git",
"reference": "b6c61142bfe36d43740a5419d11c351dddac0458"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ivanakimov/hashids.php/zipball/b6c61142bfe36d43740a5419d11c351dddac0458",
"reference": "b6c61142bfe36d43740a5419d11c351dddac0458",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
},
"suggest": {
"ext-bcmath": "Required to use BC Math arbitrary precision mathematics (*).",
"ext-gmp": "Required to use GNU multiple precision mathematics (*)."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Hashids\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ivan Akimov",
"email": "ivan@barreleye.com",
"homepage": "https://twitter.com/IvanAkimov"
},
{
"name": "Vincent Klaiber",
"email": "hello@vinkla.com",
"homepage": "https://vinkla.com"
}
],
"description": "Generate short, unique, non-sequential ids (like YouTube and Bitly) from numbers",
"homepage": "http://hashids.org/php",
"keywords": [
"bitly",
"decode",
"encode",
"hash",
"hashid",
"hashids",
"ids",
"obfuscate",
"youtube"
],
"time": "2018-03-12T16:30:09+00:00"
},
{ {
"name": "jakub-onderka/php-console-color", "name": "jakub-onderka/php-console-color",
"version": "v0.2", "version": "v0.2",
@ -3376,6 +3442,66 @@
], ],
"time": "2017-07-22T11:58:36+00:00" "time": "2017-07-22T11:58:36+00:00"
}, },
{
"name": "facebook/webdriver",
"version": "1.6.0",
"source": {
"type": "git",
"url": "https://github.com/facebook/php-webdriver.git",
"reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/bd8c740097eb9f2fc3735250fc1912bc811a954e",
"reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-zip": "*",
"php": "^5.6 || ~7.0",
"symfony/process": "^2.8 || ^3.1 || ^4.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.0",
"jakub-onderka/php-parallel-lint": "^0.9.2",
"php-coveralls/php-coveralls": "^2.0",
"php-mock/php-mock-phpunit": "^1.1",
"phpunit/phpunit": "^5.7",
"sebastian/environment": "^1.3.4 || ^2.0 || ^3.0",
"squizlabs/php_codesniffer": "^2.6",
"symfony/var-dumper": "^3.3 || ^4.0"
},
"suggest": {
"ext-SimpleXML": "For Firefox profile creation"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-community": "1.5-dev"
}
},
"autoload": {
"psr-4": {
"Facebook\\WebDriver\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"description": "A PHP client for Selenium WebDriver",
"homepage": "https://github.com/facebook/php-webdriver",
"keywords": [
"facebook",
"php",
"selenium",
"webdriver"
],
"time": "2018-05-16T17:37:13+00:00"
},
{ {
"name": "filp/whoops", "name": "filp/whoops",
"version": "2.3.1", "version": "2.3.1",
@ -3535,6 +3661,67 @@
], ],
"time": "2016-01-20T08:20:44+00:00" "time": "2016-01-20T08:20:44+00:00"
}, },
{
"name": "laravel/dusk",
"version": "v4.0.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/dusk.git",
"reference": "9810f8609c8b53d9a3bac7d38c56530e0d77a6bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/dusk/zipball/9810f8609c8b53d9a3bac7d38c56530e0d77a6bb",
"reference": "9810f8609c8b53d9a3bac7d38c56530e0d77a6bb",
"shasum": ""
},
"require": {
"facebook/webdriver": "~1.3",
"illuminate/console": "~5.6",
"illuminate/support": "~5.6",
"nesbot/carbon": "~1.20",
"php": ">=7.1.0",
"symfony/console": "~4.0",
"symfony/process": "~4.0"
},
"require-dev": {
"mockery/mockery": "~1.0",
"phpunit/phpunit": "~7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
},
"laravel": {
"providers": [
"Laravel\\Dusk\\DuskServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Dusk\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel Dusk provides simple end-to-end testing and browser automation.",
"keywords": [
"laravel",
"testing",
"webdriver"
],
"time": "2018-10-03T15:37:05+00:00"
},
{ {
"name": "mockery/mockery", "name": "mockery/mockery",
"version": "1.2.0", "version": "1.2.0",

View File

@ -15,7 +15,7 @@ return [
| |
*/ */
'default' => env('CACHE_DRIVER', 'file'), 'default' => env('CACHE_DRIVER', 'redis'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -81,7 +81,7 @@ return [
'prefix_indexes' => true, 'prefix_indexes' => true,
], ],
'db-ninja-1' => [ 'db-ninja-01' => [
'driver' => 'mysql', 'driver' => 'mysql',
'host' => env('DB_HOST1', env('DB_HOST', 'localhost')), 'host' => env('DB_HOST1', env('DB_HOST', 'localhost')),
'database' => env('DB_DATABASE1', env('DB_DATABASE', 'forge')), 'database' => env('DB_DATABASE1', env('DB_DATABASE', 'forge')),
@ -96,7 +96,7 @@ return [
'engine' => 'InnoDB', 'engine' => 'InnoDB',
], ],
'db-ninja-2' => [ 'db-ninja-02' => [
'driver' => 'mysql', 'driver' => 'mysql',
'host' => env('DB_HOST2', env('DB_HOST', 'localhost')), 'host' => env('DB_HOST2', env('DB_HOST', 'localhost')),
'database' => env('DB_DATABASE2', env('DB_DATABASE', 'forge')), 'database' => env('DB_DATABASE2', env('DB_DATABASE', 'forge')),

View File

@ -39,7 +39,7 @@ return [
| |
*/ */
'limit' => env('TELESCOPE_LIMIT', 100), 'limit' => env('TELESCOPE_LIMIT', null),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -6,6 +6,7 @@ $factory->define(App\Models\Company::class, function (Faker $faker) {
return [ return [
'name' => $faker->name, 'name' => $faker->name,
'company_key' => strtolower(str_random(RANDOM_KEY_LENGTH)), 'company_key' => strtolower(str_random(RANDOM_KEY_LENGTH)),
'ip' => $faker->ipv4 'ip' => $faker->ipv4,
'db' => config('database.default'),
]; ];
}); });

View File

@ -18,9 +18,9 @@ $factory->define(App\Models\User::class, function (Faker $faker) {
'first_name' => $faker->name, 'first_name' => $faker->name,
'last_name' => $faker->name, 'last_name' => $faker->name,
'phone' => $faker->phoneNumber, 'phone' => $faker->phoneNumber,
'email' => $faker->unique()->safeEmail, 'email' => config('ninja.testvars.username'),
'email_verified_at' => now(), 'email_verified_at' => now(),
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret 'password' => bcrypt(config('ninja.testvars.password')), // secret
'remember_token' => str_random(10), 'remember_token' => str_random(10),
'db' => config('database.default') 'db' => config('database.default')
]; ];

View File

@ -138,6 +138,7 @@ class CreateUsersTable extends Migration
$table->unsignedInteger('industry_id')->nullable(); $table->unsignedInteger('industry_id')->nullable();
$table->unsignedInteger('size_id')->nullable(); $table->unsignedInteger('size_id')->nullable();
$table->string('subdomain')->nullable(); $table->string('subdomain')->nullable();
$table->string('db')->nullable();
$table->timestamps(); $table->timestamps();
$table->softDeletes(); $table->softDeletes();

View File

@ -2,7 +2,7 @@
use App\Models\Account; use App\Models\Account;
use App\Models\Client; use App\Models\Client;
use App\Models\Contact; use App\Models\ClientContact;
use App\Models\User; use App\Models\User;
use App\Models\UserAccount; use App\Models\UserAccount;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
@ -25,41 +25,45 @@ class UsersTableSeeder extends Seeder
$faker = Faker\Factory::create(); $faker = Faker\Factory::create();
$account = Account::create([ $account = factory(\App\Models\Account::class)->create();
'name' => $faker->name(), $company = factory(\App\Models\Company::class)->create([
'account_key' => strtolower(str_random(RANDOM_KEY_LENGTH)), 'account_id' => $account->id,
]); ]);
$account->default_company_id = $company->id;
$account->save();
$user = User::create([ $user = User::create([
'account_id' => $account->id,
'first_name' => $faker->firstName, 'first_name' => $faker->firstName,
'last_name' => $faker->lastName, 'last_name' => $faker->lastName,
'email' => TEST_USERNAME, 'email' => config('ninja.testvars.username'),
'password' => Hash::make(TEST_PASSWORD), 'password' => Hash::make(config('ninja.testvars.password')),
'email_verified_at' => now(), 'email_verified_at' => now(),
]); ]);
$client = Client::create([ $client = Client::create([
'name' => $faker->name, 'name' => $faker->name,
'account_id' => $account->id, 'company_id' => $company->id,
]); ]);
Contact::create([ ClientContact::create([
'first_name' => $faker->firstName, 'first_name' => $faker->firstName,
'last_name' => $faker->lastName, 'last_name' => $faker->lastName,
'email' => TEST_CLIENTNAME, 'email' => config('ninja.testvars.clientname'),
'account_id' => $account->id, 'company_id' => $company->id,
'password' => Hash::make(TEST_PASSWORD), 'password' => Hash::make(config('ninja.testvars.password')),
'email_verified_at' => now(), 'email_verified_at' => now(),
'client_id' =>$client->id, 'client_id' =>$client->id,
]); ]);
UserAccount::create([ \App\Models\UserCompany::create([
'account_id' => $account->id, 'account_id' => $account->id,
'company_id' => $company->id,
'user_id' => $user->id, 'user_id' => $user->id,
'is_owner' => 1, 'is_owner' => 1,
'is_admin' => 1, 'is_admin' => 1,
'is_locked' => 0, 'is_locked' => 0,
'is_default' => 1,
]); ]);
} }
} }

View File

@ -16,6 +16,10 @@
<testsuite name="Integration"> <testsuite name="Integration">
<directory suffix="Test.php">./tests/Integration</directory> <directory suffix="Test.php">./tests/Integration</directory>
</testsuite> </testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites> </testsuites>
<filter> <filter>
<whitelist processUncoveredFilesFromWhitelist="true"> <whitelist processUncoveredFilesFromWhitelist="true">

View File

@ -38,9 +38,6 @@ Route::get('auth/{provider}/callback', 'Auth\LoginController@handleProviderCallb
* Authenticated User Routes * Authenticated User Routes
*/ */
Auth::routes(['verify' => true]);
Route::group(['middleware' => ['auth:user', 'db']], function () { Route::group(['middleware' => ['auth:user', 'db']], function () {
Route::get('dashboard', 'HomeController@user')->name('user.dashboard'); Route::get('dashboard', 'HomeController@user')->name('user.dashboard');
@ -53,8 +50,11 @@ Route::group(['middleware' => ['auth:user', 'db']], function () {
/* /*
* Inbound routes requiring DB Lookup * Inbound routes requiring DB Lookup
*/ */
Route::get('/user/confirm/{confirmation_code}', 'UserController@confirm'); Route::group(['middleware' => ['auth:user', 'db']], function () {
Route::get('/user/confirm/{confirmation_code}', 'UserController@confirm');
});
/* /*
Authenticated Contact Routes Authenticated Contact Routes
*/ */

View File

@ -0,0 +1,56 @@
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\DuskTestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\WithoutMiddleware;
class CreateAccountTest extends DuskTestCase
{
use WithFaker;
use DatabaseTransactions;
public function testSignupFormDisplayed()
{
$response = $this->get('/signup');
$response->assertStatus(200);
}
/**
* A valid user can be logged in.
*
* @return void
*/
public function testCreateAValidUser()
{
/*
$response = $this->post('/signup', [
'first_name' => $this->faker->firstName(),
'last_name' => $this->faker->lastName(),
'terms_of_service' => 1,
'privacy_policy' => 1,
'email' => config('ninja.testvars.username'),
'password' => config('ninja.testvars.password')
]);
$response->assertSuccessful();
*/
$this->visit('/signup')
->type($this->faker->firstName(), 'first_name')
->type($this->faker->lastName(), 'last_name')
->type($this->faker->email(), 'email')
->type($this->faker->password(7), 'password')
->check('terms_of_service')
->check('terms_of_service')
->press(trans('texts.create_account'))
->seePageIs('/dashboard');
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Tests\Browser;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends DuskTestCase
{
/**
* A basic browser test example.
*
* @return void
*/
public function testBasicExample()
{
$this->browse(function (Browser $browser) {
$browser->visit('/')
->assertSee('Laravel');
});
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace Tests\Browser\Pages;
use Laravel\Dusk\Browser;
class HomePage extends Page
{
/**
* Get the URL for the page.
*
* @return string
*/
public function url()
{
return '/';
}
/**
* Assert that the browser is on the page.
*
* @param Browser $browser
* @return void
*/
public function assert(Browser $browser)
{
//
}
/**
* Get the element shortcuts for the page.
*
* @return array
*/
public function elements()
{
return [
'@element' => '#selector',
];
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Tests\Browser\Pages;
use Laravel\Dusk\Page as BasePage;
abstract class Page extends BasePage
{
/**
* Get the global element shortcuts for the site.
*
* @return array
*/
public static function siteElements()
{
return [
'@element' => '#selector',
];
}
}

2
tests/Browser/console/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

2
tests/Browser/screenshots/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

43
tests/DuskTestCase.php Normal file
View File

@ -0,0 +1,43 @@
<?php
namespace Tests;
use Laravel\Dusk\TestCase as BaseTestCase;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
abstract class DuskTestCase extends BaseTestCase
{
use CreatesApplication;
/**
* Prepare for Dusk test execution.
*
* @beforeClass
* @return void
*/
public static function prepare()
{
static::startChromeDriver();
}
/**
* Create the RemoteWebDriver instance.
*
* @return \Facebook\WebDriver\Remote\RemoteWebDriver
*/
protected function driver()
{
$options = (new ChromeOptions)->addArguments([
'--disable-gpu',
'--headless'
]);
return RemoteWebDriver::create(
'http://localhost:9515', DesiredCapabilities::chrome()->setCapability(
ChromeOptions::CAPABILITY, $options
)
);
}
}

View File

@ -0,0 +1,79 @@
<?php
namespace Tests\Feature;
use App\Models\Account;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class LoginTest extends TestCase
{
use DatabaseTransactions;
public function testLoginFormDisplayed()
{
$response = $this->get('/login');
$response->assertStatus(200);
}
/**
* A valid user can be logged in.
*
* @return void
*/
public function testLoginAValidUser()
{
$account = factory(Account::class)->create();
$user = factory(User::class)->create([
'account_id' => $account->id,
]);
$response = $this->post('/login', [
'email' => config('ninja.testvars.username'),
'password' => config('ninja.testvars.password')
]);
$response->assertStatus(302);
$this->assertAuthenticatedAs($user);
}
/**
* An invalid user cannot be logged in.
*
* @return void
*/
public function testDoesNotLoginAnInvalidUser()
{
$account = factory(Account::class)->create();
$user = factory(User::class)->create([
'account_id' => $account->id,
]);
$response = $this->post('/login', [
'email' => config('ninja.testvars.username'),
'password' => 'invalid'
]);
$response->assertSessionHasErrors();
$this->assertGuest();
}
/**
* A logged in user can be logged out.
*
* @return void
*/
public function testLogoutAnAuthenticatedUser()
{
$account = factory(Account::class)->create();
$user = factory(User::class)->create([
'account_id' => $account->id,
]);
$response = $this->actingAs($user)->post('/logout');
$response->assertStatus(302);
$this->assertGuest();
}
}

View File

@ -35,8 +35,8 @@ class MultiDBUserTest extends TestCase
$ac = factory(\App\Models\Account::class)->make(); $ac = factory(\App\Models\Account::class)->make();
$account = Account::on('db-ninja-1')->create($ac->toArray()); $account = Account::on('db-ninja-01')->create($ac->toArray());
$account2 = Account::on('db-ninja-2')->create($ac->toArray()); $account2 = Account::on('db-ninja-02')->create($ac->toArray());
$company = factory(\App\Models\Company::class)->make([ $company = factory(\App\Models\Company::class)->make([
'account_id' => $account->id, 'account_id' => $account->id,
@ -46,8 +46,8 @@ class MultiDBUserTest extends TestCase
'account_id' => $account2->id, 'account_id' => $account2->id,
]); ]);
Company::on('db-ninja-1')->create($company->toArray()); Company::on('db-ninja-01')->create($company->toArray());
Company::on('db-ninja-2')->create($company2->toArray()); Company::on('db-ninja-02')->create($company2->toArray());
$user = [ $user = [
'first_name' => 'user_db_1', 'first_name' => 'user_db_1',
@ -77,8 +77,8 @@ class MultiDBUserTest extends TestCase
]; ];
User::on('db-ninja-1')->create($user); User::on('db-ninja-01')->create($user);
User::on('db-ninja-2')->create($user2); User::on('db-ninja-02')->create($user2);
} }
public function test_oauth_user_db2_exists() public function test_oauth_user_db2_exists()
@ -113,12 +113,12 @@ class MultiDBUserTest extends TestCase
public function test_set_db_invokes() public function test_set_db_invokes()
{ {
$this->expectNotToPerformAssertions(MultiDB::setDB('db-ninja-1')); $this->expectNotToPerformAssertions(MultiDB::setDB('db-ninja-01'));
} }
public function tearDown() public function tearDown()
{ {
DB::connection('db-ninja-1')->table('users')->delete(); DB::connection('db-ninja-01')->table('users')->delete();
DB::connection('db-ninja-2')->table('users')->delete(); DB::connection('db-ninja-02')->table('users')->delete();
} }
} }

View File

@ -29,15 +29,15 @@ class UniqueEmailTest extends TestCase
if (! config('ninja.db.multi_db_enabled')) if (! config('ninja.db.multi_db_enabled'))
$this->markTestSkipped('Multi DB not enabled - skipping'); $this->markTestSkipped('Multi DB not enabled - skipping');
DB::connection('db-ninja-1')->table('users')->delete(); DB::connection('db-ninja-01')->table('users')->delete();
DB::connection('db-ninja-2')->table('users')->delete(); DB::connection('db-ninja-02')->table('users')->delete();
$this->rule = new UniqueUserRule(); $this->rule = new UniqueUserRule();
$ac = factory(\App\Models\Account::class)->make(); $ac = factory(\App\Models\Account::class)->make();
$account = Account::on('db-ninja-1')->create($ac->toArray()); $account = Account::on('db-ninja-01')->create($ac->toArray());
$account2 = Account::on('db-ninja-2')->create($ac->toArray()); $account2 = Account::on('db-ninja-02')->create($ac->toArray());
$company = factory(\App\Models\Company::class)->make([ $company = factory(\App\Models\Company::class)->make([
'account_id' => $account->id, 'account_id' => $account->id,
@ -47,8 +47,8 @@ class UniqueEmailTest extends TestCase
'account_id' => $account2->id, 'account_id' => $account2->id,
]); ]);
Company::on('db-ninja-1')->create($company->toArray()); Company::on('db-ninja-01')->create($company->toArray());
Company::on('db-ninja-2')->create($company2->toArray()); Company::on('db-ninja-02')->create($company2->toArray());
$user = [ $user = [
@ -67,8 +67,8 @@ class UniqueEmailTest extends TestCase
'account_id' => $account2->id, 'account_id' => $account2->id,
]; ];
User::on('db-ninja-1')->create($user); User::on('db-ninja-01')->create($user);
User::on('db-ninja-2')->create($user2); User::on('db-ninja-02')->create($user2);
} }
@ -88,8 +88,8 @@ class UniqueEmailTest extends TestCase
public function tearDown() public function tearDown()
{ {
DB::connection('db-ninja-1')->table('users')->delete(); DB::connection('db-ninja-01')->table('users')->delete();
DB::connection('db-ninja-2')->table('users')->delete(); DB::connection('db-ninja-02')->table('users')->delete();
} }
} }