From f21aba50155f825edba397d0c3cd13f9cb8c82ea Mon Sep 17 00:00:00 2001 From: etiti <emmanueltiti370@gmail.com> Date: Mon, 11 Nov 2024 23:20:49 +0300 Subject: [PATCH 1/5] creting review model, test for repository, adding types --- .../app/Contract/RepositoryInterface.php | 21 ++++ .../AssessmentReviewData.php | 32 +++++ application/app/Models/AssessmentReview.php | 13 ++ application/app/Models/IdeascaleProfile.php | 3 +- application/app/Policies/ReviewPolicy.php | 66 ++++++++++ .../AssessmentReviewRepository.php | 15 +++ application/app/Repositories/Repository.php | 32 ++--- .../app/Repositories/RepositoryInterface.php | 18 --- application/composer.json | 1 + application/composer.lock | 56 ++++++++- application/config/database.php | 6 +- .../factories/AssessmentReviewFactory.php | 28 +++++ .../factories/IdeascaleProfileFactory.php | 3 +- ...151958_create_ideascale_profiles_table.php | 2 +- ...2024_11_11_153139_create_reviews_table.php | 33 +++++ .../seeders/AssessmentReviewSeeder.php | 18 +++ .../database/seeders/DatabaseSeeder.php | 1 + application/phpunit.xml | 12 +- application/resources/types/generated.d.ts | 114 +++++++++++------- application/tests/Feature/RepositoryTest.php | 99 +++++++++++++++ 20 files changed, 477 insertions(+), 96 deletions(-) create mode 100644 application/app/Contract/RepositoryInterface.php create mode 100644 application/app/DataTransferObjects/AssessmentReviewData.php create mode 100644 application/app/Models/AssessmentReview.php create mode 100644 application/app/Policies/ReviewPolicy.php create mode 100644 application/app/Repositories/AssessmentReviewRepository.php delete mode 100644 application/app/Repositories/RepositoryInterface.php create mode 100644 application/database/factories/AssessmentReviewFactory.php create mode 100644 application/database/migrations/2024_11_11_153139_create_reviews_table.php create mode 100644 application/database/seeders/AssessmentReviewSeeder.php create mode 100644 application/tests/Feature/RepositoryTest.php diff --git a/application/app/Contract/RepositoryInterface.php b/application/app/Contract/RepositoryInterface.php new file mode 100644 index 00000000..9f644315 --- /dev/null +++ b/application/app/Contract/RepositoryInterface.php @@ -0,0 +1,21 @@ +<?php + +declare(strict_types=1); + +namespace App\Contract; + +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Collection; + +interface RepositoryInterface +{ + public function all(): array|Collection; + + public function find(int|string $id): Model; + + public function create(array $data): Model; + + public function update(array $data, $id): bool; + + public function delete(int|string $id): int; +} diff --git a/application/app/DataTransferObjects/AssessmentReviewData.php b/application/app/DataTransferObjects/AssessmentReviewData.php new file mode 100644 index 00000000..4f147694 --- /dev/null +++ b/application/app/DataTransferObjects/AssessmentReviewData.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace App\DataTransferObjects; + +use Spatie\LaravelData\Data; +use Spatie\TypeScriptTransformer\Attributes\Optional as TypeScriptOptional; +use Spatie\TypeScriptTransformer\Attributes\TypeScript; + +#[TypeScript] +final class AssessmentReviewData extends Data +{ + public function __construct( + public ?int $id, + + #[TypeScriptOptional] + public ?int $assessor_id, + + public int $excellent_count, + + public int $good_count, + + public int $filtered_out_count, + + public bool $flagged, + + #[TypeScriptOptional] + public ?array $qa_rationale, + + ) {} +} diff --git a/application/app/Models/AssessmentReview.php b/application/app/Models/AssessmentReview.php new file mode 100644 index 00000000..eea64d7f --- /dev/null +++ b/application/app/Models/AssessmentReview.php @@ -0,0 +1,13 @@ +<?php + +declare(strict_types=1); + +namespace App\Models; + +use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Model; + +class AssessmentReview extends Model +{ + use HasFactory; +} diff --git a/application/app/Models/IdeascaleProfile.php b/application/app/Models/IdeascaleProfile.php index be1a8f28..a21110e6 100755 --- a/application/app/Models/IdeascaleProfile.php +++ b/application/app/Models/IdeascaleProfile.php @@ -4,8 +4,9 @@ namespace App\Models; -use App\Casts\DateFormatCast; use App\Models\Model; +use App\Casts\DateFormatCast; +use Illuminate\Database\Eloquent\Factories\HasFactory; class IdeascaleProfile extends Model { diff --git a/application/app/Policies/ReviewPolicy.php b/application/app/Policies/ReviewPolicy.php new file mode 100644 index 00000000..6eacd68a --- /dev/null +++ b/application/app/Policies/ReviewPolicy.php @@ -0,0 +1,66 @@ +<?php + +namespace App\Policies; + +use App\Models\Review; +use App\Models\User; +use Illuminate\Auth\Access\Response; + +class ReviewPolicy +{ + /** + * Determine whether the user can view any models. + */ + public function viewAny(User $user): bool + { + // + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Review $review): bool + { + // + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + // + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Review $review): bool + { + // + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Review $review): bool + { + // + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Review $review): bool + { + // + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Review $review): bool + { + // + } +} diff --git a/application/app/Repositories/AssessmentReviewRepository.php b/application/app/Repositories/AssessmentReviewRepository.php new file mode 100644 index 00000000..a56fc6f3 --- /dev/null +++ b/application/app/Repositories/AssessmentReviewRepository.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +namespace App\Repositories; + +use App\Models\AssessmentReview; + +class AssessmentReviewRepository extends Repository +{ + public function __construct(AssessmentReview $model) + { + parent::__construct($model); + } +} diff --git a/application/app/Repositories/Repository.php b/application/app/Repositories/Repository.php index babc578d..0306c0a1 100644 --- a/application/app/Repositories/Repository.php +++ b/application/app/Repositories/Repository.php @@ -5,21 +5,21 @@ namespace App\Repositories; use App\Scopes\LimitScope; -use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Database\Eloquent\Collection; +use App\Contract\RepositoryInterface; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; class Repository implements RepositoryInterface { protected $query; - // Constructor to bind model to repo public function __construct(protected Model $model) { $this->setModel($model); } - // Get all instances of model public function all(): array|Collection { if ($this->query) { @@ -29,8 +29,7 @@ public function all(): array|Collection return $this->model->all(); } - // Get all instances of model - public function count() + public function count(): int { if ($this->query) { return $this->query->count(); @@ -39,8 +38,7 @@ public function count() return $this->model->count(); } - // get the record with the given id - public function find($idOrSlug, ...$params) + public function find(int|string $idOrSlug, ...$params): Model { if (is_int($idOrSlug)) { return $this->model->findOrFail($idOrSlug); @@ -49,22 +47,19 @@ public function find($idOrSlug, ...$params) return $this->model->where('slug', '=', $idOrSlug)->first(); } - // create a new record in the database - public function create(array $data) + public function create(array $data): Model { return $this->model->create($data); } - // update record in the database - public function update(array $data, $id) + public function update(array $data, $id): bool { $record = $this->model->find($id); return $record->update($data); } - // remove record from the database - public function delete($id) + public function delete($id): int { return $this->model->destroy($id); } @@ -87,17 +82,15 @@ public function paginate($perPage = null): LengthAwarePaginator return $this->getQuery()?->fastPaginate($perPage); } - // Get the associated model public function getModel(): Model { return $this->model; } - // Set the associated model public function setModel($model): static { $this->model = $model; - $this->query = $this->getModel()::query(); + $this->query = $this->model::query(); return $this; } @@ -109,13 +102,12 @@ public function setQuery($query): static return $this; } - public function getQuery() + public function getQuery(): Builder { return $this->query ?? $this->model::query(); } - // Eager load database relationships - public function with($relations) + public function with($relations): Builder { return $this->model->with($relations); } diff --git a/application/app/Repositories/RepositoryInterface.php b/application/app/Repositories/RepositoryInterface.php deleted file mode 100644 index 2aabd293..00000000 --- a/application/app/Repositories/RepositoryInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace App\Repositories; - -interface RepositoryInterface -{ - public function all(); - - public function find($id); - - public function create(array $data); - - public function update(array $data, $id); - - public function delete($id); -} diff --git a/application/composer.json b/application/composer.json index 6cfecd21..e8b3f4f8 100644 --- a/application/composer.json +++ b/application/composer.json @@ -6,6 +6,7 @@ "license": "MIT", "require": { "php": "^8.2", + "hammerstone/fast-paginate": "^1.1", "inertiajs/inertia-laravel": "2.x-dev", "laravel/framework": "^11.9", "laravel/horizon": "^5.29", diff --git a/application/composer.lock b/application/composer.lock index d5744224..55545509 100644 --- a/application/composer.lock +++ b/application/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": "4fdd26c781ec96df3d4a35da294ccbe1", + "content-hash": "ed4af2f793d87a04968ad8068f2887a9", "packages": [ { "name": "amphp/amp", @@ -2085,6 +2085,60 @@ ], "time": "2023-12-03T19:50:20+00:00" }, + { + "name": "hammerstone/fast-paginate", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/hammerstonedev/fast-paginate.git", + "reference": "6a1fb26c860d04176d00761ae8a93f04da14c81c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hammerstonedev/fast-paginate/zipball/6a1fb26c860d04176d00761ae8a93f04da14c81c", + "reference": "6a1fb26c860d04176d00761ae8a93f04da14c81c", + "shasum": "" + }, + "require": { + "illuminate/database": "^8.37|^9.0|^10.0|^11.0", + "php": "^7.4|^8.0" + }, + "require-dev": { + "laravel/scout": "^9.4|^10.8", + "mockery/mockery": "^1.3.3", + "orchestra/testbench": "^6|^7|^8.0|^9.0", + "phpunit/phpunit": ">=8.5.23|^9" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Hammerstone\\FastPaginate\\FastPaginateProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Hammerstone\\FastPaginate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Francis", + "email": "aaron@hammerstone.dev" + } + ], + "description": "Fast paginate for Laravel", + "support": { + "issues": "https://github.com/hammerstonedev/fast-paginate/issues", + "source": "https://github.com/hammerstonedev/fast-paginate/tree/v1.1.1" + }, + "time": "2024-05-16T15:45:29+00:00" + }, { "name": "inertiajs/inertia-laravel", "version": "2.x-dev", diff --git a/application/config/database.php b/application/config/database.php index 206cde66..730cd0b0 100644 --- a/application/config/database.php +++ b/application/config/database.php @@ -33,15 +33,13 @@ 'sqlite' => [ 'driver' => 'sqlite', - 'url' => env('DB_URL'), + 'url' => env('DATABASE_URL'), 'database' => env('DB_DATABASE', database_path('database.sqlite')), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), - 'busy_timeout' => null, - 'journal_mode' => null, - 'synchronous' => null, ], + 'mysql' => [ 'driver' => 'mysql', 'url' => env('DB_URL'), diff --git a/application/database/factories/AssessmentReviewFactory.php b/application/database/factories/AssessmentReviewFactory.php new file mode 100644 index 00000000..ff0b7323 --- /dev/null +++ b/application/database/factories/AssessmentReviewFactory.php @@ -0,0 +1,28 @@ +<?php + +namespace Database\Factories; + +use Illuminate\Database\Eloquent\Factories\Factory; + +/** + * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Review> + */ +class AssessmentReviewFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array<string, mixed> + */ + public function definition(): array + { + return [ + 'assessor_id' => 1, + 'excellent_count' => rand(0,100), + 'good_count' => rand(0, 100), + 'filtered_out_count' => rand(0, 100), + 'flagged' => $this->faker->randomElement([true,false]), + 'qa_rationale' => json_encode(['en',$this->faker->sentences(500,true)]) + ]; + } +} diff --git a/application/database/factories/IdeascaleProfileFactory.php b/application/database/factories/IdeascaleProfileFactory.php index 39d8b3f4..627a1d1f 100755 --- a/application/database/factories/IdeascaleProfileFactory.php +++ b/application/database/factories/IdeascaleProfileFactory.php @@ -4,6 +4,7 @@ namespace Database\Factories; +use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; class IdeascaleProfileFactory extends Factory @@ -34,7 +35,7 @@ public function definition() 'linkedin' => $this->faker->userName, 'discord' => $this->faker->userName, 'ideascale' => $this->faker->word, - 'claimed_by' => $this->faker->randomElement([null, $this->faker->numberBetween(1, 100)]), + 'claimed_by' => User::factory(), 'telegram' => $this->faker->userName, 'title' => $this->faker->jobTitle, ]; diff --git a/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php b/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php index 08393fc0..14681373 100755 --- a/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php +++ b/application/database/migrations/2024_11_06_151958_create_ideascale_profiles_table.php @@ -26,7 +26,7 @@ public function up() $table->string('linkedin')->nullable(); $table->string('discord')->nullable(); $table->string('ideascale')->nullable(); - $table->bigInteger('claimed_by')->nullable(); + $table->foreignId('claimed_by')->constrained('users')->nullable(); $table->string('telegram')->nullable(); $table->string('title', 255)->nullable(); }); diff --git a/application/database/migrations/2024_11_11_153139_create_reviews_table.php b/application/database/migrations/2024_11_11_153139_create_reviews_table.php new file mode 100644 index 00000000..476f8095 --- /dev/null +++ b/application/database/migrations/2024_11_11_153139_create_reviews_table.php @@ -0,0 +1,33 @@ +<?php + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class extends Migration +{ + /** + * Run the migrations. + */ + public function up(): void + { + Schema::create('assessment_reviews', function (Blueprint $table) { + $table->id(); + $table->timestamps(); + $table->foreignId('assessor_id'); + $table->integer('excellent_count')->default(0); + $table->integer('good_count')->default(0); + $table->integer('filtered_out_count')->default(0); + $table->json('qa_rationale')->nullable(); + $table->boolean('flagged')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('assesment_reviews'); + } +}; diff --git a/application/database/seeders/AssessmentReviewSeeder.php b/application/database/seeders/AssessmentReviewSeeder.php new file mode 100644 index 00000000..8360998e --- /dev/null +++ b/application/database/seeders/AssessmentReviewSeeder.php @@ -0,0 +1,18 @@ +<?php + +namespace Database\Seeders; + +use App\Models\AssessmentReview; +use Illuminate\Database\Console\Seeds\WithoutModelEvents; +use Illuminate\Database\Seeder; + +class AssessmentReviewSeeder extends Seeder +{ + /** + * Run the database seeds. + */ + public function run(): void + { + AssessmentReview::factory(10)->create(); + } +} diff --git a/application/database/seeders/DatabaseSeeder.php b/application/database/seeders/DatabaseSeeder.php index 475986ff..9bbbb157 100644 --- a/application/database/seeders/DatabaseSeeder.php +++ b/application/database/seeders/DatabaseSeeder.php @@ -18,6 +18,7 @@ public function run(): void $this->call([ UserSeeder::class, ProposalSeeder::class, + RoleSeeder::class ]); $this->call( diff --git a/application/phpunit.xml b/application/phpunit.xml index c09b5bcf..81ab12ee 100644 --- a/application/phpunit.xml +++ b/application/phpunit.xml @@ -1,9 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" - bootstrap="vendor/autoload.php" - colors="true" -> +<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true"> <testsuites> <testsuite name="Unit"> <directory>tests/Unit</directory> @@ -22,7 +18,11 @@ <env name="APP_MAINTENANCE_DRIVER" value="file"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_STORE" value="array"/> - <env name="DB_DATABASE" value="testing"/> + + <!-- Database Configuration for SQLite In-Memory Testing --> + <env name="DB_CONNECTION" value="sqlite"/> + <env name="DB_DATABASE" value=":memory:"/> + <env name="MAIL_MAILER" value="array"/> <env name="PULSE_ENABLED" value="false"/> <env name="QUEUE_CONNECTION" value="sync"/> diff --git a/application/resources/types/generated.d.ts b/application/resources/types/generated.d.ts index 9ffa96fc..252b2277 100644 --- a/application/resources/types/generated.d.ts +++ b/application/resources/types/generated.d.ts @@ -1,46 +1,72 @@ declare namespace App.DataTransferObjects { -export type ProposalData = { -id: number | null; -user_id: number | null; -campaign_id: number | null; -fund_id: number | null; -title: Array<any> | null; -slug: string; -website: string | null; -excerpt?: string; -amount_requested: number; -amount_received: number | null; -definition_of_success?: string; -status?: string; -funding_status?: string; -meta_data?: Array<any>; -funded_at?: string; -deleted_at?: string; -funding_updated_at?: string; -yes_votes_count: number | null; -no_votes_count: number | null; -abstain_votes_count: number | null; -comment_prompt?: string; -social_excerpt?: string; -team_id?: number; -ideascale_link?: string; -type?: string; -meta_title?: Array<any>; -problem?: Array<any>; -solution?: Array<any>; -experience?: Array<any>; -content?: Array<any>; -currency?: string; -opensource: boolean; -ranking_total?: number; -quickpitch?: string; -quickpitch_length?: number; -}; -export type UserData = { -id: number; -name: string; -email: string; -profile_photo_url: string; -email_verified_at: string; -}; + export type AssessmentReviewData = { + id: number | null; + assessor_id?: number; + excellent_count: number; + good_count: number; + filtered_out_count: number; + flagged: boolean; + qa_rationale?: Array<any>; + }; + export type IdeascaleProfileData = { + id: number | null; + ideascaleId?: number; + username?: string; + email?: string; + name?: string; + bio?: string; + createdAt?: string; + updatedAt?: string; + twitter?: string; + linkedin?: string; + discord?: string; + ideascale?: string; + claimedBy?: number; + telegram?: string; + title?: string; + }; + export type ProposalData = { + id: number | null; + user_id: number | null; + campaign_id: number | null; + fund_id: number | null; + title: Array<any> | null; + slug: string; + website: string | null; + excerpt?: string; + amount_requested: number; + amount_received: number | null; + definition_of_success?: string; + status?: string; + funding_status?: string; + meta_data?: Array<any>; + funded_at?: string; + deleted_at?: string; + funding_updated_at?: string; + yes_votes_count: number | null; + no_votes_count: number | null; + abstain_votes_count: number | null; + comment_prompt?: string; + social_excerpt?: string; + team_id?: number; + ideascale_link?: string; + type?: string; + meta_title?: Array<any>; + problem?: Array<any>; + solution?: Array<any>; + experience?: Array<any>; + content?: Array<any>; + currency?: string; + opensource: boolean; + ranking_total?: number; + quickpitch?: string; + quickpitch_length?: number; + }; + export type UserData = { + id: number; + name: string; + email: string; + profile_photo_url: string; + email_verified_at: string; + }; } diff --git a/application/tests/Feature/RepositoryTest.php b/application/tests/Feature/RepositoryTest.php new file mode 100644 index 00000000..91b4b126 --- /dev/null +++ b/application/tests/Feature/RepositoryTest.php @@ -0,0 +1,99 @@ +<?php + +declare(strict_types=1); + +use App\Models\Proposal; +use App\Models\User; +use App\Repositories\Repository; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; + +uses(RefreshDatabase::class); + +beforeEach(function () { + // Initialize repository with the User model + $this->repository = new Repository(new User()); +}); + +it('returns all records with all method', function () { + User::factory()->count(3)->create(); + $records = $this->repository->all(); + + expect($records)->toBeInstanceOf(Collection::class) + ->and($records)->toHaveCount(3); +}); + +it('returns correct record count with count method', function () { + User::factory()->count(5)->create(); + $count = $this->repository->count(); + + expect($count)->toBeInt()->toEqual(5); +}); + +it('retrieves by id with find method', function () { + $user = User::factory()->create([ + 'name' => 'Sample User', + ]); + + $foundById = $this->repository->find($user->id); + expect($foundById)->toBeInstanceOf(User::class) + ->and($foundById->id)->toEqual($user->id); +}); + +it('retrieves by id or slug with find method', function () { + + $this->repository = new Repository(new Proposal()); + + $proposal = Proposal::factory(state: [ + 'title' => json_encode(['en' => 'Nice proposal']), + 'slug' => 'nice-proposal' + ])->create(); + + $foundById = $this->repository->find($proposal->id); + expect($foundById)->toBeInstanceOf(Proposal::class) + ->and($foundById->id)->toEqual($proposal->id); + + $foundBySlug = $this->repository->find('nice-proposal'); + expect($foundBySlug)->toBeInstanceOf(Proposal::class) + ->and($foundBySlug->slug)->toEqual('nice-proposal'); +}); + +it('creates a new record with create method', function () { + $data = ['name' => 'New User', 'email' => 'newuser@example.com', 'password' => bcrypt('password')]; + $user = $this->repository->create($data); + + expect($user)->toBeInstanceOf(User::class) + ->and($user->name)->toEqual('New User'); +}); + +it('updates existing record with update method', function () { + $user = User::factory()->create(['name' => 'Old Name']); + $updated = $this->repository->update(['name' => 'Updated Name'], $user->id); + + expect($updated)->toBeTrue() + ->and($user->refresh()->name)->toEqual('Updated Name'); +}); + +it('deletes a record by id with delete method', function () { + $user = User::factory()->create(); + $deleted = $this->repository->delete($user->id); + + expect($deleted)->toEqual(1) + ->and(User::find($user->id))->toBeNull(); +}); + +it('applies limit to query with limit method', function () { + User::factory()->count(10)->create(); + $records = $this->repository->limit(5)->all(); + + expect($records)->toHaveCount(5); +}); + +it('returns paginated result with paginate method', function () { + User::factory()->count(15)->create(); + $paginator = $this->repository->paginate(5); + + expect($paginator)->toBeInstanceOf(LengthAwarePaginator::class) + ->and($paginator->perPage())->toEqual(5); +}); -- GitLab From fad3ebb55742d9db11366c0892eab14aadad0232 Mon Sep 17 00:00:00 2001 From: etiti <emmanueltiti370@gmail.com> Date: Mon, 11 Nov 2024 23:33:50 +0300 Subject: [PATCH 2/5] deprecate assesment nomenclature --- .../DataTransferObjects/AssessmentReviewData.php | 4 ++-- .../Models/{AssessmentReview.php => Review.php} | 2 +- .../Repositories/AssessmentReviewRepository.php | 15 --------------- application/app/Repositories/ReviewRepository.php | 15 +++++++++++++++ ...essmentReviewFactory.php => ReviewFactory.php} | 2 +- .../2024_11_11_153139_create_reviews_table.php | 4 ++-- ...ssessmentReviewSeeder.php => ReviewSeeder.php} | 6 +++--- 7 files changed, 24 insertions(+), 24 deletions(-) rename application/app/Models/{AssessmentReview.php => Review.php} (82%) delete mode 100644 application/app/Repositories/AssessmentReviewRepository.php create mode 100644 application/app/Repositories/ReviewRepository.php rename application/database/factories/{AssessmentReviewFactory.php => ReviewFactory.php} (93%) rename application/database/seeders/{AssessmentReviewSeeder.php => ReviewSeeder.php} (63%) diff --git a/application/app/DataTransferObjects/AssessmentReviewData.php b/application/app/DataTransferObjects/AssessmentReviewData.php index 4f147694..45d6a8a6 100644 --- a/application/app/DataTransferObjects/AssessmentReviewData.php +++ b/application/app/DataTransferObjects/AssessmentReviewData.php @@ -9,13 +9,13 @@ use Spatie\TypeScriptTransformer\Attributes\TypeScript; #[TypeScript] -final class AssessmentReviewData extends Data +final class ReviewData extends Data { public function __construct( public ?int $id, #[TypeScriptOptional] - public ?int $assessor_id, + public ?int $reviewer_id, public int $excellent_count, diff --git a/application/app/Models/AssessmentReview.php b/application/app/Models/Review.php similarity index 82% rename from application/app/Models/AssessmentReview.php rename to application/app/Models/Review.php index eea64d7f..12cad7d1 100644 --- a/application/app/Models/AssessmentReview.php +++ b/application/app/Models/Review.php @@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -class AssessmentReview extends Model +class Review extends Model { use HasFactory; } diff --git a/application/app/Repositories/AssessmentReviewRepository.php b/application/app/Repositories/AssessmentReviewRepository.php deleted file mode 100644 index a56fc6f3..00000000 --- a/application/app/Repositories/AssessmentReviewRepository.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace App\Repositories; - -use App\Models\AssessmentReview; - -class AssessmentReviewRepository extends Repository -{ - public function __construct(AssessmentReview $model) - { - parent::__construct($model); - } -} diff --git a/application/app/Repositories/ReviewRepository.php b/application/app/Repositories/ReviewRepository.php new file mode 100644 index 00000000..134991a9 --- /dev/null +++ b/application/app/Repositories/ReviewRepository.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +namespace App\Repositories; + +use App\Models\Review; + +class ReviewRepository extends Repository +{ + public function __construct(Review $model) + { + parent::__construct($model); + } +} diff --git a/application/database/factories/AssessmentReviewFactory.php b/application/database/factories/ReviewFactory.php similarity index 93% rename from application/database/factories/AssessmentReviewFactory.php rename to application/database/factories/ReviewFactory.php index ff0b7323..d7455379 100644 --- a/application/database/factories/AssessmentReviewFactory.php +++ b/application/database/factories/ReviewFactory.php @@ -7,7 +7,7 @@ /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Review> */ -class AssessmentReviewFactory extends Factory +class ReviewFactory extends Factory { /** * Define the model's default state. diff --git a/application/database/migrations/2024_11_11_153139_create_reviews_table.php b/application/database/migrations/2024_11_11_153139_create_reviews_table.php index 476f8095..f8324011 100644 --- a/application/database/migrations/2024_11_11_153139_create_reviews_table.php +++ b/application/database/migrations/2024_11_11_153139_create_reviews_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('assessment_reviews', function (Blueprint $table) { + Schema::create('reviews', function (Blueprint $table) { $table->id(); $table->timestamps(); $table->foreignId('assessor_id'); @@ -28,6 +28,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('assesment_reviews'); + Schema::dropIfExists('reviews'); } }; diff --git a/application/database/seeders/AssessmentReviewSeeder.php b/application/database/seeders/ReviewSeeder.php similarity index 63% rename from application/database/seeders/AssessmentReviewSeeder.php rename to application/database/seeders/ReviewSeeder.php index 8360998e..6e51eb83 100644 --- a/application/database/seeders/AssessmentReviewSeeder.php +++ b/application/database/seeders/ReviewSeeder.php @@ -2,17 +2,17 @@ namespace Database\Seeders; -use App\Models\AssessmentReview; +use App\Models\Review; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; -class AssessmentReviewSeeder extends Seeder +class ReviewSeeder extends Seeder { /** * Run the database seeds. */ public function run(): void { - AssessmentReview::factory(10)->create(); + Review::factory(10)->create(); } } -- GitLab From f37ebe302c6db6934c2b39aa6af423e405cab3ca Mon Sep 17 00:00:00 2001 From: etiti <emmanueltiti370@gmail.com> Date: Mon, 11 Nov 2024 23:37:57 +0300 Subject: [PATCH 3/5] update review policy --- application/app/Policies/ReviewPolicy.php | 39 ++++++++--------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/application/app/Policies/ReviewPolicy.php b/application/app/Policies/ReviewPolicy.php index 6eacd68a..be0115f4 100644 --- a/application/app/Policies/ReviewPolicy.php +++ b/application/app/Policies/ReviewPolicy.php @@ -1,27 +1,30 @@ <?php +declare(strict_types=1); + namespace App\Policies; -use App\Models\Review; use App\Models\User; +use App\Enums\RoleEnum; +use App\Enums\PermissionEnum; use Illuminate\Auth\Access\Response; -class ReviewPolicy +class ReviewPolicy extends AppPolicy { /** * Determine whether the user can view any models. */ public function viewAny(User $user): bool { - // + return parent::canViewAny($user) || $user->hasAnyPermission([PermissionEnum::read_users()->value]); } /** * Determine whether the user can view the model. */ - public function view(User $user, Review $review): bool + public function view(User $user, User $model): bool { - // + return parent::canView($user, $model) || $user->hasAnyPermission([PermissionEnum::read_users()->value]); } /** @@ -29,38 +32,22 @@ public function view(User $user, Review $review): bool */ public function create(User $user): bool { - // + return parent::canCreate($user) || $user->hasAnyPermission([PermissionEnum::create_users()->value]); } /** * Determine whether the user can update the model. */ - public function update(User $user, Review $review): bool + public function update(User $user, User $model): bool { - // + return parent::canUpdate($user, $model) || $user->hasAnyPermission([PermissionEnum::update_users()->value]); } /** * Determine whether the user can delete the model. */ - public function delete(User $user, Review $review): bool - { - // - } - - /** - * Determine whether the user can restore the model. - */ - public function restore(User $user, Review $review): bool - { - // - } - - /** - * Determine whether the user can permanently delete the model. - */ - public function forceDelete(User $user, Review $review): bool + public function delete(User $user, User $model): bool { - // + return parent::canDelete($user, $model) || $user->hasAnyPermission([PermissionEnum::delete_users()->value]); } } -- GitLab From c557820434700010dc92009213aa8207def61833 Mon Sep 17 00:00:00 2001 From: etiti <emmanueltiti370@gmail.com> Date: Mon, 11 Nov 2024 23:45:30 +0300 Subject: [PATCH 4/5] update review model name to ReviewModeration --- application/app/Models/{Review.php => ReviewModeration.php} | 2 +- .../{ReviewPolicy.php => ReviewModerationPolicy.php} | 2 +- application/app/Repositories/ReviewRepository.php | 4 ++-- .../{ReviewFactory.php => ReviewModerationFactory.php} | 4 ++-- .../migrations/2024_11_11_153139_create_reviews_table.php | 6 +++--- .../{ReviewSeeder.php => ReviewModerationSeeder.php} | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) rename application/app/Models/{Review.php => ReviewModeration.php} (82%) rename application/app/Policies/{ReviewPolicy.php => ReviewModerationPolicy.php} (96%) rename application/database/factories/{ReviewFactory.php => ReviewModerationFactory.php} (89%) rename application/database/seeders/{ReviewSeeder.php => ReviewModerationSeeder.php} (63%) diff --git a/application/app/Models/Review.php b/application/app/Models/ReviewModeration.php similarity index 82% rename from application/app/Models/Review.php rename to application/app/Models/ReviewModeration.php index 12cad7d1..5243f8cb 100644 --- a/application/app/Models/Review.php +++ b/application/app/Models/ReviewModeration.php @@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -class Review extends Model +class ReviewModeration extends Model { use HasFactory; } diff --git a/application/app/Policies/ReviewPolicy.php b/application/app/Policies/ReviewModerationPolicy.php similarity index 96% rename from application/app/Policies/ReviewPolicy.php rename to application/app/Policies/ReviewModerationPolicy.php index be0115f4..bfbd3451 100644 --- a/application/app/Policies/ReviewPolicy.php +++ b/application/app/Policies/ReviewModerationPolicy.php @@ -9,7 +9,7 @@ use App\Enums\PermissionEnum; use Illuminate\Auth\Access\Response; -class ReviewPolicy extends AppPolicy +class ReviewModerationPolicy extends AppPolicy { /** * Determine whether the user can view any models. diff --git a/application/app/Repositories/ReviewRepository.php b/application/app/Repositories/ReviewRepository.php index 134991a9..6bb287b2 100644 --- a/application/app/Repositories/ReviewRepository.php +++ b/application/app/Repositories/ReviewRepository.php @@ -4,11 +4,11 @@ namespace App\Repositories; -use App\Models\Review; +use App\Models\ReviewModeration; class ReviewRepository extends Repository { - public function __construct(Review $model) + public function __construct(ReviewModeration $model) { parent::__construct($model); } diff --git a/application/database/factories/ReviewFactory.php b/application/database/factories/ReviewModerationFactory.php similarity index 89% rename from application/database/factories/ReviewFactory.php rename to application/database/factories/ReviewModerationFactory.php index d7455379..07e277ee 100644 --- a/application/database/factories/ReviewFactory.php +++ b/application/database/factories/ReviewModerationFactory.php @@ -7,7 +7,7 @@ /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Review> */ -class ReviewFactory extends Factory +class ReviewModerationFactory extends Factory { /** * Define the model's default state. @@ -17,7 +17,7 @@ class ReviewFactory extends Factory public function definition(): array { return [ - 'assessor_id' => 1, + 'reviewer_id' => 1, 'excellent_count' => rand(0,100), 'good_count' => rand(0, 100), 'filtered_out_count' => rand(0, 100), diff --git a/application/database/migrations/2024_11_11_153139_create_reviews_table.php b/application/database/migrations/2024_11_11_153139_create_reviews_table.php index f8324011..c360ce48 100644 --- a/application/database/migrations/2024_11_11_153139_create_reviews_table.php +++ b/application/database/migrations/2024_11_11_153139_create_reviews_table.php @@ -11,10 +11,10 @@ */ public function up(): void { - Schema::create('reviews', function (Blueprint $table) { + Schema::create('review_moderations', function (Blueprint $table) { $table->id(); $table->timestamps(); - $table->foreignId('assessor_id'); + $table->foreignId('reviewer_id'); $table->integer('excellent_count')->default(0); $table->integer('good_count')->default(0); $table->integer('filtered_out_count')->default(0); @@ -28,6 +28,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('reviews'); + Schema::dropIfExists('review_moderations'); } }; diff --git a/application/database/seeders/ReviewSeeder.php b/application/database/seeders/ReviewModerationSeeder.php similarity index 63% rename from application/database/seeders/ReviewSeeder.php rename to application/database/seeders/ReviewModerationSeeder.php index 6e51eb83..935ed183 100644 --- a/application/database/seeders/ReviewSeeder.php +++ b/application/database/seeders/ReviewModerationSeeder.php @@ -2,17 +2,17 @@ namespace Database\Seeders; -use App\Models\Review; +use App\Models\ReviewModeration; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; -class ReviewSeeder extends Seeder +class ReviewModerationSeeder extends Seeder { /** * Run the database seeds. */ public function run(): void { - Review::factory(10)->create(); + ReviewModeration::factory(10)->create(); } } -- GitLab From 04c1bb1e628c7436f2142203bb9d8f602495f1b0 Mon Sep 17 00:00:00 2001 From: etiti <emmanueltiti370@gmail.com> Date: Mon, 11 Nov 2024 23:48:42 +0300 Subject: [PATCH 5/5] update ReviewModeration DTO --- ...ReviewData.php => ReviewModerationData.php} | 2 +- application/resources/types/generated.d.ts | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) rename application/app/DataTransferObjects/{AssessmentReviewData.php => ReviewModerationData.php} (92%) diff --git a/application/app/DataTransferObjects/AssessmentReviewData.php b/application/app/DataTransferObjects/ReviewModerationData.php similarity index 92% rename from application/app/DataTransferObjects/AssessmentReviewData.php rename to application/app/DataTransferObjects/ReviewModerationData.php index 45d6a8a6..3ac74ba3 100644 --- a/application/app/DataTransferObjects/AssessmentReviewData.php +++ b/application/app/DataTransferObjects/ReviewModerationData.php @@ -9,7 +9,7 @@ use Spatie\TypeScriptTransformer\Attributes\TypeScript; #[TypeScript] -final class ReviewData extends Data +final class ReviewModerationData extends Data { public function __construct( public ?int $id, diff --git a/application/resources/types/generated.d.ts b/application/resources/types/generated.d.ts index 252b2277..97576335 100644 --- a/application/resources/types/generated.d.ts +++ b/application/resources/types/generated.d.ts @@ -1,13 +1,4 @@ declare namespace App.DataTransferObjects { - export type AssessmentReviewData = { - id: number | null; - assessor_id?: number; - excellent_count: number; - good_count: number; - filtered_out_count: number; - flagged: boolean; - qa_rationale?: Array<any>; - }; export type IdeascaleProfileData = { id: number | null; ideascaleId?: number; @@ -62,6 +53,15 @@ declare namespace App.DataTransferObjects { quickpitch?: string; quickpitch_length?: number; }; + export type ReviewModerationData = { + id: number | null; + reviewer_id?: number; + excellent_count: number; + good_count: number; + filtered_out_count: number; + flagged: boolean; + qa_rationale?: Array<any>; + }; export type UserData = { id: number; name: string; -- GitLab