From ff5ab3aa5891660ad1d657b0fa49d50dec788960 Mon Sep 17 00:00:00 2001 From: jon brookes Date: Mon, 5 Jan 2026 13:43:07 +0000 Subject: [PATCH] feat: add admin email configuration to app settings delete: remove outdated Spatie media library decision document docs: create new decision document for Spatie media library usage docs: add testing strategy document for Pest4 and Dusk test: implement login tests with Dusk for user authentication chore: add .gitignore files for console, screenshots, and source directories --- .github/copilot-instructions.md | 1 + .gitignore | 1 + GEMINI.md | 1 + app/Models/User.php | 17 +- composer.json | 1 + composer.lock | 1481 +------------------- config/app.php | 2 + docs/decisions/004-spatie-media-library | 10 - docs/decisions/004-spatie-media-library.md | 24 + docs/decisions/005-testing.md | 38 + tests/Browser/LoginTest.php | 98 ++ tests/Browser/console/.gitignore | 2 + tests/Browser/screenshots/.gitignore | 2 + tests/Browser/source/.gitignore | 2 + 14 files changed, 189 insertions(+), 1491 deletions(-) delete mode 100644 docs/decisions/004-spatie-media-library create mode 100644 docs/decisions/004-spatie-media-library.md create mode 100644 docs/decisions/005-testing.md create mode 100644 tests/Browser/LoginTest.php create mode 100644 tests/Browser/console/.gitignore create mode 100644 tests/Browser/screenshots/.gitignore create mode 100644 tests/Browser/source/.gitignore diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 690f1ee..a715f25 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -15,6 +15,7 @@ This application is a Laravel application and its main Laravel ecosystems packag - laravel/prompts (PROMPTS) - v0 - livewire/flux (FLUXUI_FREE) - v2 - livewire/livewire (LIVEWIRE) - v3 +- laravel/dusk (DUSK) - v8 - laravel/mcp (MCP) - v0 - laravel/pint (PINT) - v1 - laravel/sail (SAIL) - v1 diff --git a/.gitignore b/.gitignore index eb4f16a..f063bc9 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ yarn-error.log /.zed .vite *.deleted +.env.dusk.local diff --git a/GEMINI.md b/GEMINI.md index 690f1ee..a715f25 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -15,6 +15,7 @@ This application is a Laravel application and its main Laravel ecosystems packag - laravel/prompts (PROMPTS) - v0 - livewire/flux (FLUXUI_FREE) - v2 - livewire/livewire (LIVEWIRE) - v3 +- laravel/dusk (DUSK) - v8 - laravel/mcp (MCP) - v0 - laravel/pint (PINT) - v1 - laravel/sail (SAIL) - v1 diff --git a/app/Models/User.php b/app/Models/User.php index 214bea4..d73a69f 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -3,13 +3,18 @@ namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; + +use Filament\Models\Contracts\FilamentUser; +use Filament\Panel; +use Illuminate\Container\Attributes\Log; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Illuminate\Support\Facades\Log as FacadesLog; use Illuminate\Support\Str; use Laravel\Fortify\TwoFactorAuthenticatable; -class User extends Authenticatable +class User extends Authenticatable implements FilamentUser { /** @use HasFactory<\Database\Factories\UserFactory> */ use HasFactory, Notifiable, TwoFactorAuthenticatable; @@ -61,4 +66,14 @@ class User extends Authenticatable ->map(fn ($word) => Str::substr($word, 0, 1)) ->implode(''); } + + /** + * Determine if the user can access Filament admin panel. + */ + public function canAccessPanel(Panel $panel): bool + { + // FacadesLog::info('Checking admin access for user: ' . $this->email . ' against admin email: ' . config('app.admin_email')); + + return $this->email === config('app.admin_email'); + } } diff --git a/composer.json b/composer.json index 28fe120..1e5cca6 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "require-dev": { "fakerphp/faker": "^1.23", "laravel/boost": "^1.8", + "laravel/dusk": "^8.3", "laravel/pail": "^1.2.2", "laravel/pint": "^1.24", "laravel/sail": "^1.41", diff --git a/composer.lock b/composer.lock index 986c709..83dd478 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "2da5768872a6eb320b933b7f9b8baac4", + "content-hash": "8074d7e5af3ede59ab12a880d70b7989", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -8917,1228 +8917,6 @@ } ], "packages-dev": [ - { - "name": "amphp/amp", - "version": "v3.1.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/fa0ab33a6f47a82929c38d03ca47ebb71086a93f", - "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "phpunit/phpunit": "^9", - "psalm/phar": "5.23.1" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Future/functions.php", - "src/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v3.1.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-08-27T21:42:00+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v2.1.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/55a6bd071aec26fa2a3e002618c20c35e3df1b46", - "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/parser": "^1.1", - "amphp/pipeline": "^1", - "amphp/serialization": "^1", - "amphp/sync": "^2", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2.3" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "5.22.1" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Internal/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "https://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v2.1.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-03-16T17:10:27+00:00" - }, - { - "name": "amphp/cache", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/cache.git", - "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/cache/zipball/46912e387e6aa94933b61ea1ead9cf7540b7797c", - "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/serialization": "^1", - "amphp/sync": "^2", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Cache\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - } - ], - "description": "A fiber-aware cache API based on Amp and Revolt.", - "homepage": "https://amphp.org/cache", - "support": { - "issues": "https://github.com/amphp/cache/issues", - "source": "https://github.com/amphp/cache/tree/v2.0.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-04-19T03:38:06+00:00" - }, - { - "name": "amphp/dns", - "version": "v2.4.0", - "source": { - "type": "git", - "url": "https://github.com/amphp/dns.git", - "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/dns/zipball/78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", - "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/cache": "^2", - "amphp/parser": "^1", - "amphp/process": "^2", - "daverandom/libdns": "^2.0.2", - "ext-filter": "*", - "ext-json": "*", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "5.20" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Dns\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Chris Wright", - "email": "addr@daverandom.com" - }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "Async DNS resolution for Amp.", - "homepage": "https://github.com/amphp/dns", - "keywords": [ - "amp", - "amphp", - "async", - "client", - "dns", - "resolve" - ], - "support": { - "issues": "https://github.com/amphp/dns/issues", - "source": "https://github.com/amphp/dns/tree/v2.4.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-01-19T15:43:40+00:00" - }, - { - "name": "amphp/hpack", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/hpack.git", - "reference": "4f293064b15682a2b178b1367ddf0b8b5feb0239" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/hpack/zipball/4f293064b15682a2b178b1367ddf0b8b5feb0239", - "reference": "4f293064b15682a2b178b1367ddf0b8b5feb0239", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "http2jp/hpack-test-case": "^1", - "nikic/php-fuzzer": "^0.0.10", - "phpunit/phpunit": "^7 | ^8 | ^9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Amp\\Http\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Bob Weinand" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "HTTP/2 HPack implementation.", - "homepage": "https://github.com/amphp/hpack", - "keywords": [ - "headers", - "hpack", - "http-2" - ], - "support": { - "issues": "https://github.com/amphp/hpack/issues", - "source": "https://github.com/amphp/hpack/tree/v3.2.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-03-21T19:00:16+00:00" - }, - { - "name": "amphp/http", - "version": "v2.1.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/http.git", - "reference": "3680d80bd38b5d6f3c2cef2214ca6dd6cef26588" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/http/zipball/3680d80bd38b5d6f3c2cef2214ca6dd6cef26588", - "reference": "3680d80bd38b5d6f3c2cef2214ca6dd6cef26588", - "shasum": "" - }, - "require": { - "amphp/hpack": "^3", - "amphp/parser": "^1.1", - "league/uri-components": "^2.4.2 | ^7.1", - "php": ">=8.1", - "psr/http-message": "^1 | ^2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "league/uri": "^6.8 | ^7.1", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.26.1" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Internal/constants.php" - ], - "psr-4": { - "Amp\\Http\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "Basic HTTP primitives which can be shared by servers and clients.", - "support": { - "issues": "https://github.com/amphp/http/issues", - "source": "https://github.com/amphp/http/tree/v2.1.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-11-23T14:57:26+00:00" - }, - { - "name": "amphp/http-client", - "version": "v5.3.4", - "source": { - "type": "git", - "url": "https://github.com/amphp/http-client.git", - "reference": "75ad21574fd632594a2dd914496647816d5106bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/http-client/zipball/75ad21574fd632594a2dd914496647816d5106bc", - "reference": "75ad21574fd632594a2dd914496647816d5106bc", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/hpack": "^3", - "amphp/http": "^2", - "amphp/pipeline": "^1", - "amphp/socket": "^2", - "amphp/sync": "^2", - "league/uri": "^7", - "league/uri-components": "^7", - "league/uri-interfaces": "^7.1", - "php": ">=8.1", - "psr/http-message": "^1 | ^2", - "revolt/event-loop": "^1" - }, - "conflict": { - "amphp/file": "<3 | >=5" - }, - "require-dev": { - "amphp/file": "^3 | ^4", - "amphp/http-server": "^3", - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "ext-json": "*", - "kelunik/link-header-rfc5988": "^1", - "laminas/laminas-diactoros": "^2.3", - "phpunit/phpunit": "^9", - "psalm/phar": "~5.23" - }, - "suggest": { - "amphp/file": "Required for file request bodies and HTTP archive logging", - "ext-json": "Required for logging HTTP archives", - "ext-zlib": "Allows using compression for response bodies." - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Internal/functions.php" - ], - "psr-4": { - "Amp\\Http\\Client\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@gmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.", - "homepage": "https://amphp.org/http-client", - "keywords": [ - "async", - "client", - "concurrent", - "http", - "non-blocking", - "rest" - ], - "support": { - "issues": "https://github.com/amphp/http-client/issues", - "source": "https://github.com/amphp/http-client/tree/v5.3.4" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-08-16T20:41:23+00:00" - }, - { - "name": "amphp/http-server", - "version": "v3.4.3", - "source": { - "type": "git", - "url": "https://github.com/amphp/http-server.git", - "reference": "7aa962b0569f664af3ba23bc819f2a69884329cd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/http-server/zipball/7aa962b0569f664af3ba23bc819f2a69884329cd", - "reference": "7aa962b0569f664af3ba23bc819f2a69884329cd", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/cache": "^2", - "amphp/hpack": "^3", - "amphp/http": "^2", - "amphp/pipeline": "^1", - "amphp/socket": "^2.1", - "amphp/sync": "^2.2", - "league/uri": "^7.1", - "league/uri-interfaces": "^7.1", - "php": ">=8.1", - "psr/http-message": "^1 | ^2", - "psr/log": "^1 | ^2 | ^3", - "revolt/event-loop": "^1" - }, - "require-dev": { - "amphp/http-client": "^5", - "amphp/log": "^2", - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "league/uri-components": "^7.1", - "monolog/monolog": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "~5.23" - }, - "suggest": { - "ext-zlib": "Allows GZip compression of response bodies" - }, - "type": "library", - "autoload": { - "files": [ - "src/Driver/functions.php", - "src/Middleware/functions.php", - "src/functions.php" - ], - "psr-4": { - "Amp\\Http\\Server\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Bob Weinand" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "A non-blocking HTTP application server for PHP based on Amp.", - "homepage": "https://github.com/amphp/http-server", - "keywords": [ - "amp", - "amphp", - "async", - "http", - "non-blocking", - "server" - ], - "support": { - "issues": "https://github.com/amphp/http-server/issues", - "source": "https://github.com/amphp/http-server/tree/v3.4.3" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-05-18T15:43:42+00:00" - }, - { - "name": "amphp/parser", - "version": "v1.1.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/parser.git", - "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/parser/zipball/3cf1f8b32a0171d4b1bed93d25617637a77cded7", - "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7", - "shasum": "" - }, - "require": { - "php": ">=7.4" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Parser\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A generator parser to make streaming parsers simple.", - "homepage": "https://github.com/amphp/parser", - "keywords": [ - "async", - "non-blocking", - "parser", - "stream" - ], - "support": { - "issues": "https://github.com/amphp/parser/issues", - "source": "https://github.com/amphp/parser/tree/v1.1.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-03-21T19:16:53+00:00" - }, - { - "name": "amphp/pipeline", - "version": "v1.2.3", - "source": { - "type": "git", - "url": "https://github.com/amphp/pipeline.git", - "reference": "7b52598c2e9105ebcddf247fc523161581930367" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/pipeline/zipball/7b52598c2e9105ebcddf247fc523161581930367", - "reference": "7b52598c2e9105ebcddf247fc523161581930367", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "php": ">=8.1", - "revolt/event-loop": "^1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.18" - }, - "type": "library", - "autoload": { - "psr-4": { - "Amp\\Pipeline\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Asynchronous iterators and operators.", - "homepage": "https://amphp.org/pipeline", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "iterator", - "non-blocking" - ], - "support": { - "issues": "https://github.com/amphp/pipeline/issues", - "source": "https://github.com/amphp/pipeline/tree/v1.2.3" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-03-16T16:33:53+00:00" - }, - { - "name": "amphp/process", - "version": "v2.0.3", - "source": { - "type": "git", - "url": "https://github.com/amphp/process.git", - "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", - "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/sync": "^2", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.4" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Process\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A fiber-aware process manager based on Amp and Revolt.", - "homepage": "https://amphp.org/process", - "support": { - "issues": "https://github.com/amphp/process/issues", - "source": "https://github.com/amphp/process/tree/v2.0.3" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-04-19T03:13:44+00:00" - }, - { - "name": "amphp/serialization", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/amphp/serialization.git", - "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", - "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "phpunit/phpunit": "^9 || ^8 || ^7" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Serialization\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Serialization tools for IPC and data storage in PHP.", - "homepage": "https://github.com/amphp/serialization", - "keywords": [ - "async", - "asynchronous", - "serialization", - "serialize" - ], - "support": { - "issues": "https://github.com/amphp/serialization/issues", - "source": "https://github.com/amphp/serialization/tree/master" - }, - "time": "2020-03-25T21:39:07+00:00" - }, - { - "name": "amphp/socket", - "version": "v2.3.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/socket.git", - "reference": "58e0422221825b79681b72c50c47a930be7bf1e1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/socket/zipball/58e0422221825b79681b72c50c47a930be7bf1e1", - "reference": "58e0422221825b79681b72c50c47a930be7bf1e1", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/dns": "^2", - "ext-openssl": "*", - "kelunik/certificate": "^1.1", - "league/uri": "^6.5 | ^7", - "league/uri-interfaces": "^2.3 | ^7", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "amphp/process": "^2", - "phpunit/phpunit": "^9", - "psalm/phar": "5.20" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php", - "src/Internal/functions.php", - "src/SocketAddress/functions.php" - ], - "psr-4": { - "Amp\\Socket\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@gmail.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", - "homepage": "https://github.com/amphp/socket", - "keywords": [ - "amp", - "async", - "encryption", - "non-blocking", - "sockets", - "tcp", - "tls" - ], - "support": { - "issues": "https://github.com/amphp/socket/issues", - "source": "https://github.com/amphp/socket/tree/v2.3.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-04-21T14:33:03+00:00" - }, - { - "name": "amphp/sync", - "version": "v2.3.0", - "source": { - "type": "git", - "url": "https://github.com/amphp/sync.git", - "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/sync/zipball/217097b785130d77cfcc58ff583cf26cd1770bf1", - "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/pipeline": "^1", - "amphp/serialization": "^1", - "php": ">=8.1", - "revolt/event-loop": "^1 || ^0.2" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "5.23" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Sync\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Stephen Coakley", - "email": "me@stephencoakley.com" - } - ], - "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", - "homepage": "https://github.com/amphp/sync", - "keywords": [ - "async", - "asynchronous", - "mutex", - "semaphore", - "synchronization" - ], - "support": { - "issues": "https://github.com/amphp/sync/issues", - "source": "https://github.com/amphp/sync/tree/v2.3.0" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-08-03T19:31:26+00:00" - }, - { - "name": "amphp/websocket", - "version": "v2.0.4", - "source": { - "type": "git", - "url": "https://github.com/amphp/websocket.git", - "reference": "963904b6a883c4b62d9222d1d9749814fac96a3b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/websocket/zipball/963904b6a883c4b62d9222d1d9749814fac96a3b", - "reference": "963904b6a883c4b62d9222d1d9749814fac96a3b", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2", - "amphp/parser": "^1", - "amphp/pipeline": "^1", - "amphp/socket": "^2", - "php": ">=8.1", - "revolt/event-loop": "^1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.18" - }, - "suggest": { - "ext-zlib": "Required for compression" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Websocket\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - } - ], - "description": "Shared code for websocket servers and clients.", - "homepage": "https://github.com/amphp/websocket", - "keywords": [ - "amp", - "amphp", - "async", - "http", - "non-blocking", - "websocket" - ], - "support": { - "issues": "https://github.com/amphp/websocket/issues", - "source": "https://github.com/amphp/websocket/tree/v2.0.4" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2024-10-28T21:28:45+00:00" - }, - { - "name": "amphp/websocket-client", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/websocket-client.git", - "reference": "dc033fdce0af56295a23f63ac4f579b34d470d6c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/websocket-client/zipball/dc033fdce0af56295a23f63ac4f579b34d470d6c", - "reference": "dc033fdce0af56295a23f63ac4f579b34d470d6c", - "shasum": "" - }, - "require": { - "amphp/amp": "^3", - "amphp/byte-stream": "^2.1", - "amphp/http": "^2.1", - "amphp/http-client": "^5", - "amphp/socket": "^2.2", - "amphp/websocket": "^2", - "league/uri": "^7.1", - "php": ">=8.1", - "psr/http-message": "^1|^2", - "revolt/event-loop": "^1" - }, - "require-dev": { - "amphp/http-server": "^3", - "amphp/php-cs-fixer-config": "^2", - "amphp/phpunit-util": "^3", - "amphp/websocket-server": "^3|^4", - "phpunit/phpunit": "^9", - "psalm/phar": "~5.26.1", - "psr/log": "^1" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Amp\\Websocket\\Client\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Async WebSocket client for PHP based on Amp.", - "keywords": [ - "amp", - "amphp", - "async", - "client", - "http", - "non-blocking", - "websocket" - ], - "support": { - "issues": "https://github.com/amphp/websocket-client/issues", - "source": "https://github.com/amphp/websocket-client/tree/v2.0.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2025-08-24T17:25:34+00:00" - }, { "name": "brianium/paratest", "version": "v7.16.0", @@ -10232,50 +9010,6 @@ ], "time": "2025-12-09T20:03:26+00:00" }, - { - "name": "daverandom/libdns", - "version": "v2.1.0", - "source": { - "type": "git", - "url": "https://github.com/DaveRandom/LibDNS.git", - "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", - "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "Required for IDN support" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "LibDNS\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "DNS protocol implementation written in pure PHP", - "keywords": [ - "dns" - ], - "support": { - "issues": "https://github.com/DaveRandom/LibDNS/issues", - "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0" - }, - "time": "2024-04-12T12:12:48+00:00" - }, { "name": "doctrine/deprecations", "version": "1.1.5", @@ -10630,64 +9364,6 @@ }, "time": "2025-03-19T14:43:43+00:00" }, - { - "name": "kelunik/certificate", - "version": "v1.1.3", - "source": { - "type": "git", - "url": "https://github.com/kelunik/certificate.git", - "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", - "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "php": ">=7.0" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "^2", - "phpunit/phpunit": "^6 | 7 | ^8 | ^9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Kelunik\\Certificate\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Access certificate details and transform between different formats.", - "keywords": [ - "DER", - "certificate", - "certificates", - "openssl", - "pem", - "x509" - ], - "support": { - "issues": "https://github.com/kelunik/certificate/issues", - "source": "https://github.com/kelunik/certificate/tree/v1.1.3" - }, - "time": "2023-02-03T21:26:53+00:00" - }, { "name": "laravel/boost", "version": "v1.8.7", @@ -11669,89 +10345,6 @@ ], "time": "2025-08-20T13:10:51+00:00" }, - { - "name": "pestphp/pest-plugin-browser", - "version": "v4.1.1", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-browser.git", - "reference": "da70fce21e4b33ba22bef1276f654e77676213d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-browser/zipball/da70fce21e4b33ba22bef1276f654e77676213d7", - "reference": "da70fce21e4b33ba22bef1276f654e77676213d7", - "shasum": "" - }, - "require": { - "amphp/amp": "^3.1.1", - "amphp/http-server": "^3.4.3", - "amphp/websocket-client": "^2.0.2", - "ext-sockets": "*", - "pestphp/pest": "^4.1.0", - "pestphp/pest-plugin": "^4.0.0", - "php": "^8.3", - "symfony/process": "^7.3.4" - }, - "require-dev": { - "ext-pcntl": "*", - "ext-posix": "*", - "livewire/livewire": "^3.6.4", - "nunomaduro/collision": "^8.8.2", - "orchestra/testbench": "^10.6.0", - "pestphp/pest-dev-tools": "^4.0.0", - "pestphp/pest-plugin-laravel": "^4.0", - "pestphp/pest-plugin-type-coverage": "^4.0.2" - }, - "type": "library", - "extra": { - "pest": { - "plugins": [ - "Pest\\Browser\\Plugin" - ] - } - }, - "autoload": { - "files": [ - "src/Autoload.php" - ], - "psr-4": { - "Pest\\Browser\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Pest plugin to test browser interactions", - "keywords": [ - "browser", - "framework", - "pest", - "php", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin-browser/tree/v4.1.1" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2025-09-29T01:31:33+00:00" - }, { "name": "pestphp/pest-plugin-laravel", "version": "v4.0.0", @@ -12803,78 +11396,6 @@ ], "time": "2025-12-15T06:05:34+00:00" }, - { - "name": "revolt/event-loop", - "version": "v1.0.8", - "source": { - "type": "git", - "url": "https://github.com/revoltphp/event-loop.git", - "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/b6fc06dce8e9b523c9946138fa5e62181934f91c", - "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^9", - "psalm/phar": "^5.15" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Revolt\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "ceesjank@gmail.com" - }, - { - "name": "Christian Lück", - "email": "christian@clue.engineering" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "Rock-solid event loop for concurrent PHP applications.", - "keywords": [ - "async", - "asynchronous", - "concurrency", - "event", - "event-loop", - "non-blocking", - "scheduler" - ], - "support": { - "issues": "https://github.com/revoltphp/event-loop/issues", - "source": "https://github.com/revoltphp/event-loop/tree/v1.0.8" - }, - "time": "2025-08-27T21:33:23+00:00" - }, { "name": "sebastian/cli-parser", "version": "4.2.0", diff --git a/config/app.php b/config/app.php index 423eed5..bf88713 100644 --- a/config/app.php +++ b/config/app.php @@ -123,4 +123,6 @@ return [ 'store' => env('APP_MAINTENANCE_STORE', 'database'), ], + 'admin_email' => env('ADMIN_EMAIL', ''), + ]; diff --git a/docs/decisions/004-spatie-media-library b/docs/decisions/004-spatie-media-library deleted file mode 100644 index e1dc122..0000000 --- a/docs/decisions/004-spatie-media-library +++ /dev/null @@ -1,10 +0,0 @@ -# 2026-01-02 - -```bash -php artisan storage:link -composer require "spatie/laravel-medialibrary" -composer require filament/spatie-laravel-media-library-plugin:"^4.0" -W -php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-config" -php artisan migrate -``` - diff --git a/docs/decisions/004-spatie-media-library.md b/docs/decisions/004-spatie-media-library.md new file mode 100644 index 0000000..64431d3 --- /dev/null +++ b/docs/decisions/004-spatie-media-library.md @@ -0,0 +1,24 @@ +# 2026-01-02 + +```bash +php artisan storage:link +composer require "spatie/laravel-medialibrary" +composer require filament/spatie-laravel-media-library-plugin:"^4.0" -W +php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-config" +php artisan migrate +``` +I had a lot of fun and silly games working out if I even needed both Spatie media library and the filament plugin they have as it states itself a sub directory of filament itself. + +I managed to remove the spatie fulament plugin and for the app to work for a while but eventually found a part of it not implemented in filament core. It took a while but there seems to be an overlap somewhere. So I re-installed the spatie filament module to find all the errors went away, when previously they did not + +PHP and I guess composer would seem to aggressively cache things very very hard and I just didnt understand how very hard that is sometimes. + +Suffice to say, spatie media library seems to be 'the way' as far as media is concerned for filament. + +I looked at curator, also by the author of the tiptap filament integration to find it seems dependant on tailwind3, limiting me to Laravel 11 I believe, which was not what I wanted. + +I used filament 'actions' in order to augment the form for 'entries' so as to add 'pick from gallery' functionality together with custom javascript to insert records found in media library for both rich content and featured images + +There may be a better way of doing this but for now, I believe this is a solution I have craved for a while now with filament and have at least gained a bit better understanding of so called 'actions' and will re-visit this whole section in the docs. + + diff --git a/docs/decisions/005-testing.md b/docs/decisions/005-testing.md new file mode 100644 index 0000000..eb0c372 --- /dev/null +++ b/docs/decisions/005-testing.md @@ -0,0 +1,38 @@ +# 2026-01-05 + +I would very much like to start using Pest4 as it has a lot of nice things in it like browser testing with some of the latest screen shot visual testing and more + +for now I know Dusk and have been able to use this in previous projects before Pest4 + +so initially at least I intend to use Dusk and build on to migrate to Pest4 where I can + +# test isolation and setup + +in the past I now realize, I was introducing brittle tests by first doing setup to then rely on a configuration for further tests + +I think this is a pattern that some follow but as a generalist, devops and hybrid person I can and do make mistakes. I suppose we all do. + +Mine was to not fully embrace test isolation + +Each test therefor needs to be set up from scratch so to speak + +I then have each subsequent test re-setting up say, a user, a database table, whatever is required but each time from a blank slate + +That way, when a test fails, it should be obvious what has been broken without having to traverse through a bunch of setup and dependencies to find I broke a setup step, not a test. + +Let us hope so anyway. That is the approach I am going with with Dusk for now. Lets see how I get on and if I get the setup code as non repeated by abstraction as I can + +I think testing and particulary automated testing is essential for success. + +It has been disappointing to find in my time working with others in the past that there seems resistance to testing and to automation of testing for reasons I believe not technical but that which time does not allow for me to digress + +## confusing config + +In config files: Just use the key name without any prefix + +In your code: Use config('filename.keyname') + +The filename becomes the first part automatically - you never type it inside the config file itself. + + + diff --git a/tests/Browser/LoginTest.php b/tests/Browser/LoginTest.php new file mode 100644 index 0000000..eecd256 --- /dev/null +++ b/tests/Browser/LoginTest.php @@ -0,0 +1,98 @@ +create([ + 'email' => $email, + 'password' => bcrypt('password'), + 'two_factor_secret' => null, + 'two_factor_recovery_codes' => null, + ]); + } + + private function loginUser(Browser $browser, User $user): void + { + $browser->visit('/login') + ->type('email', $user->email) + ->type('password', 'password') + ->press('Log in') + ->waitForLocation('/dashboard'); + } + + public function test_login(): void + { + $user = $this->createTestUser("login-test@example.com"); + + $this->browse(function (Browser $browser) use ($user) { + $this->loginUser($browser, $user); + try { + $browser->assertPathIs('/dashboard'); // Or wherever successful login redirects + } catch (\Exception $e) { + $browser->pause(10000); // Pause for 10 seconds on failure to debug + throw $e; + } + }); + } + + /* + public function test_invalid_login(): void + { + $user = $this->createTestUser("invalid-email@example.com"); + + + $this->browse(function (Browser $browser) use ($user) { + $this->loginUser($browser, $user); + try { + $browser->visit('/admin') + ->waitForLocation('/admin') + ->assertPathIs('/admin') + ->assertTitleContains('Dashboard') + ->assertDontSee('Forbidden') + ->pause(1000); + } catch (\Exception $e) { + $browser->pause(1000); // Pause for 1 second on failure to debug + throw $e; + } + }); + + + + + } +*/ + + public function test_access_admin_panel(): void + { + + $user = $this->createTestUser("login-test@example.com"); + + $this->browse(function (Browser $browser) use ($user) { + $this->loginUser($browser, $user); + try { + $browser->visit('/admin') + ->waitForLocation('/admin') + ->assertPathIs('/admin') + ->assertTitleContains('Dashboard') + ->assertDontSee('Forbidden') + ->pause(1000); + } catch (\Exception $e) { + $browser->pause(1000); // Pause for 1 second on failure to debug + throw $e; + } + }); + } +} diff --git a/tests/Browser/console/.gitignore b/tests/Browser/console/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/Browser/console/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/Browser/screenshots/.gitignore b/tests/Browser/screenshots/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/Browser/screenshots/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/Browser/source/.gitignore b/tests/Browser/source/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/Browser/source/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore