From 5560614d84e9fb3e6cdf1b38cd03061ea5f63d82 Mon Sep 17 00:00:00 2001 From: Max Snow Date: Sun, 18 May 2025 12:11:42 +1000 Subject: [PATCH 1/3] Package updates, testing updates --- composer.json | 21 ++-- test/app/Models/User.php | 21 ++-- test/database/factories/UserFactory.php | 96 +++++++++++++++---- ...8_04_30_000010_create_test_users_table.php | 2 + .../{seeds => seeders}/BaseSeeder.php | 14 +-- .../{seeds => seeders}/DatabaseSeeder.php | 4 +- .../{seeds => seeders}/ForumsSeeder.php | 8 +- .../{seeds => seeders}/PostsSeeder.php | 8 +- .../{seeds => seeders}/RoleTableSeeder.php | 2 + .../{seeds => seeders}/TagsSeeder.php | 8 +- .../{seeds => seeders}/TopicsSeeder.php | 8 +- .../{seeds => seeders}/UserStorySeeder.php | 8 +- test/tests/AppTestCase.php | 2 +- test/tests/SetupTestApp.php | 3 - 14 files changed, 141 insertions(+), 64 deletions(-) rename test/database/{seeds => seeders}/BaseSeeder.php (76%) rename test/database/{seeds => seeders}/DatabaseSeeder.php (85%) rename test/database/{seeds => seeders}/ForumsSeeder.php (64%) rename test/database/{seeds => seeders}/PostsSeeder.php (77%) rename test/database/{seeds => seeders}/RoleTableSeeder.php (97%) rename test/database/{seeds => seeders}/TagsSeeder.php (58%) rename test/database/{seeds => seeders}/TopicsSeeder.php (58%) rename test/database/{seeds => seeders}/UserStorySeeder.php (88%) diff --git a/composer.json b/composer.json index 20ce219..5d0da28 100644 --- a/composer.json +++ b/composer.json @@ -11,21 +11,20 @@ ], "require": { "php": "^8.2", - "api-ecosystem-for-laravel/dingo-api": "^4.4.1", - "php-open-source-saver/jwt-auth": "^2.7", - "illuminate/support": "^11.0", + "api-ecosystem-for-laravel/dingo-api": "^4.6", + "php-open-source-saver/jwt-auth": "^2.8", + "illuminate/support": "^12.0", "ramsey/uuid": "^4.7", - "nesbot/carbon": "^2.0|^3.0" + "nesbot/carbon": "^3.0" }, "require-dev": { "ext-json": "*", - "beyondcode/laravel-dump-server": "^2.0", - "fakerphp/faker": "^1.23", + "beyondcode/laravel-dump-server": "^2.1", + "fakerphp/faker": "^1.24", "mockery/mockery": "^1.6", "nunomaduro/collision": "^8.6", "phpunit/phpunit": "^11.5", - "orchestra/testbench": "^9.9", - "laravel/legacy-factories": "^1.0" + "orchestra/testbench": "^10.3" }, "autoload": { "psr-4": { @@ -37,9 +36,11 @@ "psr-4": { "Specialtactics\\L5Api\\Tests\\": "test/tests/", "Specialtactics\\L5Api\\Test\\Mocks\\": "test/mocks/", - "App\\": "test/app/" + "App\\": "test/app/", + "Database\\Factories\\": "test/database/factories/", + "Database\\Seeders\\": "test/database/seeders/" }, - "classmap": ["test/database/seeds/", "test/database/factories/"] + "classmap": ["test/database/migrations/"] }, "extra": { "laravel": { diff --git a/test/app/Models/User.php b/test/app/Models/User.php index ea61c0a..0b76628 100644 --- a/test/app/Models/User.php +++ b/test/app/Models/User.php @@ -2,6 +2,7 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Notifications\Notifiable; use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Passwords\CanResetPassword; @@ -9,9 +10,8 @@ use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; +use Illuminate\Support\Str; use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject; -use Hash; -use App\Models\Role; class User extends BaseModel implements AuthenticatableContract, @@ -19,7 +19,7 @@ class User extends BaseModel implements CanResetPasswordContract, JWTSubject { - use Authenticatable, Authorizable, CanResetPassword, Notifiable; + use Authenticatable, Authorizable, CanResetPassword, Notifiable, HasFactory; /** * @var int Auto increments integer key @@ -49,6 +49,16 @@ class User extends BaseModel implements 'password', 'remember_token', 'primary_role', ]; + /** + * The attributes that should be cast to native types. + * + * @var array + */ + protected $casts = [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + /** * Model's boot function */ @@ -57,10 +67,7 @@ public static function boot(): void parent::boot(); static::saving(function (User $user) { - // Hash user password, if not already hashed - if (Hash::needsRehash($user->password)) { - $user->password = Hash::make($user->password); - } + $user->email = Str::lower($user->email); }); } diff --git a/test/database/factories/UserFactory.php b/test/database/factories/UserFactory.php index 2be906c..e3921d6 100644 --- a/test/database/factories/UserFactory.php +++ b/test/database/factories/UserFactory.php @@ -1,24 +1,78 @@ define(App\Models\User::class, function (Faker $faker) { - return [ - 'name' => $faker->name, - 'email' => $faker->unique()->safeEmail, - 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret - 'remember_token' => Str::random(10), - ]; -}); +/** + * @extends Factory + */ +class UserFactory extends Factory +{ + public const DEFAULT_PASSWORD = 'secret'; + + /** + * The name of the factory's corresponding model. + * + * @var string + */ + protected $model = User::class; + + protected static ?Collection $allRoles = null; + + /** + * Retrieve all roles + */ + public static function getAllRoles(): Collection + { + if (is_null(static::$allRoles)) { + static::$allRoles = Role::all(); + } + + return static::$allRoles; + } + + /** + * Define the model's default state. + */ + public function definition(): array + { + return [ + 'name' => $this->faker->name(), + 'email' => microtime(true) . '_' . $this->faker->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => static::DEFAULT_PASSWORD, + 'remember_token' => Str::random(10), + 'active' => true, + ]; + } + + public function adminRole(): UserFactory + { + return $this->state(function (array $attributes): array { + return [ + 'primary_role' => static::getAllRoles() + ->firstWhere('name', '=', Role::ROLE_ADMIN) + ->getKey(), + ]; + }); + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): UserFactory + { + return $this->state(function (array $attributes): array { + return [ + 'email_verified_at' => null, + ]; + }); + } +} diff --git a/test/database/migrations/2018_04_30_000010_create_test_users_table.php b/test/database/migrations/2018_04_30_000010_create_test_users_table.php index 7d610a9..78a7051 100644 --- a/test/database/migrations/2018_04_30_000010_create_test_users_table.php +++ b/test/database/migrations/2018_04_30_000010_create_test_users_table.php @@ -21,9 +21,11 @@ public function up() $table->string('name'); $table->string('email')->unique(); $table->string('password'); + $table->boolean('active')->default(true); $table->uuid('primary_role')->nullable(); $table->foreign('primary_role')->references('role_id')->on('roles')->onDelete('set null'); + $table->timestamp('email_verified_at')->nullable(); $table->primary('user_id'); diff --git a/test/database/seeds/BaseSeeder.php b/test/database/seeders/BaseSeeder.php similarity index 76% rename from test/database/seeds/BaseSeeder.php rename to test/database/seeders/BaseSeeder.php index a14370f..3f5eee2 100644 --- a/test/database/seeds/BaseSeeder.php +++ b/test/database/seeders/BaseSeeder.php @@ -1,5 +1,7 @@ faker = Faker\Factory::create(); + $this->faker = \Faker\Factory::create(); $this->before(); @@ -25,7 +27,7 @@ public function run() $this->runAlways(); // Production Only - if (App::environment() == 'production') { + if (app()->environment() === 'production') { $this->runProduction(); } // Fake environments @@ -37,7 +39,7 @@ public function run() } /** - * Run fake seeds - for non production environments + * Run fake Seeders - for non production environments * * @return void */ @@ -45,7 +47,7 @@ public function runFake() { } /** - * Run seeds to be ran only on production environments + * Run Seeders to be ran only on production environments * * @return void */ @@ -53,7 +55,7 @@ public function runProduction() { } /** - * Run seeds to be ran on every environment (including production) + * Run Seeders to be ran on every environment (including production) * * @return void */ diff --git a/test/database/seeds/DatabaseSeeder.php b/test/database/seeders/DatabaseSeeder.php similarity index 85% rename from test/database/seeds/DatabaseSeeder.php rename to test/database/seeders/DatabaseSeeder.php index f0ba049..12996d5 100644 --- a/test/database/seeds/DatabaseSeeder.php +++ b/test/database/seeders/DatabaseSeeder.php @@ -1,11 +1,13 @@ create([ + User::factory()->create([ 'name' => 'Admin', 'email' => 'admin@admin.com', 'primary_role' => $roles->where('name', 'admin')->first()->role_id, ]); // Create regular user - factory(App\Models\User::class)->create([ + User::factory()->create([ 'name' => 'Bob', 'email' => 'bob@bob.com', 'primary_role' => $roles->where('name', 'regular')->first()->role_id, @@ -34,7 +36,7 @@ public function runFake() { // Assign fake roles to users for ($i = 0; $i < 5; ++$i) { - $user = factory(App\Models\User::class)->create([ + $user = User::factory()->create([ 'primary_role' => $roles->random()->role_id, ]); diff --git a/test/tests/AppTestCase.php b/test/tests/AppTestCase.php index b0656fe..60752da 100644 --- a/test/tests/AppTestCase.php +++ b/test/tests/AppTestCase.php @@ -7,7 +7,7 @@ use Illuminate\Foundation\Testing\DatabaseTransactions; use JWTAuth; use Specialtactics\L5Api\APIBoilerplate; -use UserStorySeeder; +use Database\Seeders\UserStorySeeder; class AppTestCase extends SetupTestApp { diff --git a/test/tests/SetupTestApp.php b/test/tests/SetupTestApp.php index 595d6cf..54b6daa 100644 --- a/test/tests/SetupTestApp.php +++ b/test/tests/SetupTestApp.php @@ -23,9 +23,6 @@ protected function setUp(): void // Load migrations for tests $this->loadMigrationsFrom(__DIR__ . '/../database/migrations'); - // Load factories for tests - $this->withFactories(__DIR__ . '/../database/factories'); - // Migrate and seed $this->artisan('migrate', ['--database' => 'testing', '--seed' => true]); } From cc4de1acbfcaa0bb29edb5c484b58cd751ccaf0e Mon Sep 17 00:00:00 2001 From: Max Snow Date: Sun, 18 May 2025 12:12:11 +1000 Subject: [PATCH 2/3] Test laravel 12 in ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cfd2d9..4f2ff51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: matrix: stability: [prefer-stable] php: [8.2, 8.3, 8.4] - laravel: [11] + laravel: [12] name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} From d9869f18ba75d8475771513c6bd54afbffbc6900 Mon Sep 17 00:00:00 2001 From: Max Snow Date: Sun, 18 May 2025 12:43:52 +1000 Subject: [PATCH 3/3] Update readme --- readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 73f40bf..eca89d5 100644 --- a/readme.md +++ b/readme.md @@ -13,9 +13,10 @@ Please go to [The boilerplate wiki](https://github.com/specialtactics/laravel-ap | Laravel Version | Boilerplate Version | Minimum PHP Version | Support Status | |-----------------|---------------------|---------------------|----------------| +| 12.x | 7.x.x | 8.2 | Supported | | 11.x | 6.x.x | 8.2 | Supported | -| 10.x | 5.x.x | 8.1 | Supported | -| 9.x | 4.x.x | 8.0 | Supported | +| 10.x | 5.x.x | 8.1 | Not Supported | +| 9.x | 4.x.x | 8.0 | Not Supported | | 8.x | 3.x.x | 7.3 | Not Supported | | 7.x | 2.x.x | 7.2.5 | Not Supported | | 6.x | 1.1.x | 7.2 | Not Supported |