diff --git a/.coolify-logo b/.coolify-logo new file mode 100644 index 000000000..fe8daf698 --- /dev/null +++ b/.coolify-logo @@ -0,0 +1,8 @@ + _____ _ _ __ + / ____| | (_)/ _| + | | ___ ___ | |_| |_ _ _ + | | / _ \ / _ \| | | _| | | | + | |___| (_) | (_) | | | | | |_| | + \_____\___/ \___/|_|_|_| \__, | + __/ | + |___/ diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 000000000..c5a7b5ccd --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,45 @@ +tasks: + - name: Setup Sail environment and Composer dependencies + # Fix because of https://github.com/gitpod-io/gitpod/issues/16614 + before: sudo curl -o /usr/local/bin/docker-compose -fsSL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-$(uname -m) + init: | + cp .env.example .env && + sed -i "s#APP_URL=http://localhost#APP_URL=$(gp url 80)#g" .env + sed -i "s#GITPOD_VITE_URL=#GITPOD_VITE_URL=$(gp url 5173)#g" .env + composer install --ignore-platform-reqs + ./vendor/bin/sail up -d + ./vendor/bin/sail php artisan key:generate + ./vendor/bin/sail php artisan storage:link + cat .coolify-logo + gp sync-done sail-is-ready + + - name: Install Node dependencies and run Vite + command: | + echo "Waiting for Sail environment to boot up." + gp sync-await sail-is-ready + ./vendor/bin/sail npm install + ./vendor/bin/sail npm run dev + +ports: + - port: 3306 + onOpen: ignore + name: MySQL Database Port + - port: 5173 + onOpen: ignore + visibility: public + name: Node Server for Vite + +# Configure vscode +vscode: + extensions: + - bmewburn.vscode-intelephense-client + - eamodio.gitlens + - ikappas.composer + - ms-azuretools.vscode-docker + - ecmel.vscode-html-css + - MehediDracula.php-namespace-resolver + - wmaurer.change-case + - Equinusocio.vsc-community-material-theme + - EditorConfig.EditorConfig + - streetsidesoftware.code-spell-checker + - rangav.vscode-thunder-client diff --git a/composer.json b/composer.json index ab21d01e1..94fa1ffd4 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,7 @@ }, "require-dev": { "fakerphp/faker": "^1.9.1", + "laravel/dusk": "^7.7", "laravel/pint": "^1.0", "laravel/sail": "^1.18", "mockery/mockery": "^1.4.4", diff --git a/composer.lock b/composer.lock index 87f668056..432cb4ad4 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": "03c1963c1ac555dff749aba587e631c8", + "content-hash": "f6c39647206d4c1157c2be1d960de5cc", "packages": [ { "name": "bacon/bacon-qr-code", @@ -7466,6 +7466,79 @@ }, "time": "2021-10-08T21:21:46+00:00" }, + { + "name": "laravel/dusk", + "version": "v7.7.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/dusk.git", + "reference": "c1d17269c317bc99fef3c2e885465d0bb6398434" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/dusk/zipball/c1d17269c317bc99fef3c2e885465d0bb6398434", + "reference": "c1d17269c317bc99fef3c2e885465d0bb6398434", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-zip": "*", + "illuminate/console": "^9.0|^10.0", + "illuminate/support": "^9.0|^10.0", + "nesbot/carbon": "^2.0", + "php": "^8.0", + "php-webdriver/webdriver": "^1.9.0", + "symfony/console": "^6.0", + "symfony/finder": "^6.0", + "symfony/process": "^6.0", + "vlucas/phpdotenv": "^5.2" + }, + "require-dev": { + "mockery/mockery": "^1.4.2", + "orchestra/testbench": "^7.0|^8.0", + "phpunit/phpunit": "^9.5.10|^10.0.1" + }, + "suggest": { + "ext-pcntl": "Used to gracefully terminate Dusk when tests are running." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Dusk\\DuskServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Dusk\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Dusk provides simple end-to-end testing and browser automation.", + "keywords": [ + "laravel", + "testing", + "webdriver" + ], + "support": { + "issues": "https://github.com/laravel/dusk/issues", + "source": "https://github.com/laravel/dusk/tree/v7.7.0" + }, + "time": "2023-02-21T11:38:10+00:00" + }, { "name": "laravel/pint", "version": "v1.7.0", @@ -8229,6 +8302,72 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-webdriver/webdriver", + "version": "1.14.0", + "source": { + "type": "git", + "url": "https://github.com/php-webdriver/php-webdriver.git", + "reference": "3ea4f924afb43056bf9c630509e657d951608563" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/3ea4f924afb43056bf9c630509e657d951608563", + "reference": "3ea4f924afb43056bf9c630509e657d951608563", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-zip": "*", + "php": "^7.3 || ^8.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/process": "^5.0 || ^6.0" + }, + "replace": { + "facebook/webdriver": "*" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.20.0", + "ondram/ci-detector": "^4.0", + "php-coveralls/php-coveralls": "^2.4", + "php-mock/php-mock-phpunit": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.5", + "symfony/var-dumper": "^5.0 || ^6.0" + }, + "suggest": { + "ext-SimpleXML": "For Firefox profile creation" + }, + "type": "library", + "autoload": { + "files": [ + "lib/Exception/TimeoutException.php" + ], + "psr-4": { + "Facebook\\WebDriver\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP client for Selenium WebDriver. Previously facebook/webdriver.", + "homepage": "https://github.com/php-webdriver/php-webdriver", + "keywords": [ + "Chromedriver", + "geckodriver", + "php", + "selenium", + "webdriver" + ], + "support": { + "issues": "https://github.com/php-webdriver/php-webdriver/issues", + "source": "https://github.com/php-webdriver/php-webdriver/tree/1.14.0" + }, + "time": "2023-02-09T12:12:19+00:00" + }, { "name": "phpdocumentor/reflection-docblock", "version": "5.3.0", diff --git a/docker-compose.yaml b/docker-compose.yaml index 1e8869356..350c9a31e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -13,7 +13,10 @@ x-testing-host: &testing-host-base services: php: + hostname: coolify.test image: "coolify:${TAG:-4}" + extra_hosts: + - 'host.docker.internal:host-gateway' build: context: ./docker/dev dockerfile: Dockerfile @@ -34,6 +37,8 @@ services: depends_on: postgres: condition: service_healthy + selenium: + condition: service_started postgres: image: postgres:15-alpine ports: @@ -57,6 +62,14 @@ services: ] retries: 5 timeout: 10s + selenium: + image: seleniarm/standalone-chromium + extra_hosts: + - 'host.docker.internal:host-gateway' + volumes: + - '/dev/shm:/dev/shm' + networks: + - coolify testing-host: <<: *testing-host-base container_name: coolify-testing-host diff --git a/phpunit.dusk.xml b/phpunit.dusk.xml new file mode 100644 index 000000000..24fbe4597 --- /dev/null +++ b/phpunit.dusk.xml @@ -0,0 +1,15 @@ + + + + + ./tests/Browser + + + diff --git a/tests/Browser/ExampleTest.php b/tests/Browser/ExampleTest.php new file mode 100644 index 000000000..d5ad6b63b --- /dev/null +++ b/tests/Browser/ExampleTest.php @@ -0,0 +1,21 @@ +browse(function (Browser $browser) { + $browser->visit('/') + ->assertSee('Laravel'); + }); + } +} diff --git a/tests/Browser/Pages/HomePage.php b/tests/Browser/Pages/HomePage.php new file mode 100644 index 000000000..45d9283f3 --- /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 000000000..eb9a2ded2 --- /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/console/.gitignore b/tests/Browser/console/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /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 000000000..d6b7ef32c --- /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 000000000..d6b7ef32c --- /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 000000000..c78c37e3d --- /dev/null +++ b/tests/DuskTestCase.php @@ -0,0 +1,71 @@ +addArguments(collect([ + $this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080', + ])->unless($this->hasHeadlessDisabled(), function (Collection $items) { + return $items->merge([ + '--disable-gpu', + '--headless=new', + ]); + })->all()); + + return RemoteWebDriver::create( + $_ENV['DUSK_DRIVER_URL'] ?? 'http://localhost:9515', + DesiredCapabilities::chrome()->setCapability( + ChromeOptions::CAPABILITY, $options + ) + ); + } + + protected function baseUrl() + { + return rtrim(config('app.url'), '/'); + } + + /** + * Determine whether the Dusk command has disabled headless mode. + */ + protected function hasHeadlessDisabled(): bool + { + return isset($_SERVER['DUSK_HEADLESS_DISABLED']) || + isset($_ENV['DUSK_HEADLESS_DISABLED']); + } + + /** + * Determine if the browser window should start maximized. + */ + protected function shouldStartMaximized(): bool + { + return isset($_SERVER['DUSK_START_MAXIMIZED']) || + isset($_ENV['DUSK_START_MAXIMIZED']); + } +}