Update app to match latest Laravel defaults and best practices
This commit is contained in:
parent
ee2716ee4c
commit
4e5c3c938f
|
@ -9,13 +9,15 @@ return PhpCsFixer\Config::create()
|
|||
'@PHP70Migration' => true,
|
||||
'@PHP71Migration' => true,
|
||||
'@PSR2' => true,
|
||||
// '@Symfony' => true,
|
||||
'@Symfony' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
'increment_style' => ['style' => 'post'],
|
||||
'no_multiline_whitespace_before_semicolons' => true,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'ordered_imports' => ['sortAlgorithm' => 'alpha'],
|
||||
'php_unit_method_casing' => ['case' => 'snake_case'],
|
||||
'semicolon_after_instruction' => false,
|
||||
'single_line_throw' => false,
|
||||
'strict_comparison' => true,
|
||||
'yoda_style' => false,
|
||||
]);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
php:
|
||||
preset: laravel
|
||||
disabled:
|
||||
- no_unused_imports
|
||||
finder:
|
||||
not-name:
|
||||
- index.php
|
||||
- server.php
|
||||
js:
|
||||
finder:
|
||||
not-name:
|
||||
- webpack.mix.js
|
||||
css: true
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Exceptions;
|
||||
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
|
@ -21,6 +22,7 @@ class Handler extends ExceptionHandler
|
|||
* @var array
|
||||
*/
|
||||
protected $dontFlash = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
@ -32,6 +34,8 @@ class Handler extends ExceptionHandler
|
|||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
$this->reportable(function (Throwable $e) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,18 +19,16 @@ class ContactsController extends Controller
|
|||
->with('organization')
|
||||
->orderByName()
|
||||
->filter(Request::only('search', 'trashed'))
|
||||
->paginate()
|
||||
->paginate(10)
|
||||
->withQueryString()
|
||||
->through(function ($contact) {
|
||||
return [
|
||||
'id' => $contact->id,
|
||||
'name' => $contact->name,
|
||||
'phone' => $contact->phone,
|
||||
'city' => $contact->city,
|
||||
'deleted_at' => $contact->deleted_at,
|
||||
'organization' => $contact->organization ? $contact->organization->only('name') : null,
|
||||
];
|
||||
}),
|
||||
->through(fn ($contact) => [
|
||||
'id' => $contact->id,
|
||||
'name' => $contact->name,
|
||||
'phone' => $contact->phone,
|
||||
'city' => $contact->city,
|
||||
'deleted_at' => $contact->deleted_at,
|
||||
'organization' => $contact->organization ? $contact->organization->only('name') : null,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -99,9 +97,10 @@ class ContactsController extends Controller
|
|||
Request::validate([
|
||||
'first_name' => ['required', 'max:50'],
|
||||
'last_name' => ['required', 'max:50'],
|
||||
'organization_id' => ['nullable', Rule::exists('organizations', 'id')->where(function ($query) {
|
||||
$query->where('account_id', Auth::user()->account_id);
|
||||
})],
|
||||
'organization_id' => [
|
||||
'nullable',
|
||||
Rule::exists('organizations', 'id')->where(fn ($query) => $query->where('account_id', Auth::user()->account_id)),
|
||||
],
|
||||
'email' => ['nullable', 'max:50', 'email'],
|
||||
'phone' => ['nullable', 'max:50'],
|
||||
'address' => ['nullable', 'max:150'],
|
||||
|
|
|
@ -9,5 +9,7 @@ use Illuminate\Routing\Controller as BaseController;
|
|||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
}
|
||||
|
|
|
@ -17,17 +17,15 @@ class OrganizationsController extends Controller
|
|||
'organizations' => Auth::user()->account->organizations()
|
||||
->orderBy('name')
|
||||
->filter(Request::only('search', 'trashed'))
|
||||
->paginate()
|
||||
->paginate(10)
|
||||
->withQueryString()
|
||||
->through(function ($organization) {
|
||||
return [
|
||||
'id' => $organization->id,
|
||||
'name' => $organization->name,
|
||||
'phone' => $organization->phone,
|
||||
'city' => $organization->city,
|
||||
'deleted_at' => $organization->deleted_at,
|
||||
];
|
||||
}),
|
||||
->through(fn ($organization) => [
|
||||
'id' => $organization->id,
|
||||
'name' => $organization->name,
|
||||
'phone' => $organization->phone,
|
||||
'city' => $organization->city,
|
||||
'deleted_at' => $organization->deleted_at,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,16 +20,14 @@ class UsersController extends Controller
|
|||
->orderByName()
|
||||
->filter(Request::only('search', 'role', 'trashed'))
|
||||
->get()
|
||||
->transform(function ($user) {
|
||||
return [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'email' => $user->email,
|
||||
'owner' => $user->owner,
|
||||
'photo' => $user->photoUrl(['w' => 40, 'h' => 40, 'fit' => 'crop']),
|
||||
'deleted_at' => $user->deleted_at,
|
||||
];
|
||||
}),
|
||||
->transform(fn ($user) => [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name,
|
||||
'email' => $user->email,
|
||||
'owner' => $user->owner,
|
||||
'photo' => $user->photoUrl(['w' => 40, 'h' => 40, 'fit' => 'crop']),
|
||||
'deleted_at' => $user->deleted_at,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Middleware;
|
|||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
|
@ -13,10 +14,10 @@ class RedirectIfAuthenticated
|
|||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string[]|null ...$guards
|
||||
* @param string|null ...$guards
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, ...$guards)
|
||||
public function handle(Request $request, Closure $next, ...$guards)
|
||||
{
|
||||
$guards = empty($guards) ? [null] : $guards;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ class TrimStrings extends Middleware
|
|||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
|
|
@ -10,7 +10,7 @@ class TrustProxies extends Middleware
|
|||
/**
|
||||
* The trusted proxies for this application.
|
||||
*
|
||||
* @var array
|
||||
* @var array|string|null
|
||||
*/
|
||||
protected $proxies = '**';
|
||||
|
||||
|
@ -19,5 +19,5 @@ class TrustProxies extends Middleware
|
|||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $headers = Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Account extends Model
|
||||
{
|
||||
public function users()
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Contact extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
public function organization()
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model as Eloquent;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
abstract class Model extends Eloquent
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $perPage = 10;
|
||||
|
||||
public function resolveRouteBinding($value, $field = null)
|
||||
{
|
||||
return in_array(SoftDeletes::class, class_uses($this))
|
||||
? $this->where($this->getRouteKeyName(), $value)->withTrashed()->first()
|
||||
: parent::resolveRouteBinding($value);
|
||||
}
|
||||
}
|
|
@ -2,10 +2,13 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Organization extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
public function contacts()
|
||||
|
|
|
@ -2,22 +2,24 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\Access\Authorizable;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use League\Glide\Server;
|
||||
|
||||
class User extends Model implements AuthenticatableContract, AuthorizableContract
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use SoftDeletes, Authenticatable, Authorizable;
|
||||
use HasFactory;
|
||||
use Notifiable;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $casts = [
|
||||
'owner' => 'boolean',
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function account()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use League\Glide\Server;
|
||||
|
@ -15,6 +16,8 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function register()
|
||||
{
|
||||
Model::unguard();
|
||||
|
||||
$this->app->bind(Server::class, function ($app) {
|
||||
return Server::create([
|
||||
'source' => Storage::getDriver(),
|
||||
|
|
|
@ -13,7 +13,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||
* @var array
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Model' => 'App\Policies\ModelPolicy',
|
||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,15 @@ class RouteServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public const HOME = '/';
|
||||
|
||||
/**
|
||||
* The controller namespace for the application.
|
||||
*
|
||||
* When present, controller route declarations will automatically be prefixed with this namespace.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
// protected $namespace = 'App\\Http\\Controllers';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, etc.
|
||||
*
|
||||
|
@ -29,12 +38,14 @@ class RouteServiceProvider extends ServiceProvider
|
|||
$this->configureRateLimiting();
|
||||
|
||||
$this->routes(function () {
|
||||
Route::middleware('web')
|
||||
->group(base_path('routes/web.php'));
|
||||
|
||||
Route::prefix('api')
|
||||
->middleware('api')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api.php'));
|
||||
|
||||
Route::middleware('web')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/web.php'));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -46,7 +57,7 @@ class RouteServiceProvider extends ServiceProvider
|
|||
protected function configureRateLimiting()
|
||||
{
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60);
|
||||
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,62 +2,43 @@
|
|||
"name": "laravel/laravel",
|
||||
"type": "project",
|
||||
"description": "The Laravel Framework.",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"keywords": ["framework", "laravel"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"ext-exif": "*",
|
||||
"ext-gd": "*",
|
||||
"facade/ignition": "^2.3.6",
|
||||
"fideloper/proxy": "^4.2",
|
||||
"fideloper/proxy": "^4.4",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"fzaninotto/faker": "^1.9.1",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"inertiajs/inertia-laravel": "^0.3",
|
||||
"laravel/framework": "^8.0",
|
||||
"laravel/legacy-factories": "^1.0",
|
||||
"laravel/tinker": "^2.0",
|
||||
"inertiajs/inertia-laravel": "^0.4",
|
||||
"laravel/framework": "^8.40",
|
||||
"laravel/tinker": "^2.5",
|
||||
"laravel/ui": "^2.0",
|
||||
"league/glide": "2.0.x-dev",
|
||||
"mockery/mockery": "^1.3.1",
|
||||
"nunomaduro/collision": "^5.0",
|
||||
"phpunit/phpunit": "^9.3",
|
||||
"tightenco/ziggy": "^0.8.0"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"dont-discover": []
|
||||
}
|
||||
"require-dev": {
|
||||
"facade/ignition": "^2.5",
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"laravel/sail": "^1.0.1",
|
||||
"mockery/mockery": "^1.4.2",
|
||||
"nunomaduro/collision": "^5.0",
|
||||
"phpunit/phpunit": "^9.3.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/"
|
||||
},
|
||||
"classmap": [
|
||||
"database/seeds",
|
||||
"database/factories"
|
||||
]
|
||||
"App\\": "app/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
"compile": [
|
||||
"npm run prod",
|
||||
"@php artisan migrate:fresh --seed"
|
||||
],
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
"@php artisan package:discover --ansi"
|
||||
|
@ -67,6 +48,21 @@
|
|||
],
|
||||
"post-create-project-cmd": [
|
||||
"@php artisan key:generate --ansi"
|
||||
],
|
||||
"compile": [
|
||||
"@php artisan migrate:fresh --seed"
|
||||
]
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"dont-discover": []
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -201,6 +201,7 @@ return [
|
|||
'Config' => Illuminate\Support\Facades\Config::class,
|
||||
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
||||
'Crypt' => Illuminate\Support\Facades\Crypt::class,
|
||||
'Date' => Illuminate\Support\Facades\Date::class,
|
||||
'DB' => Illuminate\Support\Facades\DB::class,
|
||||
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
||||
'Event' => Illuminate\Support\Facades\Event::class,
|
||||
|
@ -215,7 +216,7 @@ return [
|
|||
'Password' => Illuminate\Support\Facades\Password::class,
|
||||
'Queue' => Illuminate\Support\Facades\Queue::class,
|
||||
'Redirect' => Illuminate\Support\Facades\Redirect::class,
|
||||
'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||
// 'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||
'Request' => Illuminate\Support\Facades\Request::class,
|
||||
'Response' => Illuminate\Support\Facades\Response::class,
|
||||
'Route' => Illuminate\Support\Facades\Route::class,
|
||||
|
|
|
@ -11,7 +11,7 @@ return [
|
|||
| framework when an event needs to be broadcast. You may set this to
|
||||
| any of the connections defined in the "connections" array below.
|
||||
|
|
||||
| Supported: "pusher", "redis", "log", "null"
|
||||
| Supported: "pusher", "ably", "redis", "log", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
|
@ -41,6 +41,11 @@ return [
|
|||
],
|
||||
],
|
||||
|
||||
'ably' => [
|
||||
'driver' => 'ably',
|
||||
'key' => env('ABLY_KEY'),
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
|
|
|
@ -13,9 +13,6 @@ return [
|
|||
| using this caching library. This connection is used when another is
|
||||
| not explicitly specified when executing a given caching function.
|
||||
|
|
||||
| Supported: "apc", "array", "database", "file",
|
||||
| "memcached", "redis", "dynamodb"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('CACHE_DRIVER', 'file'),
|
||||
|
@ -29,6 +26,9 @@ return [
|
|||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
| Supported drivers: "apc", "array", "database", "file",
|
||||
| "memcached", "redis", "dynamodb", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
|
@ -46,6 +46,7 @@ return [
|
|||
'driver' => 'database',
|
||||
'table' => 'cache',
|
||||
'connection' => null,
|
||||
'lock_connection' => null,
|
||||
],
|
||||
|
||||
'file' => [
|
||||
|
@ -75,6 +76,7 @@ return [
|
|||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'cache',
|
||||
'lock_connection' => 'default',
|
||||
],
|
||||
|
||||
'dynamodb' => [
|
||||
|
|
|
@ -15,7 +15,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'paths' => ['api/*'],
|
||||
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
||||
|
||||
'allowed_methods' => ['*'],
|
||||
|
||||
|
|
|
@ -15,19 +15,6 @@ return [
|
|||
|
||||
'default' => env('FILESYSTEM_DRIVER', 'local'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cloud Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Many applications store files both locally and in the cloud. For this
|
||||
| reason, you may specify a default "cloud" driver here. This driver
|
||||
| will be bound as the Cloud disk implementation in the container.
|
||||
|
|
||||
*/
|
||||
|
||||
'cloud' => env('FILESYSTEM_CLOUD', 's3'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|
|
|
@ -44,13 +44,13 @@ return [
|
|||
'single' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => 'debug',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
],
|
||||
|
||||
'daily' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => 'debug',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'days' => 14,
|
||||
],
|
||||
|
||||
|
@ -59,12 +59,12 @@ return [
|
|||
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
||||
'username' => 'Laravel Log',
|
||||
'emoji' => ':boom:',
|
||||
'level' => 'critical',
|
||||
'level' => env('LOG_LEVEL', 'critical'),
|
||||
],
|
||||
|
||||
'papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => 'debug',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'handler' => SyslogUdpHandler::class,
|
||||
'handler_with' => [
|
||||
'host' => env('PAPERTRAIL_URL'),
|
||||
|
@ -74,6 +74,7 @@ return [
|
|||
|
||||
'stderr' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'handler' => StreamHandler::class,
|
||||
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||
'with' => [
|
||||
|
@ -83,12 +84,12 @@ return [
|
|||
|
||||
'syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'level' => 'debug',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
],
|
||||
|
||||
'errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'level' => 'debug',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
],
|
||||
|
||||
'null' => [
|
||||
|
|
|
@ -39,6 +39,7 @@ return [
|
|||
'table' => 'jobs',
|
||||
'queue' => 'default',
|
||||
'retry_after' => 90,
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'beanstalkd' => [
|
||||
|
@ -47,6 +48,7 @@ return [
|
|||
'queue' => 'default',
|
||||
'retry_after' => 90,
|
||||
'block_for' => 0,
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'sqs' => [
|
||||
|
@ -54,9 +56,10 @@ return [
|
|||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
|
||||
'queue' => env('SQS_QUEUE', 'your-queue-name'),
|
||||
'queue' => env('SQS_QUEUE', 'default'),
|
||||
'suffix' => env('SQS_SUFFIX'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
|
@ -65,6 +68,7 @@ return [
|
|||
'queue' => env('REDIS_QUEUE', 'default'),
|
||||
'retry_after' => 90,
|
||||
'block_for' => null,
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
],
|
||||
|
|
|
@ -1,17 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
namespace Database\Factories;
|
||||
|
||||
$factory->define(App\Models\Contact::class, function (Faker $faker) {
|
||||
return [
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'email' => $faker->unique()->safeEmail,
|
||||
'phone' => $faker->tollFreePhoneNumber,
|
||||
'address' => $faker->streetAddress,
|
||||
'city' => $faker->city,
|
||||
'region' => $faker->state,
|
||||
'country' => 'US',
|
||||
'postal_code' => $faker->postcode,
|
||||
];
|
||||
});
|
||||
use App\Models\Contact;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class ContactFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model = Contact::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'first_name' => $this->faker->firstName,
|
||||
'last_name' => $this->faker->lastName,
|
||||
'email' => $this->faker->unique()->safeEmail,
|
||||
'phone' => $this->faker->tollFreePhoneNumber,
|
||||
'address' => $this->faker->streetAddress,
|
||||
'city' => $this->faker->city,
|
||||
'region' => $this->faker->state,
|
||||
'country' => 'US',
|
||||
'postal_code' => $this->faker->postcode,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
namespace Database\Factories;
|
||||
|
||||
$factory->define(App\Models\Organization::class, function (Faker $faker) {
|
||||
return [
|
||||
'name' => $faker->company,
|
||||
'email' => $faker->companyEmail,
|
||||
'phone' => $faker->tollFreePhoneNumber,
|
||||
'address' => $faker->streetAddress,
|
||||
'city' => $faker->city,
|
||||
'region' => $faker->state,
|
||||
'country' => 'US',
|
||||
'postal_code' => $faker->postcode,
|
||||
];
|
||||
});
|
||||
use App\Models\Organization;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class OrganizationFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model = Organization::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->company,
|
||||
'email' => $this->faker->companyEmail,
|
||||
'phone' => $this->faker->tollFreePhoneNumber,
|
||||
'address' => $this->faker->streetAddress,
|
||||
'city' => $this->faker->city,
|
||||
'region' => $this->faker->state,
|
||||
'country' => 'US',
|
||||
'postal_code' => $this->faker->postcode,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,49 @@
|
|||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Model Factories
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This directory should contain each of the model factory definitions for
|
||||
| your application. Factories provide a convenient way to generate new
|
||||
| model instances for testing / seeding your application's database.
|
||||
|
|
||||
*/
|
||||
class UserFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model = User::class;
|
||||
|
||||
$factory->define(App\Models\User::class, function (Faker $faker) {
|
||||
return [
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'email' => $faker->unique()->safeEmail,
|
||||
'password' => 'secret',
|
||||
'remember_token' => Str::random(10),
|
||||
'owner' => false,
|
||||
];
|
||||
});
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'first_name' => $this->faker->firstName,
|
||||
'last_name' => $this->faker->lastName,
|
||||
'email' => $this->faker->unique()->safeEmail,
|
||||
'email_verified_at' => now(),
|
||||
'password' => 'secret',
|
||||
'remember_token' => Str::random(10),
|
||||
'owner' => false,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the model's email address should be unverified.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Factories\Factory
|
||||
*/
|
||||
public function unverified()
|
||||
{
|
||||
return $this->state(function (array $attributes) {
|
||||
return [
|
||||
'email_verified_at' => null,
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ class CreateUsersTable extends Migration
|
|||
$table->string('first_name', 25);
|
||||
$table->string('last_name', 25);
|
||||
$table->string('email', 50)->unique();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password')->nullable();
|
||||
$table->boolean('owner')->default(false);
|
||||
$table->string('photo_path', 100)->nullable();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Contact;
|
||||
use App\Models\Organization;
|
||||
|
@ -8,11 +10,16 @@ use Illuminate\Database\Seeder;
|
|||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$account = Account::create(['name' => 'Acme Corporation']);
|
||||
|
||||
factory(User::class)->create([
|
||||
User::factory()->create([
|
||||
'account_id' => $account->id,
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe',
|
||||
|
@ -20,12 +27,12 @@ class DatabaseSeeder extends Seeder
|
|||
'owner' => true,
|
||||
]);
|
||||
|
||||
factory(User::class, 5)->create(['account_id' => $account->id]);
|
||||
User::factory(5)->create(['account_id' => $account->id]);
|
||||
|
||||
$organizations = factory(Organization::class, 100)
|
||||
$organizations = Organization::factory(100)
|
||||
->create(['account_id' => $account->id]);
|
||||
|
||||
factory(Contact::class, 100)
|
||||
Contact::factory(100)
|
||||
->create(['account_id' => $account->id])
|
||||
->each(function ($contact) use ($organizations) {
|
||||
$contact->update(['organization_id' => $organizations->random()->id]);
|
|
@ -7,7 +7,8 @@
|
|||
"watch-poll": "mix watch -- --watch-options-poll=1000",
|
||||
"hot": "mix watch --hot",
|
||||
"prod": "npm run production",
|
||||
"production": "mix --production"
|
||||
"production": "mix --production",
|
||||
"heroku-postbuild": "npm run prod"
|
||||
},
|
||||
"dependencies": {
|
||||
"@inertiajs/inertia": "^0.8.5",
|
||||
|
|
|
@ -1,23 +1,33 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Laravel - A PHP Framework For Web Artisans
|
||||
*
|
||||
* @package Laravel
|
||||
* @author Taylor Otwell <taylor@laravel.com>
|
||||
*/
|
||||
use Illuminate\Contracts\Http\Kernel;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Check If The Application Is Under Maintenance
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the application is in maintenance / demo mode via the "down" command
|
||||
| we will load this file so that any pre-rendered content can be shown
|
||||
| instead of starting the framework, which could cause an exception.
|
||||
|
|
||||
*/
|
||||
|
||||
if (file_exists(__DIR__.'/../storage/framework/maintenance.php')) {
|
||||
require __DIR__.'/../storage/framework/maintenance.php';
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register The Auto Loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Composer provides a convenient, automatically generated class loader for
|
||||
| our application. We just need to utilize it! We'll simply require it
|
||||
| into the script here so that we don't have to worry about manual
|
||||
| loading any of our classes later on. It feels great to relax.
|
||||
| this application. We just need to utilize it! We'll simply require it
|
||||
| into the script here so we don't need to manually load our classes.
|
||||
|
|
||||
*/
|
||||
|
||||
|
@ -25,36 +35,21 @@ require __DIR__.'/../vendor/autoload.php';
|
|||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Turn On The Lights
|
||||
| Run The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| We need to illuminate PHP development, so let us turn on the lights.
|
||||
| This bootstraps the framework and gets it ready for use, then it
|
||||
| will load up this application so that we can run it and send
|
||||
| the responses back to the browser and delight our users.
|
||||
| Once we have the application, we can handle the incoming request using
|
||||
| the application's HTTP kernel. Then, we will send the response back
|
||||
| to this client's browser, allowing them to enjoy our application.
|
||||
|
|
||||
*/
|
||||
|
||||
$app = require_once __DIR__.'/../bootstrap/app.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Run The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Once we have the application, we can handle the incoming request
|
||||
| through the kernel, and send the associated response back to
|
||||
| the client's browser allowing them to enjoy the creative
|
||||
| and wonderful application we have prepared for them.
|
||||
|
|
||||
*/
|
||||
$kernel = $app->make(Kernel::class);
|
||||
|
||||
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
|
||||
|
||||
$response = $kernel->handle(
|
||||
$request = Illuminate\Http\Request::capture()
|
||||
);
|
||||
|
||||
$response->send();
|
||||
$response = tap($kernel->handle(
|
||||
$request = Request::capture()
|
||||
))->send();
|
||||
|
||||
$kernel->terminate($request, $response);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!--
|
||||
Rewrites requires Microsoft URL Rewrite Module for IIS
|
||||
Download: https://www.microsoft.com/en-us/download/details.aspx?id=47337
|
||||
Download: https://www.iis.net/downloads/microsoft/url-rewrite
|
||||
Debug Help: https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-failed-request-tracing-to-trace-rewrite-rules
|
||||
-->
|
||||
<configuration>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Contact;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
@ -16,77 +15,118 @@ class ContactsTest extends TestCase
|
|||
{
|
||||
parent::setUp();
|
||||
|
||||
$account = Account::create(['name' => 'Acme Corporation']);
|
||||
|
||||
$this->user = factory(User::class)->create([
|
||||
'account_id' => $account->id,
|
||||
$this->user = User::factory()->create([
|
||||
'account_id' => Account::create(['name' => 'Acme Corporation'])->id,
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe',
|
||||
'email' => 'johndoe@example.com',
|
||||
'owner' => true,
|
||||
]);
|
||||
|
||||
$organization = $this->user->account->organizations()->create(['name' => 'Example Organization Inc.']);
|
||||
|
||||
$this->user->account->contacts()->createMany([
|
||||
[
|
||||
'organization_id' => $organization->id,
|
||||
'first_name' => 'Martin',
|
||||
'last_name' => 'Abbott',
|
||||
'email' => 'martin.abbott@example.com',
|
||||
'phone' => '555-111-2222',
|
||||
'address' => '330 Glenda Shore',
|
||||
'city' => 'Murphyland',
|
||||
'region' => 'Tennessee',
|
||||
'country' => 'US',
|
||||
'postal_code' => '57851',
|
||||
], [
|
||||
'organization_id' => $organization->id,
|
||||
'first_name' => 'Lynn',
|
||||
'last_name' => 'Kub',
|
||||
'email' => 'lynn.kub@example.com',
|
||||
'phone' => '555-333-4444',
|
||||
'address' => '199 Connelly Turnpike',
|
||||
'city' => 'Woodstock',
|
||||
'region' => 'Colorado',
|
||||
'country' => 'US',
|
||||
'postal_code' => '11623',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_can_view_contacts()
|
||||
{
|
||||
$this->user->account->contacts()->saveMany(
|
||||
factory(Contact::class, 5)->make()
|
||||
);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/contacts')
|
||||
->assertStatus(200)
|
||||
->assertPropCount('contacts.data', 5)
|
||||
->assertPropValue('contacts.data', function ($contacts) {
|
||||
$this->assertEquals(
|
||||
['id', 'name', 'phone', 'city',
|
||||
'deleted_at', 'organization'],
|
||||
array_keys($contacts[0])
|
||||
);
|
||||
});
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Contacts/Index')
|
||||
->has('contacts.data', 2)
|
||||
->has('contacts.data.0', fn ($assert) => $assert
|
||||
->where('id', 1)
|
||||
->where('name', 'Martin Abbott')
|
||||
->where('phone', '555-111-2222')
|
||||
->where('city', 'Murphyland')
|
||||
->where('deleted_at', null)
|
||||
->has('organization', fn ($assert) => $assert
|
||||
->where('name', 'Example Organization Inc.')
|
||||
)
|
||||
)
|
||||
->has('contacts.data.1', fn ($assert) => $assert
|
||||
->where('id', 2)
|
||||
->where('name', 'Lynn Kub')
|
||||
->where('phone', '555-333-4444')
|
||||
->where('city', 'Woodstock')
|
||||
->where('deleted_at', null)
|
||||
->has('organization', fn ($assert) => $assert
|
||||
->where('name', 'Example Organization Inc.')
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_can_search_for_contacts()
|
||||
{
|
||||
$this->user->account->contacts()->saveMany(
|
||||
factory(Contact::class, 5)->make()
|
||||
)->first()->update([
|
||||
'first_name' => 'Greg',
|
||||
'last_name' => 'Andersson'
|
||||
]);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/contacts?search=Greg')
|
||||
->assertStatus(200)
|
||||
->assertPropValue('filters.search', 'Greg')
|
||||
->assertPropCount('contacts.data', 1)
|
||||
->assertPropValue('contacts.data', function ($contacts) {
|
||||
$this->assertEquals('Greg Andersson', $contacts[0]['name']);
|
||||
});
|
||||
->get('/contacts?search=Martin')
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Contacts/Index')
|
||||
->where('filters.search', 'Martin')
|
||||
->has('contacts.data', 1)
|
||||
->has('contacts.data.0', fn ($assert) => $assert
|
||||
->where('id', 1)
|
||||
->where('name', 'Martin Abbott')
|
||||
->where('phone', '555-111-2222')
|
||||
->where('city', 'Murphyland')
|
||||
->where('deleted_at', null)
|
||||
->has('organization', fn ($assert) => $assert
|
||||
->where('name', 'Example Organization Inc.')
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_cannot_view_deleted_contacts()
|
||||
{
|
||||
$this->user->account->contacts()->saveMany(
|
||||
factory(Contact::class, 5)->make()
|
||||
)->first()->delete();
|
||||
$this->user->account->contacts()->firstWhere('first_name', 'Martin')->delete();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/contacts')
|
||||
->assertStatus(200)
|
||||
->assertPropCount('contacts.data', 4);
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Contacts/Index')
|
||||
->has('contacts.data', 1)
|
||||
->where('contacts.data.0.name', 'Lynn Kub')
|
||||
);
|
||||
}
|
||||
|
||||
public function test_can_filter_to_view_deleted_contacts()
|
||||
{
|
||||
$this->user->account->contacts()->saveMany(
|
||||
factory(Contact::class, 5)->make()
|
||||
)->first()->delete();
|
||||
$this->user->account->contacts()->firstWhere('first_name', 'Martin')->delete();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/contacts?trashed=with')
|
||||
->assertStatus(200)
|
||||
->assertPropValue('filters.trashed', 'with')
|
||||
->assertPropCount('contacts.data', 5);
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Contacts/Index')
|
||||
->has('contacts.data', 2)
|
||||
->where('contacts.data.0.name', 'Martin Abbott')
|
||||
->where('contacts.data.1.name', 'Lynn Kub')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace Tests\Feature;
|
|||
|
||||
use App\Models\Account;
|
||||
use App\Models\User;
|
||||
use App\Models\Organization;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
@ -16,73 +15,103 @@ class OrganizationsTest extends TestCase
|
|||
{
|
||||
parent::setUp();
|
||||
|
||||
$account = Account::create(['name' => 'Acme Corporation']);
|
||||
|
||||
$this->user = factory(User::class)->create([
|
||||
'account_id' => $account->id,
|
||||
$this->user = User::factory()->create([
|
||||
'account_id' => Account::create(['name' => 'Acme Corporation'])->id,
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe',
|
||||
'email' => 'johndoe@example.com',
|
||||
'owner' => true,
|
||||
]);
|
||||
|
||||
$this->user->account->organizations()->createMany([
|
||||
[
|
||||
'name' => 'Apple',
|
||||
'email' => 'info@apple.com',
|
||||
'phone' => '647-943-4400',
|
||||
'address' => '1600-120 Bremner Blvd',
|
||||
'city' => 'Toronto',
|
||||
'region' => 'ON',
|
||||
'country' => 'CA',
|
||||
'postal_code' => 'M5J 0A8',
|
||||
], [
|
||||
'name' => 'Microsoft',
|
||||
'email' => 'info@microsoft.com',
|
||||
'phone' => '877-568-2495',
|
||||
'address' => 'One Microsoft Way',
|
||||
'city' => 'Redmond',
|
||||
'region' => 'WA',
|
||||
'country' => 'US',
|
||||
'postal_code' => '98052',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_can_view_organizations()
|
||||
{
|
||||
$this->user->account->organizations()->saveMany(
|
||||
factory(Organization::class, 5)->make()
|
||||
);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/organizations')
|
||||
->assertStatus(200)
|
||||
->assertPropCount('organizations.data', 5)
|
||||
->assertPropValue('organizations.data', function ($organizations) {
|
||||
$this->assertEquals(
|
||||
['id', 'name', 'phone', 'city', 'deleted_at'],
|
||||
array_keys($organizations[0])
|
||||
);
|
||||
});
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Organizations/Index')
|
||||
->has('organizations.data', 2)
|
||||
->has('organizations.data.0', fn ($assert) => $assert
|
||||
->where('id', 1)
|
||||
->where('name', 'Apple')
|
||||
->where('phone', '647-943-4400')
|
||||
->where('city', 'Toronto')
|
||||
->where('deleted_at', null)
|
||||
)
|
||||
->has('organizations.data.1', fn ($assert) => $assert
|
||||
->where('id', 2)
|
||||
->where('name', 'Microsoft')
|
||||
->where('phone', '877-568-2495')
|
||||
->where('city', 'Redmond')
|
||||
->where('deleted_at', null)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_can_search_for_organizations()
|
||||
{
|
||||
$this->user->account->organizations()->saveMany(
|
||||
factory(Organization::class, 5)->make()
|
||||
)->first()->update(['name' => 'Some Big Fancy Company Name']);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/organizations?search=Some Big Fancy Company Name')
|
||||
->assertStatus(200)
|
||||
->assertPropValue('filters.search', 'Some Big Fancy Company Name')
|
||||
->assertPropCount('organizations.data', 1)
|
||||
->assertPropValue('organizations.data', function ($organizations) {
|
||||
$this->assertEquals('Some Big Fancy Company Name', $organizations[0]['name']);
|
||||
});
|
||||
->get('/organizations?search=Apple')
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Organizations/Index')
|
||||
->where('filters.search', 'Apple')
|
||||
->has('organizations.data', 1)
|
||||
->has('organizations.data.0', fn ($assert) => $assert
|
||||
->where('id', 1)
|
||||
->where('name', 'Apple')
|
||||
->where('phone', '647-943-4400')
|
||||
->where('city', 'Toronto')
|
||||
->where('deleted_at', null)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_cannot_view_deleted_organizations()
|
||||
{
|
||||
$this->user->account->organizations()->saveMany(
|
||||
factory(Organization::class, 5)->make()
|
||||
)->first()->delete();
|
||||
$this->user->account->organizations()->firstWhere('name', 'Microsoft')->delete();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/organizations')
|
||||
->assertStatus(200)
|
||||
->assertPropCount('organizations.data', 4);
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Organizations/Index')
|
||||
->has('organizations.data', 1)
|
||||
->where('organizations.data.0.name', 'Apple')
|
||||
);
|
||||
}
|
||||
|
||||
public function test_can_filter_to_view_deleted_organizations()
|
||||
{
|
||||
$this->user->account->organizations()->saveMany(
|
||||
factory(Organization::class, 5)->make()
|
||||
)->first()->delete();
|
||||
$this->user->account->organizations()->firstWhere('name', 'Microsoft')->delete();
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->get('/organizations?trashed=with')
|
||||
->assertStatus(200)
|
||||
->assertPropValue('filters.trashed', 'with')
|
||||
->assertPropCount('organizations.data', 5);
|
||||
->assertInertia(fn ($assert) => $assert
|
||||
->component('Organizations/Index')
|
||||
->has('organizations.data', 2)
|
||||
->where('organizations.data.0.name', 'Apple')
|
||||
->where('organizations.data.1.name', 'Microsoft')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,52 +3,8 @@
|
|||
namespace Tests;
|
||||
|
||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Testing\TestResponse;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
{
|
||||
use CreatesApplication;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
TestResponse::macro('props', function ($key = null) {
|
||||
$props = json_decode(json_encode($this->original->getData()['page']['props']), JSON_OBJECT_AS_ARRAY);
|
||||
|
||||
if ($key) {
|
||||
return Arr::get($props, $key);
|
||||
}
|
||||
|
||||
return $props;
|
||||
});
|
||||
|
||||
TestResponse::macro('assertHasProp', function ($key) {
|
||||
Assert::assertTrue(Arr::has($this->props(), $key));
|
||||
|
||||
return $this;
|
||||
});
|
||||
|
||||
TestResponse::macro('assertPropValue', function ($key, $value) {
|
||||
$this->assertHasProp($key);
|
||||
|
||||
if (is_callable($value)) {
|
||||
$value($this->props($key));
|
||||
} else {
|
||||
Assert::assertEquals($this->props($key), $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
});
|
||||
|
||||
TestResponse::macro('assertPropCount', function ($key, $count) {
|
||||
$this->assertHasProp($key);
|
||||
|
||||
Assert::assertCount($count, $this->props($key));
|
||||
|
||||
return $this;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ExampleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* A basic test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_example()
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue