From 3c32d499775dbb026b51cfd6f3d62541c35d2fe2 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Sun, 28 Dec 2025 13:48:02 +0100 Subject: [PATCH] feature - 4 - Set up e2e with basic tests --- .env.dusk.local | 24 ++++++++++ composer.json | 1 + docker-compose.yml | 19 +++++++- docker/mysql-init/01-create-test-database.sql | 8 ++++ tests/Browser/Pages/HomePage.php | 36 ++++++++++++++ tests/Browser/Pages/Page.php | 20 ++++++++ tests/Browser/RedirectTest.php | 38 +++++++++++++++ tests/Browser/RegistrationOnlyTest.php | 36 ++++++++++++++ tests/Browser/console/.gitignore | 2 + tests/Browser/screenshots/.gitignore | 2 + tests/Browser/source/.gitignore | 2 + tests/DuskTestCase.php | 47 +++++++++++++++++++ 12 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 .env.dusk.local create mode 100644 docker/mysql-init/01-create-test-database.sql create mode 100644 tests/Browser/Pages/HomePage.php create mode 100644 tests/Browser/Pages/Page.php create mode 100644 tests/Browser/RedirectTest.php create mode 100644 tests/Browser/RegistrationOnlyTest.php create mode 100644 tests/Browser/console/.gitignore create mode 100644 tests/Browser/screenshots/.gitignore create mode 100644 tests/Browser/source/.gitignore create mode 100644 tests/DuskTestCase.php diff --git a/.env.dusk.local b/.env.dusk.local new file mode 100644 index 0000000..f6e1b47 --- /dev/null +++ b/.env.dusk.local @@ -0,0 +1,24 @@ +APP_NAME=DishPlanner +APP_ENV=testing +APP_KEY=base64:KSKZNT+cJuaBRBv4Y2HQqav6hzREKoLkNIKN8yszU1Q= +APP_DEBUG=true +APP_URL=http://dishplanner_app:8000 + +LOG_CHANNEL=single + +# Test database +DB_CONNECTION=mysql +DB_HOST=db +DB_PORT=3306 +DB_DATABASE=dishplanner_test +DB_USERNAME=dishplanner +DB_PASSWORD=dishplanner + +BROADCAST_DRIVER=log +CACHE_DRIVER=array +FILESYSTEM_DISK=local +QUEUE_CONNECTION=sync +SESSION_DRIVER=array +SESSION_LIFETIME=120 + +MAIL_MAILER=array \ No newline at end of file diff --git a/composer.json b/composer.json index 1de31b0..8f1406a 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ }, "require-dev": { "fakerphp/faker": "^1.23", + "laravel/dusk": "^8.3", "laravel/pail": "^1.1", "laravel/pint": "^1.13", "laravel/sail": "^1.26", diff --git a/docker-compose.yml b/docker-compose.yml index bf97334..cd6cbf3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -63,8 +63,8 @@ services: MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD:-root}" volumes: - db_data:/var/lib/mysql - # Optional: Initialize with SQL dump - # - ./database/dumps:/docker-entrypoint-initdb.d + # Initialize with SQL scripts + - ./docker/mysql-init:/docker-entrypoint-initdb.d healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 10s @@ -84,6 +84,21 @@ services: networks: - dishplanner + # Selenium for E2E testing with Dusk + selenium: + image: selenium/standalone-chrome:latest + container_name: dishplanner_selenium + restart: unless-stopped + ports: + - "4444:4444" # Selenium server + - "7900:7900" # VNC server for debugging + volumes: + - /dev/shm:/dev/shm + networks: + - dishplanner + environment: + - SE_VNC_PASSWORD=secret + # Optional: Redis for caching/sessions # redis: # image: redis:alpine diff --git a/docker/mysql-init/01-create-test-database.sql b/docker/mysql-init/01-create-test-database.sql new file mode 100644 index 0000000..9250306 --- /dev/null +++ b/docker/mysql-init/01-create-test-database.sql @@ -0,0 +1,8 @@ +-- Create test database for Dusk E2E tests +CREATE DATABASE IF NOT EXISTS dishplanner_test; + +-- Grant all privileges on test database to the dishplanner user +GRANT ALL PRIVILEGES ON dishplanner_test.* TO 'dishplanner'@'%' IDENTIFIED BY 'dishplanner'; +GRANT ALL PRIVILEGES ON dishplanner_test.* TO 'dishplanner'@'localhost' IDENTIFIED BY 'dishplanner'; + +FLUSH PRIVILEGES; \ No newline at end of file diff --git a/tests/Browser/Pages/HomePage.php b/tests/Browser/Pages/HomePage.php new file mode 100644 index 0000000..45d9283 --- /dev/null +++ b/tests/Browser/Pages/HomePage.php @@ -0,0 +1,36 @@ + + */ + public function elements(): array + { + return [ + '@element' => '#selector', + ]; + } +} diff --git a/tests/Browser/Pages/Page.php b/tests/Browser/Pages/Page.php new file mode 100644 index 0000000..eb9a2de --- /dev/null +++ b/tests/Browser/Pages/Page.php @@ -0,0 +1,20 @@ + + */ + public static function siteElements(): array + { + return [ + '@element' => '#selector', + ]; + } +} diff --git a/tests/Browser/RedirectTest.php b/tests/Browser/RedirectTest.php new file mode 100644 index 0000000..3c5954e --- /dev/null +++ b/tests/Browser/RedirectTest.php @@ -0,0 +1,38 @@ +browse(function (Browser $browser) { + $browser->visit('http://dishplanner_app:8000/dashboard') + ->assertPathIs('/login') + ->assertSee('Login'); + }); + } + + /** + * Test that login page loads correctly + */ + public function testLoginPageLoads() + { + $this->browse(function (Browser $browser) { + $browser->visit('http://dishplanner_app:8000/login') + ->assertPathIs('/login') + ->assertSee('Login') + ->assertSee('Email') + ->assertSee('Password'); + }); + } +} \ No newline at end of file diff --git a/tests/Browser/RegistrationOnlyTest.php b/tests/Browser/RegistrationOnlyTest.php new file mode 100644 index 0000000..07c25dc --- /dev/null +++ b/tests/Browser/RegistrationOnlyTest.php @@ -0,0 +1,36 @@ +format('YmdHis'); + $testData = [ + 'name' => "Test User {$timestamp}", + 'email' => "test.{$timestamp}@example.com", + 'password' => 'SecurePassword123!', + ]; + + $this->browse(function (Browser $browser) use ($testData) { + $browser->visit('http://dishplanner_app:8000/register') + ->waitFor('input[id="name"]', 5) + ->type('input[id="name"]', $testData['name']) + ->type('input[id="email"]', $testData['email']) + ->type('input[id="password"]', $testData['password']) + ->type('input[id="password_confirmation"]', $testData['password']) + ->screenshot('filled-form') + ->click('button[type="submit"]') + ->pause(3000) // Give more time for processing + ->screenshot('after-submit') + ->assertSee("Welcome {$testData['name']}!") // Verify successful registration and login + ->assertPathIs('/dashboard'); // Should be on dashboard + }); + } +} \ No newline at end of file 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 diff --git a/tests/DuskTestCase.php b/tests/DuskTestCase.php new file mode 100644 index 0000000..8098951 --- /dev/null +++ b/tests/DuskTestCase.php @@ -0,0 +1,47 @@ +addArguments([ + '--window-size=1920,1080', + '--no-sandbox', + '--disable-dev-shm-usage', + '--disable-gpu', + '--headless=new', + '--disable-extensions', + '--disable-background-timer-throttling', + '--disable-backgrounding-occluded-windows', + '--disable-renderer-backgrounding', + ]); + + return RemoteWebDriver::create( + 'http://selenium:4444/wd/hub', // Connect to Selenium container + DesiredCapabilities::chrome()->setCapability( + ChromeOptions::CAPABILITY, $options + ) + ); + } +}