5 |
52 |
53 |
--------------------------------------------------------------------------------
/resources/views/admin/products/create.blade.php:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
15 |
16 |
--------------------------------------------------------------------------------
/resources/views/admin/products/edit.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | Update Product: "{{ $product->title }}"
4 |
28 |
29 |
37 |
38 |
--------------------------------------------------------------------------------
/resources/views/admin/products/form.blade.php:
--------------------------------------------------------------------------------
1 |
2 | Title
3 |
8 |
9 |
10 |
11 | Description
12 | {{old('description') ?: $product->description}}
16 |
17 |
18 |
19 | Price
20 |
25 |
26 |
27 |
28 | Discount %
29 |
34 |
35 |
36 |
37 | Discounted Price
38 |
43 |
44 |
--------------------------------------------------------------------------------
/resources/views/admin/products/index.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | My Products
4 |
5 | Create new Product
6 |
7 |
8 |
9 |
10 |
11 |
12 | #
13 | Title
14 | Price
15 | Create Date
16 | Update Date
17 | Actions
18 |
19 |
20 |
21 | @foreach($products as $i => $product)
22 |
23 | {{ $i + 1 }}
24 | {{ $product->title }}
25 | {{ $product->getPrice() }}
26 | {{ $product->getCreatedAt() }}
27 | {{ $product->getUpdatedAt() }}
28 |
29 |
30 |
34 |
36 |
38 |
39 |
40 |
118 |
119 |
120 |
121 | @endforeach
122 |
123 |
124 |
125 |
126 | {{ $products->links() }}
127 |
128 |
129 |
--------------------------------------------------------------------------------
/resources/views/admin/products/show.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 | Product Details
4 |
28 |
29 |
30 |
Title
31 |
{{$product->title}}
32 |
33 |
34 |
Slug
35 |
{{$product->slug}}
36 |
37 |
38 |
Description
39 |
40 | {{$product->description}}
41 |
42 |
43 |
44 |
Price
45 |
{{$product->getPrice()}}
46 |
47 |
48 |
Discount %
49 |
{{$product->discount_pct ? '%'.$product->discount_pct : ''}}
50 |
51 |
52 |
Discounted Price
53 |
{{$product->getDiscountedPrice()}}
54 |
55 |
56 |
Create Date
57 |
{{$product->getCreatedAt()}}
58 |
59 |
60 |
Update Date
61 |
{{$product->getUpdatedAt()}}
62 |
63 |
64 |
--------------------------------------------------------------------------------
/resources/views/admin/sidebar.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
11 |
13 |
14 |
15 | Dashboard
16 |
17 |
18 |
19 |
21 |
23 |
24 |
25 | Products
26 |
27 |
28 |
29 |
30 |
32 |
34 |
35 |
36 | Orders
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/resources/views/auth/confirm-password.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
11 |
12 |
13 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/resources/views/auth/forgot-password.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
44 |
45 |
--------------------------------------------------------------------------------
/resources/views/auth/login.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
60 |
61 |
--------------------------------------------------------------------------------
/resources/views/auth/register.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
56 |
57 |
--------------------------------------------------------------------------------
/resources/views/auth/reset-password.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/resources/views/auth/verify-email.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
5 |
6 |
7 | @if (session('status') == 'verification-link-sent')
8 |
9 | {{ __('A new verification link has been sent to the email address you provided during registration.') }}
10 |
11 | @endif
12 |
13 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/resources/views/components/admin/input.blade.php:
--------------------------------------------------------------------------------
1 | @props(['disabled' => false, 'errors', 'label' => false])
2 |
5 |
10 | @if ($label)
11 |
{{$label}}
12 | @endif
13 |
merge([
14 | 'class' => 'px-4 w-full border-2 py-2 rounded-md text-sm outline-none ' .
15 | ($errors->has($attributes['name']) ? $errorClasses : (old($attributes['name']) ? $successClasses :$defaultClasses))
16 | ]) !!}>
17 | @error($attributes['name'])
18 |
{{ $message }}
19 | @enderror
20 |
--------------------------------------------------------------------------------
/resources/views/components/admin/sidebar-item.blade.php:
--------------------------------------------------------------------------------
1 | @props(['href'])
2 |
3 |
4 | class(['block font-light text-sm py-2 px-4 transition-colors hover:bg-slate-800 flex items-center']) }}
7 | >
8 |
9 | {{ $icon ?? '' }}
10 |
11 | {{$slot}}
12 |
13 |
14 |
--------------------------------------------------------------------------------
/resources/views/components/application-logo.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/resources/views/components/auth-session-status.blade.php:
--------------------------------------------------------------------------------
1 | @props(['status'])
2 |
3 | @if ($status)
4 |
merge(['class' => 'py-2 px-4 bg-emerald-500 text-white rounded']) }}>
5 | {{ $status }}
6 |
7 | @endif
8 |
--------------------------------------------------------------------------------
/resources/views/components/auth-validation-errors.blade.php:
--------------------------------------------------------------------------------
1 | @props(['errors'])
2 |
3 | @if ($errors->any())
4 |
merge(['class' => 'py-2 px-4 bg-red-500 text-white rounded']) }} >
5 |
6 | {{ __('Whoops! Something went wrong.') }}
7 |
8 |
9 |
10 | @foreach ($errors->all() as $error)
11 | {{ $error }}
12 | @endforeach
13 |
14 |
15 | @endif
16 |
--------------------------------------------------------------------------------
/resources/views/components/button-link.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'size' => 'default',
3 | 'variant' => 'primary'
4 | ])
5 |
6 |
merge([
7 | 'class' => 'flex items-center btn-primary'.
8 | ($size == 'sm' ? ' px-2 py-1 text-sm' : '').
9 | ($variant === 'primary' ? ' bg-emerald-500 hover:bg-emerald-600 active:bg-emerald-700' : '').
10 | ($variant === 'info' ? ' bg-blue-500 hover:bg-blue-600 active:bg-blue-700' : '').
11 | ($variant === 'danger' ? ' bg-red-500 hover:bg-red-600 active:bg-red-700' : '')
12 |
13 | ]) }}>
14 |
15 | {{$slot}}
16 |
17 |
--------------------------------------------------------------------------------
/resources/views/components/button.blade.php:
--------------------------------------------------------------------------------
1 | @props([
2 | 'size' => 'default',
3 | 'variant' => 'primary'
4 | ])
5 |
6 |
merge([
7 | 'type' => 'submit',
8 | 'class' => 'flex items-center btn-primary'.
9 | ($size == 'sm' ? ' px-2 py-1 text-sm' : '').
10 | ($variant === 'primary' ? ' bg-emerald-500 hover:bg-emerald-600 active:bg-emerald-700' : '').
11 | ($variant === 'info' ? ' bg-blue-500 hover:bg-blue-600 active:bg-blue-700' : '').
12 | ($variant === 'danger' ? ' bg-red-500 hover:bg-red-600 active:bg-red-700' : '')
13 | ]) }}>
14 | {{ $slot }}
15 |
16 |
--------------------------------------------------------------------------------
/resources/views/components/card.blade.php:
--------------------------------------------------------------------------------
1 |
2 | {{ $slot }}
3 |
4 |
--------------------------------------------------------------------------------
/resources/views/components/dropdown-link.blade.php:
--------------------------------------------------------------------------------
1 |
merge(['class' => 'block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out']) }}>{{ $slot }}
2 |
--------------------------------------------------------------------------------
/resources/views/components/dropdown.blade.php:
--------------------------------------------------------------------------------
1 | @props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white'])
2 |
3 | @php
4 | switch ($align) {
5 | case 'left':
6 | $alignmentClasses = 'origin-top-left left-0';
7 | break;
8 | case 'top':
9 | $alignmentClasses = 'origin-top';
10 | break;
11 | case 'right':
12 | default:
13 | $alignmentClasses = 'origin-top-right right-0';
14 | break;
15 | }
16 |
17 | switch ($width) {
18 | case '48':
19 | $width = 'w-48';
20 | break;
21 | }
22 | @endphp
23 |
24 |
25 |
26 | {{ $trigger }}
27 |
28 |
29 |
39 |
40 | {{ $content }}
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/resources/views/components/input.blade.php:
--------------------------------------------------------------------------------
1 | @props(['disabled' => false, 'errors'])
2 |
5 |
10 |
11 |
merge([
12 | 'class' => 'border-gray-300 focus:outline-none rounded-md w-full ' .
13 | ($errors->has($attributes['name']) ? $errorClasses : (old($attributes['name']) ? $successClasses :$defaultClasses))
14 | ]) !!}>
15 | @error($attributes['name'])
16 |
{{ $message }}
17 | @enderror
18 |
--------------------------------------------------------------------------------
/resources/views/components/label.blade.php:
--------------------------------------------------------------------------------
1 | @props(['value'])
2 |
3 |
merge(['class' => 'block font-medium text-sm text-gray-700']) }}>
4 | {{ $value ?? $slot }}
5 |
6 |
--------------------------------------------------------------------------------
/resources/views/components/nav-link.blade.php:
--------------------------------------------------------------------------------
1 | @props(['active'])
2 |
3 | @php
4 | $classes = ($active ?? false)
5 | ? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
6 | : 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
7 | @endphp
8 |
9 |
merge(['class' => $classes]) }}>
10 | {{ $slot }}
11 |
12 |
--------------------------------------------------------------------------------
/resources/views/components/responsive-nav-link.blade.php:
--------------------------------------------------------------------------------
1 | @props(['active'])
2 |
3 | @php
4 | $classes = ($active ?? false)
5 | ? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
6 | : 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
7 | @endphp
8 |
9 |
merge(['class' => $classes]) }}>
10 | {{ $slot }}
11 |
12 |
--------------------------------------------------------------------------------
/resources/views/components/textarea.blade.php:
--------------------------------------------------------------------------------
1 | @props(['disabled' => false, 'errors'])
2 |
5 |
10 |
11 |
15 | @error($attributes['name'])
16 |
{{ $message }}
17 | @enderror
18 |
--------------------------------------------------------------------------------
/resources/views/dashboard.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ __('Dashboard') }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | You're logged in!
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/resources/views/layouts/admin-guest.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{{ config('app.name', 'Laravel E-commerce Website') }}
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 | {{ $slot }}
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/resources/views/layouts/app.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{{ config('app.name', 'Laravel E-commerce Website') }}
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 | @include('layouts.navigation')
22 |
23 |
24 | {{ $slot }}
25 |
26 |
27 |
28 |
36 |
37 |
41 |
49 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/resources/views/layouts/guest.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{{ config('app.name', 'Laravel') }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ $slot }}
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/resources/views/vendor/pagination/simple-tailwind.blade.php:
--------------------------------------------------------------------------------
1 | @if ($paginator->hasPages())
2 |
3 | {{-- Previous Page Link --}}
4 | @if ($paginator->onFirstPage())
5 |
6 | {!! __('pagination.previous') !!}
7 |
8 | @else
9 |
10 | {!! __('pagination.previous') !!}
11 |
12 | @endif
13 |
14 | {{-- Next Page Link --}}
15 | @if ($paginator->hasMorePages())
16 |
17 | {!! __('pagination.next') !!}
18 |
19 | @else
20 |
21 | {!! __('pagination.next') !!}
22 |
23 | @endif
24 |
25 | @endif
26 |
--------------------------------------------------------------------------------
/resources/views/welcome.blade.php:
--------------------------------------------------------------------------------
1 |
2 | Product Listing
3 |
4 |
--------------------------------------------------------------------------------
/routes/admin.php:
--------------------------------------------------------------------------------
1 | group(function () {
13 | Route::middleware(['admin.auth'])->group(function () {
14 | Route::get('/', [\App\Http\Controllers\Admin\DashboardController::class, 'index']);
15 | Route::resource('products',ProductController::class);
16 | });
17 | Route::middleware(['admin.guest'])->group(function () {
18 | Route::get('/login', [\App\Http\Controllers\Admin\LoginController::class, 'form'])->name('admin.login');
19 | Route::post('/login', [\App\Http\Controllers\Admin\LoginController::class, 'login']);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/routes/api.php:
--------------------------------------------------------------------------------
1 | get('/user', function (Request $request) {
18 | return $request->user();
19 | });
20 |
--------------------------------------------------------------------------------
/routes/auth.php:
--------------------------------------------------------------------------------
1 | group(function () {
14 | Route::get('register', [RegisteredUserController::class, 'create'])
15 | ->name('register');
16 |
17 | Route::post('register', [RegisteredUserController::class, 'store']);
18 |
19 | Route::get('login', [AuthenticatedSessionController::class, 'create'])
20 | ->name('login');
21 |
22 | Route::post('login', [AuthenticatedSessionController::class, 'store']);
23 |
24 | Route::get('forgot-password', [PasswordResetLinkController::class, 'create'])
25 | ->name('password.request');
26 |
27 | Route::post('forgot-password', [PasswordResetLinkController::class, 'store'])
28 | ->name('password.email');
29 |
30 | Route::get('reset-password/{token}', [NewPasswordController::class, 'create'])
31 | ->name('password.reset');
32 |
33 | Route::post('reset-password', [NewPasswordController::class, 'store'])
34 | ->name('password.update');
35 | });
36 |
37 | Route::middleware('auth')->group(function () {
38 | Route::get('verify-email', [EmailVerificationPromptController::class, '__invoke'])
39 | ->name('verification.notice');
40 |
41 | Route::get('verify-email/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
42 | ->middleware(['signed', 'throttle:6,1'])
43 | ->name('verification.verify');
44 |
45 | Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
46 | ->middleware('throttle:6,1')
47 | ->name('verification.send');
48 |
49 | Route::get('confirm-password', [ConfirmablePasswordController::class, 'show'])
50 | ->name('password.confirm');
51 |
52 | Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']);
53 |
54 | Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])
55 | ->name('logout');
56 | });
57 |
--------------------------------------------------------------------------------
/routes/channels.php:
--------------------------------------------------------------------------------
1 | id === (int) $id;
18 | });
19 |
--------------------------------------------------------------------------------
/routes/console.php:
--------------------------------------------------------------------------------
1 | comment(Inspiring::quote());
19 | })->purpose('Display an inspiring quote');
20 |
--------------------------------------------------------------------------------
/routes/web.php:
--------------------------------------------------------------------------------
1 | name('home');
20 |
21 | Route::get('/dashboard', function () {
22 | return view('dashboard');
23 | })->middleware(['auth', 'verified'])->name('dashboard');
24 |
25 | require __DIR__.'/auth.php';
26 | require __DIR__.'/admin.php';
27 |
28 |
--------------------------------------------------------------------------------
/storage/app/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !public/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/app/public/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/.gitignore:
--------------------------------------------------------------------------------
1 | compiled.php
2 | config.php
3 | down
4 | events.scanned.php
5 | maintenance.php
6 | routes.php
7 | routes.scanned.php
8 | schedule-*
9 | services.json
10 |
--------------------------------------------------------------------------------
/storage/framework/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !data/
3 | !.gitignore
4 |
--------------------------------------------------------------------------------
/storage/framework/cache/data/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/sessions/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/testing/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/framework/views/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/storage/logs/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const defaultTheme = require('tailwindcss/defaultTheme');
2 |
3 | module.exports = {
4 | content: [
5 | './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
6 | './storage/framework/views/*.php',
7 | './resources/views/**/*.blade.php',
8 | ],
9 |
10 | theme: {
11 | extend: {
12 | fontFamily: {
13 | sans: ['Nunito', ...defaultTheme.fontFamily.sans],
14 | },
15 | },
16 | },
17 |
18 | plugins: [require('@tailwindcss/forms')],
19 | };
20 |
--------------------------------------------------------------------------------
/tests/CreatesApplication.php:
--------------------------------------------------------------------------------
1 | make(Kernel::class)->bootstrap();
19 |
20 | return $app;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/Feature/Auth/AuthenticationTest.php:
--------------------------------------------------------------------------------
1 | get('/login');
17 |
18 | $response->assertStatus(200);
19 | }
20 |
21 | public function test_users_can_authenticate_using_the_login_screen()
22 | {
23 | $user = User::factory()->create();
24 |
25 | $response = $this->post('/login', [
26 | 'email' => $user->email,
27 | 'password' => 'password',
28 | ]);
29 |
30 | $this->assertAuthenticated();
31 | $response->assertRedirect(RouteServiceProvider::HOME);
32 | }
33 |
34 | public function test_users_can_not_authenticate_with_invalid_password()
35 | {
36 | $user = User::factory()->create();
37 |
38 | $this->post('/login', [
39 | 'email' => $user->email,
40 | 'password' => 'wrong-password',
41 | ]);
42 |
43 | $this->assertGuest();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/Feature/Auth/EmailVerificationTest.php:
--------------------------------------------------------------------------------
1 | create([
20 | 'email_verified_at' => null,
21 | ]);
22 |
23 | $response = $this->actingAs($user)->get('/verify-email');
24 |
25 | $response->assertStatus(200);
26 | }
27 |
28 | public function test_email_can_be_verified()
29 | {
30 | $user = User::factory()->create([
31 | 'email_verified_at' => null,
32 | ]);
33 |
34 | Event::fake();
35 |
36 | $verificationUrl = URL::temporarySignedRoute(
37 | 'verification.verify',
38 | now()->addMinutes(60),
39 | ['id' => $user->id, 'hash' => sha1($user->email)]
40 | );
41 |
42 | $response = $this->actingAs($user)->get($verificationUrl);
43 |
44 | Event::assertDispatched(Verified::class);
45 | $this->assertTrue($user->fresh()->hasVerifiedEmail());
46 | $response->assertRedirect(RouteServiceProvider::HOME.'?verified=1');
47 | }
48 |
49 | public function test_email_is_not_verified_with_invalid_hash()
50 | {
51 | $user = User::factory()->create([
52 | 'email_verified_at' => null,
53 | ]);
54 |
55 | $verificationUrl = URL::temporarySignedRoute(
56 | 'verification.verify',
57 | now()->addMinutes(60),
58 | ['id' => $user->id, 'hash' => sha1('wrong-email')]
59 | );
60 |
61 | $this->actingAs($user)->get($verificationUrl);
62 |
63 | $this->assertFalse($user->fresh()->hasVerifiedEmail());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/Feature/Auth/PasswordConfirmationTest.php:
--------------------------------------------------------------------------------
1 | create();
16 |
17 | $response = $this->actingAs($user)->get('/confirm-password');
18 |
19 | $response->assertStatus(200);
20 | }
21 |
22 | public function test_password_can_be_confirmed()
23 | {
24 | $user = User::factory()->create();
25 |
26 | $response = $this->actingAs($user)->post('/confirm-password', [
27 | 'password' => 'password',
28 | ]);
29 |
30 | $response->assertRedirect();
31 | $response->assertSessionHasNoErrors();
32 | }
33 |
34 | public function test_password_is_not_confirmed_with_invalid_password()
35 | {
36 | $user = User::factory()->create();
37 |
38 | $response = $this->actingAs($user)->post('/confirm-password', [
39 | 'password' => 'wrong-password',
40 | ]);
41 |
42 | $response->assertSessionHasErrors();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/Feature/Auth/PasswordResetTest.php:
--------------------------------------------------------------------------------
1 | get('/forgot-password');
18 |
19 | $response->assertStatus(200);
20 | }
21 |
22 | public function test_reset_password_link_can_be_requested()
23 | {
24 | Notification::fake();
25 |
26 | $user = User::factory()->create();
27 |
28 | $this->post('/forgot-password', ['email' => $user->email]);
29 |
30 | Notification::assertSentTo($user, ResetPassword::class);
31 | }
32 |
33 | public function test_reset_password_screen_can_be_rendered()
34 | {
35 | Notification::fake();
36 |
37 | $user = User::factory()->create();
38 |
39 | $this->post('/forgot-password', ['email' => $user->email]);
40 |
41 | Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
42 | $response = $this->get('/reset-password/'.$notification->token);
43 |
44 | $response->assertStatus(200);
45 |
46 | return true;
47 | });
48 | }
49 |
50 | public function test_password_can_be_reset_with_valid_token()
51 | {
52 | Notification::fake();
53 |
54 | $user = User::factory()->create();
55 |
56 | $this->post('/forgot-password', ['email' => $user->email]);
57 |
58 | Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
59 | $response = $this->post('/reset-password', [
60 | 'token' => $notification->token,
61 | 'email' => $user->email,
62 | 'password' => 'password',
63 | 'password_confirmation' => 'password',
64 | ]);
65 |
66 | $response->assertSessionHasNoErrors();
67 |
68 | return true;
69 | });
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/tests/Feature/Auth/RegistrationTest.php:
--------------------------------------------------------------------------------
1 | get('/register');
16 |
17 | $response->assertStatus(200);
18 | }
19 |
20 | public function test_new_users_can_register()
21 | {
22 | $response = $this->post('/register', [
23 | 'name' => 'Test User',
24 | 'email' => 'test@example.com',
25 | 'password' => 'password',
26 | 'password_confirmation' => 'password',
27 | ]);
28 |
29 | $this->assertAuthenticated();
30 | $response->assertRedirect(RouteServiceProvider::HOME);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/Feature/ExampleTest.php:
--------------------------------------------------------------------------------
1 | get('/');
18 |
19 | $response->assertStatus(200);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | assertTrue(true);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/webpack.mix.js:
--------------------------------------------------------------------------------
1 | const mix = require('laravel-mix');
2 |
3 | /*
4 | |--------------------------------------------------------------------------
5 | | Mix Asset Management
6 | |--------------------------------------------------------------------------
7 | |
8 | | Mix provides a clean, fluent API for defining some Webpack build steps
9 | | for your Laravel applications. By default, we are compiling the CSS
10 | | file for the application as well as bundling up all the JS files.
11 | |
12 | */
13 |
14 | mix.js('resources/js/app.js', 'public/js').postCss('resources/css/app.css', 'public/css', [
15 | require('tailwindcss'),
16 | require('autoprefixer'),
17 | ]);
18 |
--------------------------------------------------------------------------------