Sign Up Scaffolding (#2453)

* Fix js dependencies

* Breadcrumb implementation

* Test for UniqueEmailRule Validation

* reduce length of account_key to prevent key too long error

* Fixes for travis - reduce user email length

* Reduce all unique field lengths to 100 to prevent key overflow

* Fix for Bank Model

* Prevent a user from registering multiple account with one email address when using multiple databases
This commit is contained in:
David Bomba 2018-10-17 23:26:27 +11:00 committed by GitHub
parent 528c99f655
commit 62e2444a2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 878 additions and 348 deletions

22
.env.travis Normal file
View File

@ -0,0 +1,22 @@
APP_ENV=development
APP_DEBUG=false
APP_URL=http://ninja.test
APP_KEY=SomeRandomStringSomeRandomString
APP_CIPHER=AES-256-CBC
APP_LOCALE=en
DB_STRICT=false
DB_HOST=localhost
DB_USERNAME=ninja
DB_PASSWORD=ninja
DB_DATABASE1=ninja1
DB_DATABASE2=ninja2
MAIL_DRIVER=log
TRAVIS=true
API_SECRET=password
TEST_USERNAME=user@example.com
TEST_PERMISSIONS_USERNAME=permissions@example.com
USER_AUTH_PROVIDER=users
CONTACT_AUTH_PROVIDER=contacts

View File

@ -44,7 +44,15 @@ before_script:
- php artisan key:generate --no-interaction
- sed -i '$a NINJA_DEV=true' .env
# create the database and user
- mysql -u root -e "create database IF NOT EXISTS ninja0;"
- mysql -u root -e "create database IF NOT EXISTS ninja1;"
- mysql -u root -e "create database IF NOT EXISTS ninja2;"
- 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 ninja2.* To 'ninja'@'localhost' IDENTIFIED BY 'ninja'; FLUSH PRIVILEGES;"
# migrate and seed the database
- php artisan migrate --database=db-ninja-1 --seed --no-interaction
- php artisan migrate --database=db-ninja-2 --seed --no-interaction
- php artisan optimize
# migrate and seed the database
# Start webserver on ninja.test:8000
- php artisan serve --host=www.ninja.test --port=8000 & # '&' allows to run in background

View File

@ -25,5 +25,5 @@ if (! defined('APP_NAME')) {
define('BANK_LIBRARY_OFX', 1);
define('MULTI_DBS', serialize(['db-ninja-1', 'db-ninja-2']));
}

View File

@ -25,7 +25,7 @@ class LoginController extends Controller
*
* @var string
*/
protected $redirectTo = '/home';
protected $redirectTo = '/dashboard';
/**
* Create a new controller instance.

View File

@ -28,7 +28,7 @@ class RegisterController extends Controller
*
* @var string
*/
protected $redirectTo = '/home';
protected $redirectTo = '/dashboard';
/**
* Create a new controller instance.

View File

@ -25,7 +25,7 @@ class ResetPasswordController extends Controller
*
* @var string
*/
protected $redirectTo = '/home';
protected $redirectTo = '/dashboard';
/**
* Create a new controller instance.

View File

@ -26,7 +26,7 @@ class VerificationController extends Controller
*
* @var string
*/
protected $redirectTo = '/home';
protected $redirectTo = '/dashboard';
/**
* Create a new controller instance.

View File

@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ClientController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}

View File

@ -2,7 +2,7 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\SignupRequest;
class HomeController extends Controller
{
@ -35,6 +35,12 @@ class HomeController extends Controller
public function signup()
{
return 'sign up page';
return view('signup.index');
}
public function processSignup(SignupRequest $request)
{
dd($request->validated());
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class InvoiceController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SettingsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class Request extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Http\Requests;
use App\Http\ValidationRules\UniqueUserRule;
use Illuminate\Support\Facades\Auth;
class SignupRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return ! Auth::user();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//'email' => 'required|string|email|max:100',
'password' => 'required|string|min:6',
'email' => new UniqueUserRule(),
];
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Http\ValidationRules;
use App\Models\User;
use Illuminate\Contracts\Validation\Rule;
class UniqueUserRule implements Rule
{
public function passes($attribute, $value)
{
return $this->checkIfEmailExists($value);
}
public function message()
{
return trans('texts.email_already_register');
}
private function checkIfEmailExists($email) : bool
{
if (config('auth.providers.users.driver') == 'eloquent') //default eloquent = single DB
{
return User::where(['email' => $email])->get()->count() == 0 ?? false; // true -> 0 emails found / false -> >=1 emails found
}
//multi-db active
foreach (unserialize(MULTI_DBS) as $db)
{
if(User::on($db)->where(['email' => $email])->get()->count() >=1) // if user already exists, validation will fail
return false;
}
return true;
}
}

View File

@ -2,12 +2,12 @@
namespace App\Models;
use Eloquent;
use Illuminate\Database\Eloquent\Model;
/**
* Class Bank.
*/
class Bank extends Eloquent
class Bank extends Model
{
/**
* @var bool

View File

@ -20,6 +20,7 @@
"require": {
"php": "^7.1.3",
"asgrim/ofxparser": "^1.2",
"davejamesmiller/laravel-breadcrumbs": "5.x",
"fideloper/proxy": "^4.0",
"laravel/framework": "5.7.*",
"laravel/tinker": "^1.0",
@ -43,7 +44,8 @@
"App\\": "app/"
},
"files": [
"app/Libraries/OFX.php"
"app/Libraries/OFX.php",
"app/Constants.php"
]
},
"autoload-dev": {

61
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "218e884d0942a0ea04acd7d82b9705e8",
"content-hash": "c9e2e008fc8ade0315e2c39e1934152d",
"packages": [
{
"name": "asgrim/ofxparser",
@ -62,6 +62,65 @@
],
"time": "2016-09-26T11:36:23+00:00"
},
{
"name": "davejamesmiller/laravel-breadcrumbs",
"version": "5.1.2",
"source": {
"type": "git",
"url": "https://github.com/davejamesmiller/laravel-breadcrumbs.git",
"reference": "f24853b97d9f973a9b936d2692f93b11924415e2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/davejamesmiller/laravel-breadcrumbs/zipball/f24853b97d9f973a9b936d2692f93b11924415e2",
"reference": "f24853b97d9f973a9b936d2692f93b11924415e2",
"shasum": ""
},
"require": {
"illuminate/support": "5.6.*|5.7.*",
"illuminate/view": "5.6.*|5.7.*",
"php": ">=7.1.3"
},
"require-dev": {
"laravel/framework": "5.6.*|5.7.*",
"orchestra/testbench": "3.6.*|3.7.*",
"php-coveralls/php-coveralls": "^1.0",
"phpunit/phpunit": "7.*"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"DaveJamesMiller\\Breadcrumbs\\BreadcrumbsServiceProvider"
],
"aliases": {
"Breadcrumbs": "DaveJamesMiller\\Breadcrumbs\\Facades\\Breadcrumbs"
}
}
},
"autoload": {
"psr-4": {
"DaveJamesMiller\\Breadcrumbs\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dave James Miller",
"email": "dave@davejamesmiller.com",
"homepage": "https://davejamesmiller.com/"
}
],
"description": "A simple Laravel-style way to create breadcrumbs.",
"homepage": "https://github.com/davejamesmiller/laravel-breadcrumbs",
"keywords": [
"laravel"
],
"time": "2018-09-14T06:29:58+00:00"
},
{
"name": "dnoegel/php-xdg-base-dir",
"version": "0.1",

View File

@ -73,11 +73,11 @@ return [
'providers' => [
'users' => [
'driver' => env('AUTH_PROVIDER', 'eloquent'),
'driver' => env('USER_AUTH_PROVIDER', 'eloquent'),
'model' => App\Models\User::class,
],
'contacts' => [
'driver' => env('AUTH_PROVIDER', 'eloquent'),
'driver' => env('CONTACT_AUTH_PROVIDER', 'eloquent'),
'model' => App\Models\Contact::class,
],

74
config/breadcrumbs.php Normal file
View File

@ -0,0 +1,74 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| View Name
|--------------------------------------------------------------------------
|
| Choose a view to display when Breadcrumbs::render() is called.
| Built in templates are:
|
| - 'breadcrumbs::bootstrap4' - Bootstrap 4
| - 'breadcrumbs::bootstrap3' - Bootstrap 3
| - 'breadcrumbs::bootstrap2' - Bootstrap 2
| - 'breadcrumbs::bulma' - Bulma
| - 'breadcrumbs::foundation6' - Foundation 6
| - 'breadcrumbs::materialize' - Materialize
| - 'breadcrumbs::json-ld' - JSON-LD Structured Data
|
| Or a custom view, e.g. '_partials/breadcrumbs'.
|
*/
'view' => 'breadcrumbs::bootstrap4',
/*
|--------------------------------------------------------------------------
| Breadcrumbs File(s)
|--------------------------------------------------------------------------
|
| The file(s) where breadcrumbs are defined. e.g.
|
| - base_path('routes/breadcrumbs.php')
| - glob(base_path('breadcrumbs/*.php'))
|
*/
'files' => base_path('routes/breadcrumbs.php'),
/*
|--------------------------------------------------------------------------
| Exceptions
|--------------------------------------------------------------------------
|
| Determine when to throw an exception.
|
*/
// When route-bound breadcrumbs are used but the current route doesn't have a name (UnnamedRouteException)
'unnamed-route-exception' => true,
// When route-bound breadcrumbs are used and the matching breadcrumb doesn't exist (InvalidBreadcrumbException)
'missing-route-bound-breadcrumb-exception' => true,
// When a named breadcrumb is used but doesn't exist (InvalidBreadcrumbException)
'invalid-named-breadcrumb-exception' => true,
/*
|--------------------------------------------------------------------------
| Classes
|--------------------------------------------------------------------------
|
| Subclass the default classes for more advanced customisations.
|
*/
// Manager
'manager-class' => DaveJamesMiller\Breadcrumbs\BreadcrumbsManager::class,
// Generator
'generator-class' => DaveJamesMiller\Breadcrumbs\BreadcrumbsGenerator::class,
];

View File

@ -15,7 +15,9 @@ use Faker\Generator as Faker;
$factory->define(App\Models\User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'first_name' => $faker->name,
'last_name' => $faker->name,
'phone' => $faker->phoneNumber,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret

View File

@ -13,7 +13,7 @@ class CreateUsersTable extends Migration
*/
public function up()
{
require_once app_path() . '/Constants.php';
// require_once app_path() . '/Constants.php';
Schema::create('countries', function ($table) {
$table->increments('id');
@ -85,7 +85,7 @@ class CreateUsersTable extends Migration
$table->unsignedInteger('timezone_id')->nullable();
$table->unsignedInteger('currency_id')->nullable();
$table->string('ip');
$table->string('account_key')->unique();
$table->string('account_key',100)->unique();
$table->timestamp('last_login')->nullable();
$table->string('address1')->nullable();
$table->string('address2')->nullable();
@ -132,7 +132,7 @@ class CreateUsersTable extends Migration
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('phone')->nullable();
$table->string('email')->unique();
$table->string('email',100)->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('confirmation_code')->nullable();
$table->boolean('registered')->default(false);
@ -140,7 +140,7 @@ class CreateUsersTable extends Migration
$table->integer('theme_id')->nullable();
$table->smallInteger('failed_logins')->nullable();
$table->string('referral_code')->nullable();
$table->string('oauth_user_id')->nullable()->unique();
$table->string('oauth_user_id',100)->nullable()->unique();
$table->unsignedInteger('oauth_provider_id')->nullable()->unique();
$table->string('google_2fa_secret')->nullable();
$table->string('accepted_terms_version')->nullable();
@ -218,13 +218,13 @@ class CreateUsersTable extends Migration
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('phone')->nullable();
$table->string('email')->unique(); //todo handle one contact across many accounts ?
$table->string('email',100);
$table->timestamp('email_verified_at')->nullable();
$table->string('confirmation_code')->nullable();
$table->boolean('registered')->default(false);
$table->boolean('confirmed')->default(false);
$table->smallInteger('failed_logins')->nullable();
$table->string('oauth_user_id')->nullable()->unique();
$table->string('oauth_user_id',100)->nullable()->unique();
$table->unsignedInteger('oauth_provider_id')->nullable()->unique();
$table->string('google_2fa_secret')->nullable();
$table->string('accepted_terms_version')->nullable();
@ -239,7 +239,7 @@ class CreateUsersTable extends Migration
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
$table->unique(['account_id', 'email']);
});
@ -308,7 +308,7 @@ class CreateUsersTable extends Migration
$t->unsignedInteger('user_id');
$t->unsignedInteger('contact_id');
$t->unsignedInteger('invoice_id')->index();
$t->string('invitation_key')->index()->unique();
$t->string('invitation_key',100)->index()->unique();
$t->timestamps();
$t->softDeletes();
@ -330,7 +330,7 @@ class CreateUsersTable extends Migration
$t->timestamps();
$t->softDeletes();
$t->string('name')->unique();
$t->string('name',100)->unique();
$t->decimal('rate', 13, 3);
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');

View File

@ -17,7 +17,7 @@ class UsersTableSeeder extends Seeder
public function run()
{
require_once app_path() . '/Constants.php';
//require_once app_path() . '/Constants.php';
$this->command->info('Running UserTableSeeder');

View File

@ -13,8 +13,8 @@
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
<testsuite name="Integration">
<directory suffix="Test.php">./tests/Integration</directory>
</testsuite>
</testsuites>
<filter>

17
public/js/ninja.js vendored

File diff suppressed because one or more lines are too long

2
resources/js/app.js vendored
View File

@ -5,7 +5,7 @@
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
//require('./bootstrap');
window.Vue = require('vue');

View File

@ -3102,7 +3102,8 @@ $LANG = array(
'last30_days' => 'Last 30 days',
'custom_js' => 'Custom JS',
'adjust_fee_percent_help' => 'Adjust percent to account for fee',
'email_already_register' => 'This email is already linked to an account',
'create_account' => 'Create Account',
);
return $LANG;

View File

@ -23,7 +23,7 @@
@if ($errors->has('email'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email') }}</strong>
</span>
</span>
@endif
</div>

View File

@ -23,7 +23,7 @@
<div class="list-group-item list-group-item-accent-secondary bg-light text-center font-weight-bold text-muted text-uppercase small">Today</div>
<div class="list-group-item list-group-item-accent-warning list-group-item-divider">
<div class="avatar float-right">
<img class="img-avatar" src="img/avatars/7.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div>Meeting with
<strong>Lucas</strong>
@ -35,7 +35,7 @@
</div>
<div class="list-group-item list-group-item-accent-info">
<div class="avatar float-right">
<img class="img-avatar" src="img/avatars/4.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div>Skype with
<strong>Megan</strong>
@ -56,19 +56,19 @@
<i class="icon-home"></i>  creativeLabs HQ</small>
<div class="avatars-stack mt-2">
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/2.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/3.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/4.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/5.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/6.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
</div>
</div>
@ -90,25 +90,25 @@
<i class="icon-home"></i>  creativeLabs HQ</small>
<div class="avatars-stack mt-2">
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/2.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/3.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/4.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/5.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/6.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/7.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
<div class="avatar avatar-xs">
<img class="img-avatar" src="img/avatars/8.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
</div>
</div>
</div>
@ -118,7 +118,7 @@
<div class="message">
<div class="py-3 pb-5 mr-3 float-left">
<div class="avatar">
<img class="img-avatar" src="img/avatars/7.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
<span class="avatar-status badge-success"></span>
</div>
</div>
@ -133,7 +133,7 @@
<div class="message">
<div class="py-3 pb-5 mr-3 float-left">
<div class="avatar">
<img class="img-avatar" src="img/avatars/7.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
<span class="avatar-status badge-success"></span>
</div>
</div>
@ -148,7 +148,7 @@
<div class="message">
<div class="py-3 pb-5 mr-3 float-left">
<div class="avatar">
<img class="img-avatar" src="img/avatars/7.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
<span class="avatar-status badge-success"></span>
</div>
</div>
@ -163,7 +163,7 @@
<div class="message">
<div class="py-3 pb-5 mr-3 float-left">
<div class="avatar">
<img class="img-avatar" src="img/avatars/7.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
<span class="avatar-status badge-success"></span>
</div>
</div>
@ -178,7 +178,7 @@
<div class="message">
<div class="py-3 pb-5 mr-3 float-left">
<div class="avatar">
<img class="img-avatar" src="img/avatars/7.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com">
<span class="avatar-status badge-success"></span>
</div>
</div>

View File

@ -12,25 +12,7 @@
@section('body')
<main class="main">
<!-- Breadcrumb-->
<ol class="breadcrumb">
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item">
<a href="#">Admin</a>
</li>
<li class="breadcrumb-item active">Dashboard</li>
<!-- Breadcrumb Menu-->
<li class="breadcrumb-menu d-md-down-none">
<div class="btn-group" role="group" aria-label="Button group">
<a class="btn" href="#">
<i class="icon-speech"></i>
</a>
<a class="btn" href="./">
<i class="icon-graph"></i>  Dashboard</a>
<a class="btn" href="#">
<i class="icon-settings"></i>  Settings</a>
</div>
</li>
</ol>
{{ Breadcrumbs::render('dashboard') }}
<div class="container-fluid">
</div>

View File

@ -1,11 +1,11 @@
<footer class="app-footer">
<div>
<a href="https://coreui.io">CoreUI</a>
<span>&copy; 2018 creativeLabs.</span>
<a href="https://coreui.io">Invoice Ninja</a>
<span>&copy; 2018 Invoice Ninja LLC.</span>
</div>
<div class="ml-auto">
<span>Powered by</span>
<a href="https://coreui.io">CoreUI</a>
<a href="https://invioceninja.com">InvoiceNinja</a>
</div>
</footer>

View File

@ -3,48 +3,88 @@
<button class="navbar-toggler sidebar-toggler d-lg-none mr-auto" type="button" data-toggle="sidebar-show">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">
<a class="navbar-brand" href="https://invoiceninja.com">
<img class="navbar-brand-full" src="images/logo.png" width="50" height="50" alt="Invoice Ninja Logo">
<img class="navbar-brand-minimized" src="images/logo.png" width="30" height="30" alt="Invoice Ninja Logo">
</a>
<button class="sidebar-minimizer brand-minimizer" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<ul class="nav navbar-nav d-md-down-none">
<li class="nav-item px-3">
<a class="nav-link" href="#">Dashboard</a>
</li>
<li class="nav-item px-3">
<a class="nav-link" href="#">Users</a>
</li>
<li class="nav-item px-3">
<a class="nav-link" href="#">Settings</a>
</li>
</ul>
<ul class="nav navbar-nav ml-auto">
<li class="nav-item d-md-down-none">
<a class="nav-link" href="#">
<i class="fa fa-user"></i>
<span class="badge badge-pill badge-danger">5</span>
</a>
</li>
<li class="nav-item d-md-down-none">
<a class="nav-link" href="#">
<li class="nav-item dropdown d-md-down-none">
<a class="nav-link" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
<i class="icon-list"></i>
<span class="badge badge-pill badge-warning">15</span>
</a>
<div class="dropdown-menu dropdown-menu-right dropdown-menu-lg">
<div class="dropdown-header text-center">
<strong>You have 5 pending tasks</strong>
</div>
<a class="dropdown-item" href="#">
<div class="small mb-1">Mr Miyagi todos
<span class="float-right">
<strong>0%</strong>
</span>
</div>
<span class="progress progress-xs">
<div class="progress-bar bg-info" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</span>
</a>
<a class="dropdown-item" href="#">
<div class="small mb-1">First, wash all car.
<span class="float-right">
<strong>25%</strong>
</span>
</div>
<span class="progress progress-xs">
<div class="progress-bar bg-danger" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
</span>
</a>
<a class="dropdown-item" href="#">
<div class="small mb-1">Then wax. Wax on...
<span class="float-right">
<strong>50%</strong>
</span>
</div>
<span class="progress progress-xs">
<div class="progress-bar bg-warning" role="progressbar" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
</span>
</a>
<a class="dropdown-item" href="#">
<div class="small mb-1">No questions!
<span class="float-right">
<strong>75%</strong>
</span>
</div>
<span class="progress progress-xs">
<div class="progress-bar bg-info" role="progressbar" style="width: 75%" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</span>
</a>
<a class="dropdown-item" href="#">
<div class="small mb-1">Wax on... wax off. Wax on... wax off.
<span class="float-right">
<strong>100%</strong>
</span>
</div>
<span class="progress progress-xs">
<div class="progress-bar bg-success" role="progressbar" style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
</span>
</a>
<a class="dropdown-item text-center" href="#">
<strong>View all tasks</strong>
</a>
</div>
</li>
<li class="nav-item d-md-down-none">
<a class="nav-link" href="#">
<i class="icon-location-pin"></i>
</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
<img class="img-avatar" src="img/avatars/6.jpg" alt="admin@bootstrapmaster.com">
<img class="img-avatar" src="images/logo.png" alt="admin@bootstrapmaster.com"> David Bomba
</a>
<div class="dropdown-menu dropdown-menu-right">
<!-- if multiple accounts exist, loop through here and display
<div class="dropdown-header text-center">
<strong>Account</strong>
<strong>Accounts</strong>
</div>
<a class="dropdown-item" href="#">
<i class="fa fa-bell-o"></i> Updates
@ -62,25 +102,17 @@
<i class="fa fa-comments"></i> Comments
<span class="badge badge-warning">42</span>
</a>
<!-- if multiple accounts exist, loop through here and display -->
<div class="dropdown-header text-center">
<strong>Settings</strong>
</div>
<a class="dropdown-item" href="#">
<i class="fa fa-user"></i> Profile</a>
<a class="dropdown-item" href="#">
<i class="fa fa-wrench"></i> Settings</a>
<a class="dropdown-item" href="#">
<i class="fa fa-usd"></i> Payments
<span class="badge badge-secondary">42</span>
</a>
<a class="dropdown-item" href="#">
<i class="fa fa-file"></i> Projects
<span class="badge badge-primary">42</span>
</a>
<div class="divider"></div>
<a class="dropdown-item" href="#">
<i class="fa fa-shield"></i> Lock Account</a>
<a class="dropdown-item" href="#">
<a class="dropdown-item" href="{{ route('user.settings') }}">
<i class="fa fa-wrench"></i> @lang('texts.settings')</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{{ route('user.logout') }}">
<i class="fa fa-lock"></i> Logout</a>
</div>
</li>

View File

@ -23,7 +23,7 @@
@endif
<meta charset="utf-8">
<title>@yield('meta_title') | {{ config('app.name') }}</title>
<title>@yield('meta_title', 'Invoice Ninja') | {{ config('app.name') }}</title>
<meta name="description" content="@yield('meta_description')"/>
<link href="{{ asset('favicon.png') }}" rel="shortcut icon" type="image/png">
@ -50,15 +50,15 @@
-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="keyword" content="Bootstrap,Admin,Template,Open,Source,jQuery,CSS,HTML,RWD,Dashboard">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="https://unpkg.com/@coreui/icons/css/coreui-icons.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.4.1/css/simple-line-icons.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<link rel="canonical" href="{{ config('ninja.app_url') }}/{{ request()->path() }}"/>
<link rel="stylesheet" href="{{ mix('/css/ninja.css') }}">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src=" {{ mix('/js/ninja.js') }}"></script>
@yield('head')

View File

@ -1,201 +1,71 @@
<div class="sidebar">
<nav class="sidebar-nav">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="index.html">
<i class="nav-icon icon-speedometer"></i> Dashboard
<span class="badge badge-primary">NEW</span>
<li class="nav-item ">
<a class="nav-link" href="{{ route('user.dashboard') }}">
<i class="nav-icon icon-speedometer"></i> @lang('texts.dashboard')
</a>
</li>
<li class="nav-title">Theme</li>
<li class="nav-item">
<a class="nav-link" href="colors.html">
<i class="nav-icon icon-drop"></i> Colors</a>
<i class="nav-icon icon-user"></i> @lang('texts.clients')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-pencil"></i> Typography</a>
</li>
<li class="nav-title">Components</li>
<li class="nav-item nav-dropdown">
<a class="nav-link nav-dropdown-toggle" href="#">
<i class="nav-icon icon-puzzle"></i> Base</a>
<ul class="nav-dropdown-items">
<li class="nav-item">
<a class="nav-link" href="base/breadcrumb.html">
<i class="nav-icon icon-puzzle"></i> Breadcrumb</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/cards.html">
<i class="nav-icon icon-puzzle"></i> Cards</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/carousel.html">
<i class="nav-icon icon-puzzle"></i> Carousel</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/collapse.html">
<i class="nav-icon icon-puzzle"></i> Collapse</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/forms.html">
<i class="nav-icon icon-puzzle"></i> Forms</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/jumbotron.html">
<i class="nav-icon icon-puzzle"></i> Jumbotron</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/list-group.html">
<i class="nav-icon icon-puzzle"></i> List group</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/navs.html">
<i class="nav-icon icon-puzzle"></i> Navs</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/pagination.html">
<i class="nav-icon icon-puzzle"></i> Pagination</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/popovers.html">
<i class="nav-icon icon-puzzle"></i> Popovers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/progress.html">
<i class="nav-icon icon-puzzle"></i> Progress</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/scrollspy.html">
<i class="nav-icon icon-puzzle"></i> Scrollspy</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/switches.html">
<i class="nav-icon icon-puzzle"></i> Switches</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/tables.html">
<i class="nav-icon icon-puzzle"></i> Tables</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/tabs.html">
<i class="nav-icon icon-puzzle"></i> Tabs</a>
</li>
<li class="nav-item">
<a class="nav-link" href="base/tooltips.html">
<i class="nav-icon icon-puzzle"></i> Tooltips</a>
</li>
</ul>
</li>
<li class="nav-item nav-dropdown">
<a class="nav-link nav-dropdown-toggle" href="#">
<i class="nav-icon icon-cursor"></i> Buttons</a>
<ul class="nav-dropdown-items">
<li class="nav-item">
<a class="nav-link" href="buttons/buttons.html">
<i class="nav-icon icon-cursor"></i> Buttons</a>
</li>
<li class="nav-item">
<a class="nav-link" href="buttons/button-group.html">
<i class="nav-icon icon-cursor"></i> Buttons Group</a>
</li>
<li class="nav-item">
<a class="nav-link" href="buttons/dropdowns.html">
<i class="nav-icon icon-cursor"></i> Dropdowns</a>
</li>
<li class="nav-item">
<a class="nav-link" href="buttons/brand-buttons.html">
<i class="nav-icon icon-cursor"></i> Brand Buttons</a>
</li>
</ul>
<i class="nav-icon icon-present"></i> @lang('texts.products')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="charts.html">
<i class="nav-icon icon-pie-chart"></i> Charts</a>
</li>
<li class="nav-item nav-dropdown">
<a class="nav-link nav-dropdown-toggle" href="#">
<i class="nav-icon icon-star"></i> Icons</a>
<ul class="nav-dropdown-items">
<li class="nav-item">
<a class="nav-link" href="icons/coreui-icons.html">
<i class="nav-icon icon-star"></i> CoreUI Icons
<span class="badge badge-success">NEW</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="icons/flags.html">
<i class="nav-icon icon-star"></i> Flags</a>
</li>
<li class="nav-item">
<a class="nav-link" href="icons/font-awesome.html">
<i class="nav-icon icon-star"></i> Font Awesome
<span class="badge badge-secondary">4.7</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="icons/simple-line-icons.html">
<i class="nav-icon icon-star"></i> Simple Line Icons</a>
</li>
</ul>
</li>
<li class="nav-item nav-dropdown">
<a class="nav-link nav-dropdown-toggle" href="#">
<i class="nav-icon icon-bell"></i> Notifications</a>
<ul class="nav-dropdown-items">
<li class="nav-item">
<a class="nav-link" href="notifications/alerts.html">
<i class="nav-icon icon-bell"></i> Alerts</a>
</li>
<li class="nav-item">
<a class="nav-link" href="notifications/badge.html">
<i class="nav-icon icon-bell"></i> Badge</a>
</li>
<li class="nav-item">
<a class="nav-link" href="notifications/modals.html">
<i class="nav-icon icon-bell"></i> Modals</a>
</li>
</ul>
<a class="nav-link" href="{{ route('invoices.index') }}">
<i class="nav-icon icon-notebook"></i> @lang('texts.invoices')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="widgets.html">
<i class="nav-icon icon-calculator"></i> Widgets
<span class="badge badge-primary">NEW</span>
</a>
</li>
<li class="divider"></li>
<li class="nav-title">Extras</li>
<li class="nav-item nav-dropdown">
<a class="nav-link nav-dropdown-toggle" href="#">
<i class="nav-icon icon-star"></i> Pages</a>
<ul class="nav-dropdown-items">
<li class="nav-item">
<a class="nav-link" href="login.html" target="_top">
<i class="nav-icon icon-star"></i> Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="register.html" target="_top">
<i class="nav-icon icon-star"></i> Register</a>
</li>
<li class="nav-item">
<a class="nav-link" href="404.html" target="_top">
<i class="nav-icon icon-star"></i> Error 404</a>
</li>
<li class="nav-item">
<a class="nav-link" href="500.html" target="_top">
<i class="nav-icon icon-star"></i> Error 500</a>
</li>
</ul>
</li>
<li class="nav-item mt-auto">
<a class="nav-link nav-link-success" href="https://coreui.io" target="_top">
<i class="nav-icon icon-cloud-download"></i> Download CoreUI</a>
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-wallet"></i> @lang('texts.payments')</a>
</li>
<li class="nav-item">
<a class="nav-link nav-link-danger" href="https://coreui.io/pro/" target="_top">
<i class="nav-icon icon-layers"></i> Try CoreUI
<strong>PRO</strong>
</a>
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-docs"></i> @lang('texts.recurring')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-badge"></i> @lang('texts.credits')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-vector"></i> @lang('texts.quotes')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-wrench"></i> @lang('texts.projects')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-grid"></i> @lang('texts.tasks')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-envelope-open"></i> @lang('texts.expenses')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-bell"></i> @lang('texts.vendors')</a>
</li>
<li class="nav-item">
<a class="nav-link" href="typography.html">
<i class="nav-icon icon-printer"></i> @lang('texts.reports')</a>
</li>
</ul>
</nav>

View File

@ -0,0 +1,81 @@
@extends('layouts.master')
@section('body')
<body class="app flex-row align-items-center">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mx-4">
<div class="card-body p-4">
<span class="align-items-center" style="width:100%; display: block; text-align: center; padding:30px;">
<img src="images/logo.png" width="100px" height="100px">
</span>
<h1 style="text-align: center;">@lang('texts.login_create_an_account')</h1>
<p class="text-muted"></p>
{{ html()->form('POST', route('signup.submit'))->open() }}
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">@</span>
</div>
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" placeholder="@lang('texts.email')" required autofocus>
@if ($errors->has('email'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
@if ($errors->has('email2'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email2') }}</strong>
</span>
@endif
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="icon-lock"></i>
</span>
</div>
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" placeholder="@lang('texts.password')" required>
@if ($errors->has('password'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
<button class="btn btn-block btn-success" type="submit">@lang('texts.create_account')</button>
</div>
{{ html()->form()->close() }}
<div class="card-footer p-4">
<div class="row">
<div class="col-6">
<button class="btn btn-block btn-facebook" type="button">
<span>facebook</span>
</button>
</div>
<div class="col-6">
<button class="btn btn-block btn-twitter" type="button">
<span>twitter</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
</body>
</html>

6
routes/breadcrumbs.php Normal file
View File

@ -0,0 +1,6 @@
<?php
// Home
Breadcrumbs::for('dashboard', function ($trail) {
$trail->push(trans('texts.dashboard'), route('user.dashboard'));
});

View File

@ -29,7 +29,9 @@ Open Routes
//Route::get('/', 'HomeController@index')->name('default');
Route::redirect('/', '/login', 301);
Route::get('/signup', 'HomeController@signup')->name('signup');
Route::post('/process_signup', 'HomeController@processSignup')->name('signup.submit');
Route::get('/contact/login', 'Auth\ContactLoginController@showLoginForm')->name('contact.login');
Route::post('/contact/login', 'Auth\ContactLoginController@login')->name('contact.login.submit');
@ -40,9 +42,10 @@ Authenticated User Routes
*/
Route::group(['middleware' => ['auth:user']], function () {
Route::get('/home', 'HomeController@user')->name('user.dashboard');
Route::get('/dashboard', 'HomeController@user')->name('user.dashboard');
Route::get('/logout', 'Auth\LoginController@logout')->name('user.logout');
Route::resource('/invoices', 'InvoiceController'); // name = (invoices. index / create / show / update / destroy / edit
Route::get('/settings', 'SettingsController@index')->name('user.settings');
});

View File

@ -0,0 +1,65 @@
<?php
namespace Tests\Unit;
use App\Http\ValidationRules\UniqueUserRule;
use App\Models\User;
use Illuminate\Foundation\Testing\Concerns\InteractsWithDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
/**
* @test
* @covers App\Utils\NumberHelper
*/
class UniqueEmailTest extends TestCase
{
use InteractsWithDatabase;
protected $rule;
public function setUp()
{
parent::setUp();
if (config('auth.providers.users.driver') == 'eloquent')
$this->markTestSkipped('Multi DB not enabled - skipping');
DB::connection('db-ninja-1')->table('users')->delete();
DB::connection('db-ninja-2')->table('users')->delete();
$this->rule = new UniqueUserRule();
$user = [
'first_name' => 'user_db_1',
'email' => 'user@example.com',
'password' => Hash::make('password'),
];
User::on('db-ninja-1')->create($user);
User::on('db-ninja-2')->create($user);
}
public function test_unique_emails_detected_on_database()
{
$this->assertFalse($this->rule->passes('email', 'user@example.com'));
}
public function test_no_unique_emails_detected()
{
$this->assertTrue($this->rule->passes('email', 'nohit@example.com'));
}
public function tearDown()
{
// DB::connection('db-ninja-1')->table('users')->delete();
// DB::connection('db-ninja-2')->table('users')->delete();
}
}

View File

@ -1,34 +0,0 @@
<?php
namespace Tests\Unit;
use App\Utils\NumberHelper;
use Tests\TestCase;
/**
* @test
* @covers App\Utils\NumberHelper
*/
class NumberTest extends TestCase
{
public function testRoundingThreeLow()
{
$rounded = NumberHelper::roundValue(3.144444444444, 3);
$this->assertEquals(3.144, $rounded);
}
public function testRoundingThreeHigh()
{
$rounded = NumberHelper::roundValue(3.144944444444, 3);
$this->assertEquals(3.145, $rounded);
}
public function testRoundingTwoLow()
{
$rounded = NumberHelper::roundValue(2.145);
$this->assertEquals(2.15, $rounded);
}
}

View File

@ -11,6 +11,8 @@ use Tests\TestCase;
*/
class NumberTest extends TestCase
{
public function testRoundingThreeLow()
{
$rounded = NumberHelper::roundValue(3.144444444444, 3);

1
webpack.mix.js vendored
View File

@ -15,7 +15,6 @@ mix.js('resources/js/app.js', 'public/js/vendor');
mix.scripts([
'node_modules/@coreui/coreui/dist/js/coreui.js',
'node_modules/bootstrap/dist/js/bootstrap.js',
'public/js/vendor/app.js'
], 'public/js/ninja.js');