diff --git a/.env.example b/.env.example index aa138d6..8c717f8 100644 --- a/.env.example +++ b/.env.example @@ -22,11 +22,11 @@ LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mariadb -DB_HOST=127.0.0.1 +DB_HOST=ranqueamento_mariadb DB_PORT=3306 DB_DATABASE=ranqueamento -DB_USERNAME=admin -DB_PASSWORD=admin +DB_USERNAME=ranqueamento +DB_PASSWORD=ranqueamento SESSION_DRIVER=database SESSION_LIFETIME=120 @@ -36,7 +36,7 @@ SESSION_DOMAIN=null BROADCAST_CONNECTION=log FILESYSTEM_DISK=local -QUEUE_CONNECTION=database +QUEUE_CONNECTION=sync CACHE_STORE=database CACHE_PREFIX= @@ -48,9 +48,9 @@ REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 -MAIL_MAILER=log -MAIL_HOST=127.0.0.1 -MAIL_PORT=2525 +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null @@ -71,6 +71,14 @@ SENHAUNICA_CALLBACK_ID= SENHAUNICA_ADMINS= SENHAUNICA_CODIGO_UNIDADE=8 +# senha unica faker +SENHAUNICA_KEY=faker +SENHAUNICA_SECRET=faker +SENHAUNICA_CALLBACK_ID=1 +SENHAUNICA_ADMINS=1111 +SENHAUNICA_DEV="http://auth.local:3141/wsusuario/oauth" +SENHAUNICA_USAR_REPLICADO=false + REPLICADO_HOST= REPLICADO_PORT= REPLICADO_DATABASE= @@ -78,8 +86,14 @@ REPLICADO_USERNAME= REPLICADO_PASSWORD= REPLICADO_CODUNDCLG= REPLICADO_SYBASE= - -USP_THEME_SKIN=fflch +REPLICADO_FAKE=1 LARAVEL_TOOLS_FORCAR_HTTPS=false LARAVEL_TOOLS_DEBUG=false + +APP_URL=http://ranqueamento +DUSK_DRIVER_URL='http://selenium:4444/wd/hub' +DUSK_START_MAXIMIZED=true +DUSK_HEADLESS_DISABLED=true + +USP_THEME_SKIN=fflch \ No newline at end of file diff --git a/.gitignore b/.gitignore index 25af3f2..1b7a1c5 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,6 @@ yarn-error.log /.idea /.vscode /.zed - +/.phpunit.cache public/vendor +.env.dusk.local \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0753906 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM uspdev/uspdev-php-apache:8.3 + +RUN sed -i 's|/var/www/html|/var/www/html/public|' \ + /etc/apache2/sites-available/000-default.conf + +USER www-data + +COPY --chown=www-data . . + +RUN composer install \ + --no-dev \ + --optimize-autoloader \ + --no-interaction + +CMD ["apache2-foreground"] \ No newline at end of file diff --git a/README.md b/README.md index 9983143..ac1af5c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## ranqueamento +# ranqueamento Sistema para ranqueamento das habilitações do curso de letras @@ -7,3 +7,97 @@ Falta verificar para reranqueamento: - Alunos com trancamento total podem ou não participarem - pegar exemplo de alunos com mais de 8 créditos que não poderiam participar +## Instalação + +### 1. Clone o repositório + +```bash +git clone LINK + +cd ranqueamento +``` + +### 2. Build da imagem Docker + +```bash +docker build --no-cache -t ranqueamento . +``` + +### 3. Configure o ambiente + +```bash +cp .env.example .env +``` + +Edite o `.env` e ajuste as variáveis necessárias, especialmente: + +```env +DB_HOST=mariadb # nome do serviço no docker-compose +DB_DATABASE=ranqueamento +DB_USERNAME=ranqueamento +DB_PASSWORD=ranqueamento + +SENHAUNICA_KEY= # credenciais da Senha Única USP +SENHAUNICA_SECRET= +SENHAUNICA_CALLBACK_ID= +SENHAUNICA_ADMINS= # número(s) USP dos administradores +``` + +### 4. Suba os containers + +```bash +docker compose up -d +``` + +### 5. Gere a chave da aplicação + +```bash +docker exec -it ranqueamento php artisan key:generate +``` + +### 6. Execute as migrations + +```bash +docker exec -it ranqueamento php artisan migrate +``` + +A aplicação estará disponível em **http://127.0.0.1:8000**. + +--- + +## Testes com Dusk + +### 1. Crie o banco de dados de testes + +```bash +docker compose exec mariadb mariadb -u root -pranqueamento \ + -e "CREATE DATABASE IF NOT EXISTS ranqueamento_dusk;" + +docker compose exec mariadb mariadb -u root -pranqueamento \ + -e "GRANT ALL PRIVILEGES ON ranqueamento_dusk.* TO 'ranqueamento'@'%'; FLUSH PRIVILEGES;" +``` + +### 2. Configure o ambiente Dusk + +```bash +cp .env.dusk.local.example .env.dusk.local +``` + +Edite o `.env.dusk.local` e cole o valor de `APP_KEY` do seu `.env`: + +```env +APP_KEY= # copie do seu .env +``` + +### 3. Instale o Dusk + +```bash +docker exec -it ranqueamento composer require --dev laravel/dusk +docker exec -it ranqueamento php artisan dusk:install +``` + +### 4. Execute os testes + +```bash +docker exec -it ranqueamento php artisan dusk +``` diff --git a/composer.json b/composer.json index d8cf9ae..11eecf1 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ }, "require-dev": { "fakerphp/faker": "^1.23", + "laravel/dusk": "^8.6", "laravel/pail": "^1.1", "laravel/pint": "^1.13", "laravel/sail": "^1.26", diff --git a/composer.lock b/composer.lock index e4d1c24..9194e8d 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": "840bad61c09c4164ee4a72e0e374038d", + "content-hash": "bbf644e4828c8ec7f0fe0e89b22335c5", "packages": [ { "name": "brick/math", @@ -7507,23 +7507,23 @@ }, { "name": "uspdev/replicado", - "version": "1.25.0", + "version": "1.28.4", "source": { "type": "git", "url": "https://github.com/uspdev/replicado.git", - "reference": "a315b1afb4841a9dda1d4dbb245d8f300914692c" + "reference": "b5f2fdc1ebb2d1c645dcb948bc2a99e2d3e4fa15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/uspdev/replicado/zipball/a315b1afb4841a9dda1d4dbb245d8f300914692c", - "reference": "a315b1afb4841a9dda1d4dbb245d8f300914692c", + "url": "https://api.github.com/repos/uspdev/replicado/zipball/b5f2fdc1ebb2d1c645dcb948bc2a99e2d3e4fa15", + "reference": "b5f2fdc1ebb2d1c645dcb948bc2a99e2d3e4fa15", "shasum": "" }, "require": { "ext-pdo_dblib": "*", - "illuminate/collections": "^8 || ^9 || ^10 || ^11", + "illuminate/collections": "^8 || ^9 || ^10 || ^11 || ^12 || ^13", "monolog/monolog": "^2 || ^3", - "php": ">=7.0", + "php": "^7 || ^8", "uspdev/cache": "^1" }, "type": "library", @@ -7550,31 +7550,31 @@ "homepage": "https://github.com/uspdev/replicado", "support": { "issues": "https://github.com/uspdev/replicado/issues", - "source": "https://github.com/uspdev/replicado/tree/1.25.0" + "source": "https://github.com/uspdev/replicado/tree/1.28.4" }, - "time": "2024-12-12T14:02:40+00:00" + "time": "2026-09-03T15:10:07+00:00" }, { "name": "uspdev/senhaunica-socialite", - "version": "4.3.17", + "version": "4.5.9", "source": { "type": "git", "url": "https://github.com/uspdev/senhaunica-socialite.git", - "reference": "d7f128c5707197f728e63dd6599e51a96b431c20" + "reference": "2830f14a38e63cd2ffd7798d1fa57c399445e38a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/uspdev/senhaunica-socialite/zipball/d7f128c5707197f728e63dd6599e51a96b431c20", - "reference": "d7f128c5707197f728e63dd6599e51a96b431c20", + "url": "https://api.github.com/repos/uspdev/senhaunica-socialite/zipball/2830f14a38e63cd2ffd7798d1fa57c399445e38a", + "reference": "2830f14a38e63cd2ffd7798d1fa57c399445e38a", "shasum": "" }, "require": { - "doctrine/dbal": "^3.1 | ^4.2.1", - "kyslik/column-sortable": "^6.5", - "laravel/socialite": "^5.0", - "php": ">=7.1.3", - "socialiteproviders/manager": "^3.4.2 | ^4.0", - "spatie/laravel-permission": "^4.2 | ^5.0 | ^6.0" + "doctrine/dbal": "^3 | ^4 ", + "kyslik/column-sortable": "^6 | ^7 | ^8", + "laravel/socialite": "^5", + "php": "^7 | ^8", + "socialiteproviders/manager": "^3 | ^4", + "spatie/laravel-permission": "^4 | ^5 | ^6 | ^7" }, "type": "library", "extra": { @@ -7607,9 +7607,9 @@ "homepage": "https://github.com/uspdev/senhaunica-socialite", "support": { "issues": "https://github.com/uspdev/senhaunica-socialite/issues", - "source": "https://github.com/uspdev/senhaunica-socialite/tree/4.3.17" + "source": "https://github.com/uspdev/senhaunica-socialite/tree/4.5.9" }, - "time": "2024-10-24T19:40:56+00:00" + "time": "2026-08-28T21:38:17+00:00" }, { "name": "vlucas/phpdotenv", @@ -8067,6 +8067,80 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "laravel/dusk", + "version": "v8.6.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/dusk.git", + "reference": "e7fd48762c6a82ad2cd311db07587aa2a97ce143" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/dusk/zipball/e7fd48762c6a82ad2cd311db07587aa2a97ce143", + "reference": "e7fd48762c6a82ad2cd311db07587aa2a97ce143", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-zip": "*", + "guzzlehttp/guzzle": "^7.5", + "illuminate/console": "^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^10.0|^11.0|^12.0|^13.0", + "php": "^8.1", + "php-webdriver/webdriver": "^1.15.2", + "symfony/console": "^6.2|^7.0|^8.0", + "symfony/finder": "^6.2|^7.0|^8.0", + "symfony/process": "^6.2|^7.0|^8.0", + "vlucas/phpdotenv": "^5.2" + }, + "require-dev": { + "laravel/framework": "^10.0|^11.0|^12.0|^13.0", + "mockery/mockery": "^1.6", + "orchestra/testbench-core": "^8.19|^9.17|^10.8|^11.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1|^11.0|^12.0.1", + "psy/psysh": "^0.11.12|^0.12", + "symfony/yaml": "^6.2|^7.0|^8.0" + }, + "suggest": { + "ext-pcntl": "Used to gracefully terminate Dusk when tests are running." + }, + "type": "library", + "extra": { + "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/v8.6.0" + }, + "time": "2026-04-15T14:50:40+00:00" + }, { "name": "laravel/pail", "version": "v1.2.1", @@ -8632,6 +8706,72 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-webdriver/webdriver", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/php-webdriver/php-webdriver.git", + "reference": "ac0662863aa120b4f645869f584013e4c4dba46a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/ac0662863aa120b4f645869f584013e4c4dba46a", + "reference": "ac0662863aa120b4f645869f584013e4c4dba46a", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-zip": "*", + "php": "^7.3 || ^8.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/process": "^5.0 || ^6.0 || ^7.0 || ^8.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 || ^7.0 || ^8.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.16.0" + }, + "time": "2025-12-28T23:57:40+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "11.0.8", @@ -10166,5 +10306,5 @@ "php": "^8.2" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..55b9bbf --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,84 @@ +services: + ranqueamento: + build: . + image: ranqueamento:latest + container_name: ranqueamento + ports: + - "8000:80" + depends_on: + - mariadb + networks: + - ranqueamento-network + volumes: + - ./:/var/www/html + environment: + HOME: /tmp + user: "${UID:-1000}:${GID:-1000}" + + mariadb: + image: mariadb:11 + container_name: ranqueamento_mariadb + restart: always + environment: + MYSQL_DATABASE: ranqueamento + MYSQL_USER: ranqueamento + MYSQL_PASSWORD: ranqueamento + MYSQL_ROOT_PASSWORD: ranqueamento + volumes: + - mariadb_data:/var/lib/mysql + networks: + - ranqueamento-network + + phpmyadmin: + image: phpmyadmin:latest + container_name: ranqueamento_phpmyadmin + restart: always + depends_on: + - mariadb + ports: + - "8081:80" + environment: + PMA_HOST: mariadb + PMA_PORT: 3306 + PMA_USER: root + PMA_PASSWORD: ranqueamento + networks: + - ranqueamento-network + + selenium: + image: selenium/standalone-chrome + container_name: ranqueamento_selenium + ports: + - "7900:7900" + networks: + - ranqueamento-network + shm_size: 2gb + + # No /etc/hosts do seu computador colocar a linha `127.0.0.1 auth.local` + # particularidades do protocolo oAuth1 usado na USP + senhaunica-faker: + image: uspdev/senhaunica-faker + container_name: ranqueamento_senhaunica-faker + ports: + - "3141:3141" + environment: + - APP_URL=http://auth.local:3141 + networks: + ranqueamento-network: + aliases: + - auth.local + + mailpit: + image: axllent/mailpit:latest + container_name: ranqueamento_mailpit + ports: + - "1025:1025" # SMTP + - "8025:8025" # Interface Web + networks: + - ranqueamento-network + +networks: + ranqueamento-network: + +volumes: + mariadb_data: diff --git a/tests/Browser/IndexTest.php b/tests/Browser/IndexTest.php new file mode 100644 index 0000000..dfb574f --- /dev/null +++ b/tests/Browser/IndexTest.php @@ -0,0 +1,21 @@ +browse(function (Browser $browser) { + $browser->visit('/') + ->assertSee('Ranqueamento'); + }); + } +} diff --git a/tests/Browser/LoginTest.php b/tests/Browser/LoginTest.php new file mode 100644 index 0000000..e03839e --- /dev/null +++ b/tests/Browser/LoginTest.php @@ -0,0 +1,26 @@ +browse(function (Browser $browser) { + // Login como admin + $browser->visit('/login') + ->type('#callback', 'http://ranqueamento/callback') + ->type('#loginUsuario', '1111') + ->press('Login') + ->waitForText('Ranqueamento') + ->assertSee('Sair'); + }); + } +} 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/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..020699d --- /dev/null +++ b/tests/DuskTestCase.php @@ -0,0 +1,48 @@ +addArguments(collect([ + $this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080', + '--disable-search-engine-choice-screen', + '--disable-smooth-scrolling', + ])->unless($this->hasHeadlessDisabled(), function (Collection $items) { + return $items->merge([ + '--disable-gpu', + '--headless=new', + ]); + })->all()); + + return RemoteWebDriver::create( + $_ENV['DUSK_DRIVER_URL'] ?? env('DUSK_DRIVER_URL') ?? 'http://localhost:9515', + DesiredCapabilities::chrome()->setCapability( + ChromeOptions::CAPABILITY, $options + ) + ); + } +}