diff --git a/AGENTS.md b/AGENTS.md index 3a4a6c0..73e2226 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,9 +23,3 @@ Before responding to the first user message in a session, you MUST: Skipping this protocol caused real bugs and rework in past sessions (work landed on master, TDD order was lost, formatter not run, banned constructs slipped in). Treat the protocol as non-negotiable. - -## Command execution - -When running commands that need the Nix devshell, set `login: false`. -The login shell resets `PATH` and can hide tools like `phpcs`, Cypress, -and the devshell Node version. diff --git a/backend/app/Auth/CreateSessionDto.php b/backend/app/Auth/CreateSessionDto.php index d22b708..2e5e2f7 100644 --- a/backend/app/Auth/CreateSessionDto.php +++ b/backend/app/Auth/CreateSessionDto.php @@ -12,6 +12,5 @@ class CreateSessionDto public User $user, public DateTimeImmutable $createdAt, public DateTimeImmutable $expiresAt, - ) { - } + ) {} } diff --git a/backend/app/Auth/EloquentSessionRepository.php b/backend/app/Auth/EloquentSessionRepository.php index 92689b7..01cd4be 100644 --- a/backend/app/Auth/EloquentSessionRepository.php +++ b/backend/app/Auth/EloquentSessionRepository.php @@ -8,9 +8,7 @@ use DateTimeZone; class EloquentSessionRepository implements SessionRepository { - public function __construct(private UserRepository $userRepo) - { - } + public function __construct(private UserRepository $userRepo) {} public function create(CreateSessionDto $dto): Session { diff --git a/backend/app/Auth/Session.php b/backend/app/Auth/Session.php index b95905b..b433114 100644 --- a/backend/app/Auth/Session.php +++ b/backend/app/Auth/Session.php @@ -12,8 +12,7 @@ class Session private User $user, private DateTimeImmutable $createdAt, private DateTimeImmutable $expiresAt, - ) { - } + ) {} public function getToken(): string { diff --git a/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUser.php b/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUser.php index e91d487..7e8c92c 100644 --- a/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUser.php +++ b/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUser.php @@ -14,8 +14,7 @@ class AuthenticateUser public function __construct( private UserRepository $userRepo, private PasswordHasher $hasher, - ) { - } + ) {} /** * @throws BadRequestException diff --git a/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUserRequest.php b/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUserRequest.php index d7cf6dd..aa8b1df 100644 --- a/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUserRequest.php +++ b/backend/app/Auth/UseCases/AuthenticateUser/AuthenticateUserRequest.php @@ -7,6 +7,5 @@ class AuthenticateUserRequest public function __construct( public ?string $email, public ?string $password, - ) { - } + ) {} } diff --git a/backend/app/Auth/UseCases/CreateSession/CreateSession.php b/backend/app/Auth/UseCases/CreateSession/CreateSession.php index 83014a6..db6403f 100644 --- a/backend/app/Auth/UseCases/CreateSession/CreateSession.php +++ b/backend/app/Auth/UseCases/CreateSession/CreateSession.php @@ -17,8 +17,7 @@ class CreateSession private SessionRepository $sessionRepo, private TokenGenerator $tokenGenerator, private Clock $clock, - ) { - } + ) {} public function execute(User $user): Session { diff --git a/backend/app/Auth/UseCases/Logout/Logout.php b/backend/app/Auth/UseCases/Logout/Logout.php index 793666b..31b16de 100644 --- a/backend/app/Auth/UseCases/Logout/Logout.php +++ b/backend/app/Auth/UseCases/Logout/Logout.php @@ -8,8 +8,7 @@ class Logout { public function __construct( private SessionRepository $sessionRepo, - ) { - } + ) {} public function execute(string $token): void { diff --git a/backend/app/Controllers/AuthController.php b/backend/app/Controllers/AuthController.php index 43c9964..841b4c4 100644 --- a/backend/app/Controllers/AuthController.php +++ b/backend/app/Controllers/AuthController.php @@ -20,8 +20,7 @@ class AuthController private AuthenticateUser $authenticateUser, private CreateSession $createSession, private Logout $logout, - ) { - } + ) {} public function login(Request $request): JsonResponse { @@ -34,13 +33,11 @@ class AuthController ); } catch (BadRequestException $exception) { return new JsonResponse( - ['error' => $exception->getMessage()], - 400 + ['error' => $exception->getMessage()], 400 ); } catch (UnauthorizedException $exception) { return new JsonResponse( - ['error' => $exception->getMessage()], - 401 + ['error' => $exception->getMessage()], 401 ); } @@ -74,7 +71,7 @@ class AuthController } /** - * @return array{id: int, email: string} + * @return array{id: int, email: string, firstname: string, lastname: string} */ private function buildUserPayload(User $user): array { diff --git a/backend/app/Controllers/SetController.php b/backend/app/Controllers/SetController.php deleted file mode 100644 index 1a035c9..0000000 --- a/backend/app/Controllers/SetController.php +++ /dev/null @@ -1,44 +0,0 @@ -setRepository->getAll() as $set) { - $sets[] = $this->buildSetPayload($set); - } - - return new JsonResponse([ - 'sets' => $sets, - ], 200); - } - - /** - * @return array{ - * id: int, - * name: string, - * description: string, - * iconImageUrl: string - * } - */ - private function buildSetPayload(DomainSet $set): array - { - return [ - 'id' => $set->getId(), - 'name' => $set->getName(), - 'description' => $set->getDescription(), - 'iconImageUrl' => $set->getIconImageUrl(), - ]; - } -} diff --git a/backend/app/Element/CreateElementDto.php b/backend/app/Element/CreateElementDto.php index b815300..db77dd7 100644 --- a/backend/app/Element/CreateElementDto.php +++ b/backend/app/Element/CreateElementDto.php @@ -10,6 +10,5 @@ class CreateElementDto public Set $set, public string $title, public ?Element $parentElement, - ) { - } + ) {} } diff --git a/backend/app/Element/Element.php b/backend/app/Element/Element.php index 143df26..9ef75f6 100644 --- a/backend/app/Element/Element.php +++ b/backend/app/Element/Element.php @@ -11,8 +11,7 @@ class Element private string $title, private Set $set, private ?Element $parentElement, - ) { - } + ) {} public function getId(): int { diff --git a/backend/app/Element/EloquentElementRepository.php b/backend/app/Element/EloquentElementRepository.php index 61e1433..56ec2e6 100644 --- a/backend/app/Element/EloquentElementRepository.php +++ b/backend/app/Element/EloquentElementRepository.php @@ -8,9 +8,7 @@ use DomainException; class EloquentElementRepository implements ElementRepository { - public function __construct(private SetRepository $setRepo) - { - } + public function __construct(private SetRepository $setRepo) {} public function create(CreateElementDto $dto): Element { diff --git a/backend/app/Element/UseCases/CreateElement/CreateElement.php b/backend/app/Element/UseCases/CreateElement/CreateElement.php index 9b32cd7..6656338 100644 --- a/backend/app/Element/UseCases/CreateElement/CreateElement.php +++ b/backend/app/Element/UseCases/CreateElement/CreateElement.php @@ -15,8 +15,7 @@ class CreateElement public function __construct( private ElementRepository $elementRepo, private SetRepository $setRepo, - ) { - } + ) {} /** * @throws BadRequestException diff --git a/backend/app/Element/UseCases/CreateElement/CreateElementRequest.php b/backend/app/Element/UseCases/CreateElement/CreateElementRequest.php index eef7e7e..b9f0dbd 100644 --- a/backend/app/Element/UseCases/CreateElement/CreateElementRequest.php +++ b/backend/app/Element/UseCases/CreateElement/CreateElementRequest.php @@ -8,6 +8,5 @@ class CreateElementRequest public ?int $setId, public ?string $title, public ?int $parentElementId, - ) { - } + ) {} } diff --git a/backend/app/Exceptions/BadRequestException.php b/backend/app/Exceptions/BadRequestException.php index 1670d31..b900f47 100644 --- a/backend/app/Exceptions/BadRequestException.php +++ b/backend/app/Exceptions/BadRequestException.php @@ -4,6 +4,4 @@ namespace App\Exceptions; use DomainException; -class BadRequestException extends DomainException -{ -} +class BadRequestException extends DomainException {} diff --git a/backend/app/Exceptions/UnauthorizedException.php b/backend/app/Exceptions/UnauthorizedException.php index 84f3f71..f5d406e 100644 --- a/backend/app/Exceptions/UnauthorizedException.php +++ b/backend/app/Exceptions/UnauthorizedException.php @@ -4,6 +4,4 @@ namespace App\Exceptions; use DomainException; -class UnauthorizedException extends DomainException -{ -} +class UnauthorizedException extends DomainException {} diff --git a/backend/app/Http/Middleware/AuthMiddleware.php b/backend/app/Http/Middleware/AuthMiddleware.php index 0589cdb..8e21ece 100644 --- a/backend/app/Http/Middleware/AuthMiddleware.php +++ b/backend/app/Http/Middleware/AuthMiddleware.php @@ -16,8 +16,7 @@ class AuthMiddleware public function __construct( private SessionRepository $sessionRepo, private Clock $clock, - ) { - } + ) {} /** * @param Closure(Request): Response $next diff --git a/backend/app/Set/CreateSetDto.php b/backend/app/Set/CreateSetDto.php index 934a410..2999a88 100644 --- a/backend/app/Set/CreateSetDto.php +++ b/backend/app/Set/CreateSetDto.php @@ -6,8 +6,5 @@ class CreateSetDto { public function __construct( public string $name, - public string $description, - public string $iconImageUrl, - ) { - } + ) {} } diff --git a/backend/app/Set/EloquentSetRepository.php b/backend/app/Set/EloquentSetRepository.php index d7db606..ef8976e 100644 --- a/backend/app/Set/EloquentSetRepository.php +++ b/backend/app/Set/EloquentSetRepository.php @@ -8,8 +8,6 @@ class EloquentSetRepository implements SetRepository { $model = SetModel::create([ 'name' => $dto->name, - 'description' => $dto->description, - 'icon_image_url' => $dto->iconImageUrl, ]); return $this->toDomain($model); @@ -38,8 +36,6 @@ class EloquentSetRepository implements SetRepository return new Set( id: $model->id, name: $model->name, - description: $model->description, - iconImageUrl: $model->icon_image_url, ); } } diff --git a/backend/app/Set/Set.php b/backend/app/Set/Set.php index bf44461..d045e70 100644 --- a/backend/app/Set/Set.php +++ b/backend/app/Set/Set.php @@ -7,10 +7,7 @@ class Set public function __construct( private int $id, private string $name, - private string $description, - private string $iconImageUrl, - ) { - } + ) {} public function getId(): int { @@ -21,14 +18,4 @@ class Set { return $this->name; } - - public function getDescription(): string - { - return $this->description; - } - - public function getIconImageUrl(): string - { - return $this->iconImageUrl; - } } diff --git a/backend/app/Set/SetModel.php b/backend/app/Set/SetModel.php index d80a6df..c30e2c9 100644 --- a/backend/app/Set/SetModel.php +++ b/backend/app/Set/SetModel.php @@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Model; /** * @property int $id * @property string $name - * @property string $description - * @property string $icon_image_url * * @method static Builder|SetModel newModelQuery() * @method static Builder|SetModel newQuery() @@ -25,5 +23,5 @@ class SetModel extends Model public $timestamps = false; - protected $fillable = ['name', 'description', 'icon_image_url']; + protected $fillable = ['name']; } diff --git a/backend/app/Shared/ValueObject/EmailAddress.php b/backend/app/Shared/ValueObject/EmailAddress.php index 00ed5cf..a744918 100644 --- a/backend/app/Shared/ValueObject/EmailAddress.php +++ b/backend/app/Shared/ValueObject/EmailAddress.php @@ -18,15 +18,15 @@ final readonly class EmailAddress $trimmed = trim($email); if ($trimmed === '' || ! str_contains($trimmed, '@')) { - throw new InvalidArgumentException(self::ERROR_MESSAGE . " $email"); + throw new InvalidArgumentException(self::ERROR_MESSAGE." $email"); } [$local, $domain] = explode('@', $trimmed, 2); $this->domain = mb_strtolower($domain); - $normalized = $local . '@' . $this->domain; + $normalized = $local.'@'.$this->domain; if (filter_var($normalized, FILTER_VALIDATE_EMAIL) === false) { - throw new InvalidArgumentException(self::ERROR_MESSAGE . " $email"); + throw new InvalidArgumentException(self::ERROR_MESSAGE." $email"); } $this->normalized = $normalized; diff --git a/backend/app/User/CreateUserDto.php b/backend/app/User/CreateUserDto.php index 848d9f7..d10b373 100644 --- a/backend/app/User/CreateUserDto.php +++ b/backend/app/User/CreateUserDto.php @@ -9,6 +9,5 @@ class CreateUserDto public function __construct( public EmailAddress $email, public string $passwordHash, - ) { - } + ) {} } diff --git a/backend/app/User/EloquentUserRepository.php b/backend/app/User/EloquentUserRepository.php index 8a1a2c9..f69ec4a 100644 --- a/backend/app/User/EloquentUserRepository.php +++ b/backend/app/User/EloquentUserRepository.php @@ -25,7 +25,7 @@ class EloquentUserRepository implements UserRepository public function findByEmailDomain(string $domain): array { - $models = UserModel::where('email', 'like', '%@' . $domain)->get(); + $models = UserModel::where('email', 'like', '%@'.$domain)->get(); $users = []; foreach ($models as $model) { $users[] = $this->toDomain($model); diff --git a/backend/app/User/User.php b/backend/app/User/User.php index e73b5aa..3d8ed63 100644 --- a/backend/app/User/User.php +++ b/backend/app/User/User.php @@ -10,8 +10,7 @@ class User private int $id, private EmailAddress $email, private string $passwordHash, - ) { - } + ) {} public function getId(): int { diff --git a/backend/app/User/UserModel.php b/backend/app/User/UserModel.php index 6bde5dd..7d8c09d 100644 --- a/backend/app/User/UserModel.php +++ b/backend/app/User/UserModel.php @@ -9,6 +9,12 @@ use Illuminate\Database\Eloquent\Model; * @property string $email * @property string $password_hash * + * @method static \Illuminate\Database\Eloquent\Builder|UserModel newModelQuery() + * @method static \Illuminate\Database\Eloquent\Builder|UserModel newQuery() + * @method static \Illuminate\Database\Eloquent\Builder|UserModel query() + * @method static \Illuminate\Database\Eloquent\Builder|UserModel whereEmail($value) + * @method static \Illuminate\Database\Eloquent\Builder|UserModel whereId($value) + * * @mixin \Eloquent */ class UserModel extends Model diff --git a/backend/config/auth.php b/backend/config/auth.php index 3f8d685..d7568ff 100644 --- a/backend/config/auth.php +++ b/backend/config/auth.php @@ -95,10 +95,7 @@ return [ 'passwords' => [ 'users' => [ 'provider' => 'users', - 'table' => env( - 'AUTH_PASSWORD_RESET_TOKEN_TABLE', - 'password_reset_tokens' - ), + 'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'), 'expire' => 60, 'throttle' => 60, ], diff --git a/backend/config/cache.php b/backend/config/cache.php index 8047361..c68acdf 100644 --- a/backend/config/cache.php +++ b/backend/config/cache.php @@ -112,10 +112,7 @@ return [ | */ - 'prefix' => env( - 'CACHE_PREFIX', - Str::slug((string) env('APP_NAME', 'laravel')) . '-cache-' - ), + 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'), /* |-------------------------------------------------------------------------- diff --git a/backend/config/database.php b/backend/config/database.php index aed38f9..abbb88e 100644 --- a/backend/config/database.php +++ b/backend/config/database.php @@ -111,10 +111,7 @@ return [ 'prefix' => '', 'prefix_indexes' => true, // 'encrypt' => env('DB_ENCRYPT', 'yes'), - // 'trust_server_certificate' => env( - // 'DB_TRUST_SERVER_CERTIFICATE', - // 'false' - // ), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), ], ], @@ -152,11 +149,7 @@ return [ 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'redis'), - 'prefix' => env( - 'REDIS_PREFIX', - Str::slug((string) env('APP_NAME', 'laravel')) - . '-database-' - ), + 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'), 'persistent' => env('REDIS_PERSISTENT', false), ], @@ -168,10 +161,7 @@ return [ 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_DB', '0'), 'max_retries' => env('REDIS_MAX_RETRIES', 3), - 'backoff_algorithm' => env( - 'REDIS_BACKOFF_ALGORITHM', - 'decorrelated_jitter' - ), + 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'), 'backoff_base' => env('REDIS_BACKOFF_BASE', 100), 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000), ], @@ -184,10 +174,7 @@ return [ 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_CACHE_DB', '1'), 'max_retries' => env('REDIS_MAX_RETRIES', 3), - 'backoff_algorithm' => env( - 'REDIS_BACKOFF_ALGORITHM', - 'decorrelated_jitter' - ), + 'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'), 'backoff_base' => env('REDIS_BACKOFF_BASE', 100), 'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000), ], diff --git a/backend/config/filesystems.php b/backend/config/filesystems.php index 9d9f625..37d8fca 100644 --- a/backend/config/filesystems.php +++ b/backend/config/filesystems.php @@ -41,10 +41,7 @@ return [ 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), - 'url' => rtrim( - env('APP_URL', 'http://localhost'), - '/' - ) . '/storage', + 'url' => rtrim(env('APP_URL', 'http://localhost'), '/').'/storage', 'visibility' => 'public', 'throw' => false, 'report' => false, @@ -58,10 +55,7 @@ return [ 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), - 'use_path_style_endpoint' => env( - 'AWS_USE_PATH_STYLE_ENDPOINT', - false - ), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 'throw' => false, 'report' => false, ], diff --git a/backend/config/logging.php b/backend/config/logging.php index fe06e47..b09cb25 100644 --- a/backend/config/logging.php +++ b/backend/config/logging.php @@ -89,10 +89,7 @@ return [ 'handler_with' => [ 'host' => env('PAPERTRAIL_URL'), 'port' => env('PAPERTRAIL_PORT'), - 'connectionString' => 'tls://' - . env('PAPERTRAIL_URL') - . ':' - . env('PAPERTRAIL_PORT'), + 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), ], 'processors' => [PsrLogMessageProcessor::class], ], diff --git a/backend/config/mail.php b/backend/config/mail.php index 8d18020..e32e88d 100644 --- a/backend/config/mail.php +++ b/backend/config/mail.php @@ -46,13 +46,7 @@ return [ 'username' => env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), 'timeout' => null, - 'local_domain' => env( - 'MAIL_EHLO_DOMAIN', - parse_url( - (string) env('APP_URL', 'http://localhost'), - PHP_URL_HOST - ) - ), + 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)), ], 'ses' => [ diff --git a/backend/config/queue.php b/backend/config/queue.php index e0f7e11..79c2c0a 100644 --- a/backend/config/queue.php +++ b/backend/config/queue.php @@ -57,10 +57,7 @@ return [ 'driver' => 'sqs', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), - 'prefix' => env( - 'SQS_PREFIX', - 'https://sqs.us-east-1.amazonaws.com/your-account-id' - ), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 'queue' => env('SQS_QUEUE', 'default'), 'suffix' => env('SQS_SUFFIX'), 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), diff --git a/backend/config/session.php b/backend/config/session.php index 34a19a2..f574482 100644 --- a/backend/config/session.php +++ b/backend/config/session.php @@ -129,7 +129,7 @@ return [ 'cookie' => env( 'SESSION_COOKIE', - Str::slug((string) env('APP_NAME', 'laravel')) . '-session' + Str::slug((string) env('APP_NAME', 'laravel')).'-session' ), /* @@ -193,7 +193,7 @@ return [ | take place, and can be used to mitigate CSRF attacks. By default, we | will set this value to "lax" to permit secure cross-site requests. | - | See MDN Set-Cookie SameSite documentation. + | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value | | Supported: "lax", "strict", "none", null | diff --git a/backend/database/migrations/2026_05_24_000000_sets_table.php b/backend/database/migrations/2026_05_24_000000_sets_table.php index f3ab093..a39348b 100644 --- a/backend/database/migrations/2026_05_24_000000_sets_table.php +++ b/backend/database/migrations/2026_05_24_000000_sets_table.php @@ -11,8 +11,6 @@ return new class extends Migration Schema::create('sets', function (Blueprint $table) { $table->id(); $table->string('name'); - $table->text('description'); - $table->string('icon_image_url'); }); } diff --git a/backend/database/seeders/SetSeeder.php b/backend/database/seeders/SetSeeder.php index b2ca3b5..2f2975c 100644 --- a/backend/database/seeders/SetSeeder.php +++ b/backend/database/seeders/SetSeeder.php @@ -15,10 +15,6 @@ class SetSeeder extends Seeder $set = $setRepository->create(new CreateSetDto( name: $title, - description: 'Baderech HaAvodah is a way of living - ' - . 'a structured path for inner and outer growth, ' - . 'spiritual refinement, and personal development.', - iconImageUrl: '/assets/baderech-haavodah-icon.png', )); } } diff --git a/backend/public/index.php b/backend/public/index.php index f1aabdc..ee8f07e 100644 --- a/backend/public/index.php +++ b/backend/public/index.php @@ -1,23 +1,20 @@ handleRequest(Request::capture()); diff --git a/backend/routes/api.php b/backend/routes/api.php index 92cd42d..9e1c55e 100644 --- a/backend/routes/api.php +++ b/backend/routes/api.php @@ -1,7 +1,6 @@ middleware(AuthMiddleware::class); -Route::get('/sets', [SetController::class, 'index']); diff --git a/backend/tests/Fakes/FakeClock.php b/backend/tests/Fakes/FakeClock.php index 7b14d8d..f112836 100644 --- a/backend/tests/Fakes/FakeClock.php +++ b/backend/tests/Fakes/FakeClock.php @@ -7,9 +7,7 @@ use DateTimeImmutable; class FakeClock implements Clock { - public function __construct(private DateTimeImmutable $currentTime) - { - } + public function __construct(private DateTimeImmutable $currentTime) {} public function now(): DateTimeImmutable { diff --git a/backend/tests/Fakes/FakeSetRepository.php b/backend/tests/Fakes/FakeSetRepository.php index 079ea93..295e619 100644 --- a/backend/tests/Fakes/FakeSetRepository.php +++ b/backend/tests/Fakes/FakeSetRepository.php @@ -19,8 +19,6 @@ class FakeSetRepository implements SetRepository $set = new DomainSet( id: $id, name: $dto->name, - description: $dto->description, - iconImageUrl: $dto->iconImageUrl, ); $this->setsById[$id] = $set; @@ -54,8 +52,6 @@ class FakeSetRepository implements SetRepository return new DomainSet( id: $set->getId(), name: $set->getName(), - description: $set->getDescription(), - iconImageUrl: $set->getIconImageUrl(), ); } } diff --git a/backend/tests/Fakes/FakeTokenGenerator.php b/backend/tests/Fakes/FakeTokenGenerator.php index 4788ab3..e10bbcf 100644 --- a/backend/tests/Fakes/FakeTokenGenerator.php +++ b/backend/tests/Fakes/FakeTokenGenerator.php @@ -12,9 +12,7 @@ class FakeTokenGenerator implements TokenGenerator /** * @param string[] $tokens */ - public function __construct(private array $tokens) - { - } + public function __construct(private array $tokens) {} public function generate(): string { diff --git a/backend/tests/Feature/SetsEndpointTest.php b/backend/tests/Feature/SetsEndpointTest.php deleted file mode 100644 index f1ab5cc..0000000 --- a/backend/tests/Feature/SetsEndpointTest.php +++ /dev/null @@ -1,48 +0,0 @@ -create(new CreateSetDto( - name: 'Baderech HaAvodah', - description: 'Baderech HaAvodah is a way of living', - iconImageUrl: '/assets/baderech-haavodah-icon.png', - )); - $dailyLearningSet = $setRepository->create(new CreateSetDto( - name: 'Daily Learning', - description: 'Daily learning for steady growth', - iconImageUrl: '/assets/daily-learning-icon.svg', - )); - - $response = $this->getJson('/api/sets'); - - $response->assertOk(); - $response->assertExactJson([ - 'sets' => [ - [ - 'id' => $baderechSet->getId(), - 'name' => $baderechSet->getName(), - 'description' => $baderechSet->getDescription(), - 'iconImageUrl' => $baderechSet->getIconImageUrl(), - ], - [ - 'id' => $dailyLearningSet->getId(), - 'name' => $dailyLearningSet->getName(), - 'description' => $dailyLearningSet->getDescription(), - 'iconImageUrl' => $dailyLearningSet->getIconImageUrl(), - ], - ], - ]); - } -} diff --git a/backend/tests/Unit/Auth/Middleware/AuthMiddlewareTest.php b/backend/tests/Unit/Auth/Middleware/AuthMiddlewareTest.php index 33689a5..45aaf3d 100644 --- a/backend/tests/Unit/Auth/Middleware/AuthMiddlewareTest.php +++ b/backend/tests/Unit/Auth/Middleware/AuthMiddlewareTest.php @@ -31,7 +31,7 @@ class AuthMiddlewareTest extends TestCase '2026-04-29T12:00:00', new DateTimeZone('UTC') ); - $this->sessionRepo = new FakeSessionRepository(); + $this->sessionRepo = new FakeSessionRepository; $this->clock = new FakeClock($this->now); $this->middleware = new AuthMiddleware( $this->sessionRepo, @@ -58,7 +58,7 @@ class AuthMiddlewareTest extends TestCase }; } - public function testMissingCookieReturnsUnauthorizedJson(): void + public function test_missing_cookie_returns_unauthorized_json(): void { $captured = null; $response = $this->middleware->handle( @@ -74,7 +74,7 @@ class AuthMiddlewareTest extends TestCase $this->assertNull($captured); } - public function testUnknownTokenReturnsUnauthorized(): void + public function test_unknown_token_returns_unauthorized(): void { $captured = null; $response = $this->middleware->handle( @@ -86,7 +86,7 @@ class AuthMiddlewareTest extends TestCase $this->assertNull($captured); } - public function testExpiredSessionReturnsUnauthorizedAndIsDeleted(): void + public function test_expired_session_returns_unauthorized_and_is_deleted(): void { $user = new User( id: 7, @@ -113,7 +113,7 @@ class AuthMiddlewareTest extends TestCase ); } - public function testValidSessionAttachesUserAndCallsNext(): void + public function test_valid_session_attaches_user_and_calls_next(): void { $user = new User( id: 7, diff --git a/backend/tests/Unit/Auth/UseCases/AuthenticateUserTest.php b/backend/tests/Unit/Auth/UseCases/AuthenticateUserTest.php index df43f2c..b39dbff 100644 --- a/backend/tests/Unit/Auth/UseCases/AuthenticateUserTest.php +++ b/backend/tests/Unit/Auth/UseCases/AuthenticateUserTest.php @@ -25,10 +25,7 @@ class AuthenticateUserTest extends TestCase $this->userRepo = new FakeUserRepository(); $this->hasher = new FakeHasher(); - $this->authenticateUser = new AuthenticateUser( - $this->userRepo, - $this->hasher - ); + $this->authenticateUser = new AuthenticateUser($this->userRepo, $this->hasher); } public function testAuthenticatesValidUser(): void diff --git a/backend/tests/Unit/Auth/UseCases/CreateSessionTest.php b/backend/tests/Unit/Auth/UseCases/CreateSessionTest.php index d9fba39..034d7c5 100644 --- a/backend/tests/Unit/Auth/UseCases/CreateSessionTest.php +++ b/backend/tests/Unit/Auth/UseCases/CreateSessionTest.php @@ -44,14 +44,8 @@ class CreateSessionTest extends TestCase $this->assertSame('fake-token-123', $session->getToken()); $this->assertSame($user, $session->getUser()); $this->assertFalse($session->isExpired($this->clock->now())); - $this->assertSame( - '2026-05-18 12:00:00', - $session->getCreatedAt()->format('Y-m-d H:i:s') - ); - $this->assertSame( - '2026-05-25 12:00:00', - $session->getExpiresAt()->format('Y-m-d H:i:s') - ); + $this->assertSame('2026-05-18 12:00:00', $session->getCreatedAt()->format('Y-m-d H:i:s')); + $this->assertSame('2026-05-25 12:00:00', $session->getExpiresAt()->format('Y-m-d H:i:s')); $stored = $this->sessionRepo->findByToken($session->getToken()); $this->assertNotNull($stored); diff --git a/backend/tests/Unit/Auth/UseCases/LogoutTest.php b/backend/tests/Unit/Auth/UseCases/LogoutTest.php index 84f6c28..5dda63f 100644 --- a/backend/tests/Unit/Auth/UseCases/LogoutTest.php +++ b/backend/tests/Unit/Auth/UseCases/LogoutTest.php @@ -25,11 +25,11 @@ class LogoutTest extends TestCase '2026-04-29T12:00:00', new DateTimeZone('UTC') ); - $this->sessionRepo = new FakeSessionRepository(); + $this->sessionRepo = new FakeSessionRepository; $this->useCase = new Logout($this->sessionRepo); } - public function testExistingTokenSessionIsRemoved(): void + public function test_existing_token_session_is_removed(): void { $this->sessionRepo->create(new CreateSessionDto( token: 'token-abc', @@ -47,7 +47,7 @@ class LogoutTest extends TestCase $this->assertNull($this->sessionRepo->findByToken('token-abc')); } - public function testUnknownTokenDoesNotThrow(): void + public function test_unknown_token_does_not_throw(): void { $this->useCase->execute('unknown-token'); diff --git a/backend/tests/Unit/Controllers/AuthControllerTest.php b/backend/tests/Unit/Controllers/AuthControllerTest.php index 29ce7de..1855c59 100644 --- a/backend/tests/Unit/Controllers/AuthControllerTest.php +++ b/backend/tests/Unit/Controllers/AuthControllerTest.php @@ -73,7 +73,7 @@ class AuthControllerTest extends TestCase ); } - public function testLoginReturns200AndSetsCookieOnSuccess(): void + public function test_login_returns_200_and_sets_cookie_on_success(): void { $email = 'user@example.com'; $password = 'password'; @@ -104,21 +104,21 @@ class AuthControllerTest extends TestCase ); } - public function testLoginReturns400WhenEmailMissing(): void + public function test_login_returns_400_when_email_missing(): void { $request = new Request(['password' => 'correctpassword']); $response = $this->controller->login($request); $this->assertEquals(400, $response->getStatusCode()); } - public function testLoginReturns400WhenPasswordMissing(): void + public function test_login_returns_400_when_password_missing(): void { $request = new Request(['email' => 'user@example.com']); $response = $this->controller->login($request); $this->assertEquals(400, $response->getStatusCode()); } - public function testLoginReturns401WhenCredentialsInvalid(): void + public function test_login_returns_401_when_credentials_invalid(): void { $this->seedStartupUser('user@example.com', 'correctpassword'); @@ -130,7 +130,7 @@ class AuthControllerTest extends TestCase $this->assertEquals(401, $response->getStatusCode()); } - public function testLogoutReturns204AndClearsCookie(): void + public function test_logout_returns_204_and_clears_cookie(): void { $this->seedStartupUser('user@example.com', 'correctpassword'); $loginRequest = new Request([ @@ -139,7 +139,7 @@ class AuthControllerTest extends TestCase ]); $this->controller->login($loginRequest); - $logoutRequest = new Request(); + $logoutRequest = new Request; $logoutRequest->cookies->set( AuthMiddleware::COOKIE_NAME, 'session-token-1' @@ -160,7 +160,7 @@ class AuthControllerTest extends TestCase $this->assertSame('', $cookies[0]->getValue()); } - public function testMeReturns200WithUserWhenAuthenticated(): void + public function test_me_returns_200_with_user_when_authenticated(): void { $email = 'me@example.com'; $user = $this->userRepo->create( @@ -170,7 +170,7 @@ class AuthControllerTest extends TestCase ) ); - $request = new Request(); + $request = new Request; $request->attributes->set('user', $user); $response = $this->controller->me($request); diff --git a/backend/tests/Unit/Element/ElementTest.php b/backend/tests/Unit/Element/ElementTest.php index 5d7ded2..3e914d9 100644 --- a/backend/tests/Unit/Element/ElementTest.php +++ b/backend/tests/Unit/Element/ElementTest.php @@ -10,12 +10,7 @@ class ElementTest extends TestCase { public function testCreatesElementWithNullableParent(): void { - $set = new DomainSet( - id: 1, - name: 'Daily learning', - description: 'Daily learning description', - iconImageUrl: '/assets/daily-learning-icon.svg', - ); + $set = new DomainSet(1, 'Daily learning'); $rootElement = new Element( id: 1, title: 'Root', diff --git a/backend/tests/Unit/Element/UseCases/CreateElementTest.php b/backend/tests/Unit/Element/UseCases/CreateElementTest.php index 340f49e..2d01fc6 100644 --- a/backend/tests/Unit/Element/UseCases/CreateElementTest.php +++ b/backend/tests/Unit/Element/UseCases/CreateElementTest.php @@ -7,7 +7,6 @@ use App\Element\UseCases\CreateElement\CreateElement; use App\Element\UseCases\CreateElement\CreateElementRequest; use App\Exceptions\BadRequestException; use App\Set\CreateSetDto; -use App\Set\Set as DomainSet; use DomainException; use Tests\Fakes\FakeElementRepository; use Tests\Fakes\FakeSetRepository; @@ -31,18 +30,11 @@ class CreateElementTest extends TestCase ); } - private function createSet(string $name): DomainSet - { - return $this->setRepo->create(new CreateSetDto( - name: $name, - description: "$name description", - iconImageUrl: '/assets/test-set-icon.svg', - )); - } - public function testCreatesRootElement(): void { - $set = $this->createSet('Daily learning'); + $set = $this->setRepo->create( + new CreateSetDto('Daily learning') + ); $element = $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), @@ -58,7 +50,9 @@ class CreateElementTest extends TestCase public function testCreatesChildElement(): void { - $set = $this->createSet('Daily learning'); + $set = $this->setRepo->create( + new CreateSetDto('Daily learning') + ); $rootElement = $this->createElement->execute( new CreateElementRequest( setId: $set->getId(), @@ -120,7 +114,9 @@ class CreateElementTest extends TestCase public function testThrowsWhenParentElementDoesNotExist(): void { - $set = $this->createSet('Daily learning'); + $set = $this->setRepo->create( + new CreateSetDto('Daily learning') + ); $this->expectException(DomainException::class); $this->expectExceptionMessage( @@ -136,7 +132,9 @@ class CreateElementTest extends TestCase public function testThrowsWhenRootElementAlreadyExists(): void { - $set = $this->createSet('Daily learning'); + $set = $this->setRepo->create( + new CreateSetDto('Daily learning') + ); $this->createElement->execute(new CreateElementRequest( setId: $set->getId(), title: 'Root', @@ -157,8 +155,12 @@ class CreateElementTest extends TestCase public function testThrowsWhenParentBelongsToAnotherSet(): void { - $parentSet = $this->createSet('Parent set'); - $childSet = $this->createSet('Child set'); + $parentSet = $this->setRepo->create( + new CreateSetDto('Parent set') + ); + $childSet = $this->setRepo->create( + new CreateSetDto('Child set') + ); $parentElement = $this->createElement->execute( new CreateElementRequest( setId: $parentSet->getId(), diff --git a/backend/tests/Unit/Set/SetTest.php b/backend/tests/Unit/Set/SetTest.php index b3159c2..a98ac5f 100644 --- a/backend/tests/Unit/Set/SetTest.php +++ b/backend/tests/Unit/Set/SetTest.php @@ -9,22 +9,9 @@ class SetTest extends TestCase { public function testCreatesSetWithName(): void { - $set = new DomainSet( - id: 1, - name: 'Daily learning', - description: 'A structured path for daily growth', - iconImageUrl: '/assets/daily-learning-icon.svg', - ); + $set = new DomainSet(1, 'Daily learning'); $this->assertSame(1, $set->getId()); $this->assertSame('Daily learning', $set->getName()); - $this->assertSame( - 'A structured path for daily growth', - $set->getDescription() - ); - $this->assertSame( - '/assets/daily-learning-icon.svg', - $set->getIconImageUrl() - ); } } diff --git a/frontend/rabbi_gerzi/cypress/e2e/media.cy.ts b/frontend/rabbi_gerzi/cypress/e2e/media.cy.ts deleted file mode 100644 index 1202ae9..0000000 --- a/frontend/rabbi_gerzi/cypress/e2e/media.cy.ts +++ /dev/null @@ -1,26 +0,0 @@ -describe('media page sets', () => { - it('fetches and renders seeded set cards', () => { - cy.visit('/media') - - cy.get('header.site-header').within(() => { - cy.contains('Torah Media').should('be.visible') - cy.contains('About').should('be.visible') - cy.contains('Contact').should('be.visible') - cy.contains('Donate').should('be.visible') - }) - cy.contains('h1', 'Torah Media').should('be.visible') - cy.get('[data-cy="media-set-grid"]').should('be.visible') - cy.get('[data-cy="media-set-card"]', { timeout: 10000 }) - .should('have.length', 1) - .first() - .within(() => { - cy.get('img[data-cy="media-set-icon"]') - .should('be.visible') - .and('have.attr', 'src') - .and('include', '/assets/baderech-haavodah-icon.png') - cy.contains('h2', 'Baderech HaAvodah').should('be.visible') - cy.contains('a structured path for inner and outer growth') - .should('be.visible') - }) - }) -}) diff --git a/frontend/rabbi_gerzi/public/assets/baderech-haavodah-icon.png b/frontend/rabbi_gerzi/public/assets/baderech-haavodah-icon.png deleted file mode 100644 index 72603bb..0000000 Binary files a/frontend/rabbi_gerzi/public/assets/baderech-haavodah-icon.png and /dev/null differ diff --git a/frontend/rabbi_gerzi/src/stores/mediaSets.ts b/frontend/rabbi_gerzi/src/stores/mediaSets.ts deleted file mode 100644 index 0ed97dd..0000000 --- a/frontend/rabbi_gerzi/src/stores/mediaSets.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { ref } from 'vue' -import { defineStore } from 'pinia' - -export interface MediaSet { - id: number - name: string - description: string - iconImageUrl: string -} - -interface SetsResponse { - sets: MediaSet[] -} - -const API_BASE_URL = import.meta.env.VITE_API_BASE_URL as string - -export const useMediaSetsStore = defineStore('mediaSets', () => { - const sets = ref([]) - const isLoading = ref(false) - const error = ref(null) - - async function fetchSets(): Promise { - error.value = null - isLoading.value = true - - try { - const response = await fetch(`${API_BASE_URL}/api/sets`) - - if (!response.ok) { - sets.value = [] - error.value = 'Could not load media sets' - return - } - - const data: SetsResponse = await response.json() - sets.value = data.sets - } catch { - sets.value = [] - error.value = 'Network error - could not load media sets' - } finally { - isLoading.value = false - } - } - - return { sets, isLoading, error, fetchSets } -}) diff --git a/frontend/rabbi_gerzi/src/views/MediaPage.vue b/frontend/rabbi_gerzi/src/views/MediaPage.vue index 314d3d3..b405d36 100644 --- a/frontend/rabbi_gerzi/src/views/MediaPage.vue +++ b/frontend/rabbi_gerzi/src/views/MediaPage.vue @@ -1,56 +1,17 @@