Tests fixed

This commit is contained in:
Dan Baker 2026-02-22 19:02:59 +00:00
parent 2418edccfd
commit 030c049ca8
13 changed files with 131 additions and 38 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@
.env.production
.phpactor.json
.phpunit.result.cache
/.composer
/.fleet
/.idea
/.nova

View file

@ -21,6 +21,10 @@ RUN apt-get update && apt-get install -y \
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Fix nginx permissions for rootless
RUN mkdir -p /var/lib/nginx/body /var/lib/nginx/proxy /var/lib/nginx/fastcgi /var/log/nginx /var/run \
&& chmod -R 777 /var/lib/nginx /var/log/nginx /var/run
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql pdo_pgsql mbstring exif pcntl bcmath gd zip
@ -42,7 +46,7 @@ RUN chown -R www-data:www-data /var/www/html \
&& chmod -R 755 /var/www/html/bootstrap/cache
# Expose port 80
EXPOSE 80
EXPOSE 8080
# Start supervisor
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

View file

@ -5,11 +5,12 @@ services:
dockerfile: Dockerfile
container_name: laravel-app
restart: unless-stopped
userns_mode: "keep-id"
working_dir: /var/www/html
volumes:
- ./:/var/www/html:Z
ports:
- "8080:80"
- "8080:8080"
networks:
- laravel
depends_on:
@ -53,6 +54,21 @@ services:
networks:
- laravel
phpmyadmin:
image: docker.io/phpmyadmin/phpmyadmin:latest
container_name: laravel-phpmyadmin
restart: unless-stopped
environment:
PMA_HOST: db
PMA_USER: root
PMA_PASSWORD: root
ports:
- "8081:80"
networks:
- laravel
depends_on:
- db
networks:
laravel:
driver: bridge

View file

@ -8,7 +8,8 @@
"require": {
"php": "^8.2",
"laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1"
"laravel/tinker": "^2.10.1",
"predis/predis": "^3.4"
},
"require-dev": {
"fakerphp/faker": "^1.23",

65
composer.lock generated
View file

@ -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": "c514d8f7b9fc5970bdd94287905ef584",
"content-hash": "d6bd2a26512dd52b870be9ab0b7d9c72",
"packages": [
{
"name": "brick/math",
@ -2603,6 +2603,69 @@
],
"time": "2025-12-27T19:41:33+00:00"
},
{
"name": "predis/predis",
"version": "v3.4.0",
"source": {
"type": "git",
"url": "https://github.com/predis/predis.git",
"reference": "1183f5732e6b10efd33f64984a96726eaecb59aa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/predis/predis/zipball/1183f5732e6b10efd33f64984a96726eaecb59aa",
"reference": "1183f5732e6b10efd33f64984a96726eaecb59aa",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"psr/http-message": "^1.0|^2.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.3",
"phpstan/phpstan": "^1.9",
"phpunit/phpcov": "^6.0 || ^8.0",
"phpunit/phpunit": "^8.0 || ~9.4.4"
},
"suggest": {
"ext-relay": "Faster connection with in-memory caching (>=0.6.2)"
},
"type": "library",
"autoload": {
"psr-4": {
"Predis\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Till Krüss",
"homepage": "https://till.im",
"role": "Maintainer"
}
],
"description": "A flexible and feature-complete Redis/Valkey client for PHP.",
"homepage": "http://github.com/predis/predis",
"keywords": [
"nosql",
"predis",
"redis"
],
"support": {
"issues": "https://github.com/predis/predis/issues",
"source": "https://github.com/predis/predis/tree/v3.4.0"
},
"funding": [
{
"url": "https://github.com/sponsors/tillkruss",
"type": "github"
}
],
"time": "2026-02-11T17:30:28+00:00"
},
{
"name": "psr/clock",
"version": "1.0.0",

View file

@ -1,6 +1,6 @@
server {
listen 80;
listen [::]:80;
listen 8080;
listen [::]:8080;
server_name localhost;
root /var/www/html/public;

View file

@ -1,8 +1,8 @@
[supervisord]
nodaemon=true
user=root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
logfile=/dev/stdout
logfile_maxbytes=0
pidfile=/tmp/supervisord.pid
[program:php-fpm]
command=/usr/local/sbin/php-fpm -F
@ -21,3 +21,12 @@ stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:queue-worker]
command=php /var/www/html/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

View file

@ -23,6 +23,8 @@
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="BROADCAST_CONNECTION" value="null"/>
<env name="CACHE_STORE" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>

View file

@ -27,7 +27,7 @@
</div>
@endif
<form method="POST" action="{{ route('login') }}">
<form method="POST" action="{{ route('magic-link.send') }}">
@csrf
<div class="mb-6">

View file

@ -10,7 +10,7 @@ Route::get('/', function () {
// Guest routes (unauthenticated users)
Route::middleware('guest')->group(function () {
Route::get('/login', [MagicLinkController::class, 'showLoginForm'])->name('login');
Route::post('/login', [MagicLinkController::class, 'sendLink'])->name('magic-link.send');
Route::post('/magic-link', [MagicLinkController::class, 'sendLink'])->name('magic-link.send');
Route::get('/verify-code', [MagicLinkController::class, 'showCodeForm'])->name('verify-code');
Route::post('/verify-code', [MagicLinkController::class, 'verifyCode'])->name('magic-link.verify-code');
Route::get('/auth/magic-link', [MagicLinkController::class, 'verifyLink'])->name('magic-link.verify');

View file

@ -7,7 +7,6 @@ use App\Models\MagicLoginToken;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\URL;
@ -165,27 +164,6 @@ class MagicLinkAuthTest extends TestCase
$this->assertGuest();
}
public function test_4_word_token_format_validation(): void
{
$token = MagicLoginToken::generate('test@example.com', '127.0.0.1', 'TestAgent');
$plainToken = $token->plain_token;
$this->assertMatchesRegularExpression(
'/^[a-z]+-[a-z]+-[a-z]+-[a-z]+$/',
$plainToken,
'Token should be 4 words separated by hyphens'
);
$words = explode('-', $plainToken);
$this->assertCount(4, $words, 'Token should contain exactly 4 words');
foreach ($words as $word) {
$this->assertNotEmpty($word, 'Each word should not be empty');
$this->assertMatchesRegularExpression('/^[a-z]+$/', $word, 'Each word should contain only lowercase letters');
}
}
public function test_remember_token_always_set(): void
{
$user = User::create([

View file

@ -2,11 +2,9 @@
namespace Tests;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
use DatabaseTransactions;
}

View file

@ -219,7 +219,7 @@ class MagicLoginTokenTest extends TestCase
public function test_token_expiry_is_15_minutes(): void
{
$beforeCreation = now()->addMinutes(15);
$beforeCreation = now()->startOfSecond()->addMinutes(15);
$token = MagicLoginToken::generate('test@example.com', '127.0.0.1', 'TestAgent');
@ -300,4 +300,25 @@ class MagicLoginTokenTest extends TestCase
$this->assertInstanceOf(\Illuminate\Support\Carbon::class, $token->used_at);
}
public function test_4_word_token_format_validation(): void
{
$token = MagicLoginToken::generate('test@example.com', '127.0.0.1', 'TestAgent');
$plainToken = $token->plain_token;
$this->assertMatchesRegularExpression(
'/^[a-z]+-[a-z]+-[a-z]+-[a-z]+$/',
$plainToken,
'Token should be 4 words separated by hyphens'
);
$words = explode('-', $plainToken);
$this->assertCount(4, $words, 'Token should contain exactly 4 words');
foreach ($words as $word) {
$this->assertNotEmpty($word, 'Each word should not be empty');
$this->assertMatchesRegularExpression('/^[a-z]+$/', $word, 'Each word should contain only lowercase letters');
}
}
}