From d2ebfb75c0ab186ca5d168b6a7fe3d234574af1c Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Fri, 10 Jul 2026 18:05:28 +0200 Subject: [PATCH 01/11] Create endpoint to get polices that should be accepted Bug: T429591 --- app/Http/Controllers/PoliciesController.php | 24 +++++++++++++++++++ app/Http/Resources/PoliciesCollection.php | 19 +++++++++++++++ routes/api.php | 1 + .../Controllers/PoliciesControllerTest.php | 14 +++++++++++ 4 files changed, 58 insertions(+) create mode 100644 app/Http/Controllers/PoliciesController.php create mode 100644 app/Http/Resources/PoliciesCollection.php create mode 100644 tests/Http/Controllers/PoliciesControllerTest.php diff --git a/app/Http/Controllers/PoliciesController.php b/app/Http/Controllers/PoliciesController.php new file mode 100644 index 00000000..960a28ab --- /dev/null +++ b/app/Http/Controllers/PoliciesController.php @@ -0,0 +1,24 @@ +selectRaw('MAX(id) as id') + ->groupBy('policy_type') + ->pluck('id'); + + $currentPolicies = Policy::whereIn('id', $latestPolicyIds)->get(); + return new PoliciesCollection($currentPolicies); + } +} diff --git a/app/Http/Resources/PoliciesCollection.php b/app/Http/Resources/PoliciesCollection.php new file mode 100644 index 00000000..e183cef2 --- /dev/null +++ b/app/Http/Resources/PoliciesCollection.php @@ -0,0 +1,19 @@ + + */ + public function toArray(Request $request): array { + return [ + 'items'=> $this->collection + ]; + } +} diff --git a/routes/api.php b/routes/api.php index f014ffbc..e88422c6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -21,6 +21,7 @@ $router->post('user/resetPassword', ['uses' => 'Auth\ResetPasswordController@reset']); $router->post('contact/sendMessage', ['uses' => 'ContactController@sendMessage']); $router->post('complaint/sendMessage', ['uses' => 'ComplaintController@sendMessage']); + $router->get('policies/current', ['uses' => 'PoliciesController@getCurrentPolicies']); $router->post('auth/login', ['uses' => 'Auth\LoginController@postLogin'])->name('login'); // Authed diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php new file mode 100644 index 00000000..aa7d5aa6 --- /dev/null +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -0,0 +1,14 @@ +create(); + } +} From 14506fd06d1787df3f9fc7459664d32d0a265134 Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Mon, 13 Jul 2026 12:27:34 +0200 Subject: [PATCH 02/11] Added unit tests --- app/Policy.php | 4 ++- database/factories/PolicyFactory.php | 26 +++++++++++++++++++ .../Controllers/PoliciesControllerTest.php | 17 +++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 database/factories/PolicyFactory.php diff --git a/app/Policy.php b/app/Policy.php index 44933192..95b9f499 100644 --- a/app/Policy.php +++ b/app/Policy.php @@ -5,6 +5,7 @@ use Carbon\CarbonImmutable; use Eloquent; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; /** @@ -24,10 +25,11 @@ * @method static Builder|Policy whereId($value) * @method static Builder|Policy wherePolicyType($value) * @method static Builder|Policy whereUpdatedAt($value) - * + * @method static \Database\Factories\PolicyFactory factory(...$parameters) * @mixin Eloquent */ class Policy extends Model { + use HasFactory; // define which attributes are mass assignable protected $fillable = [ 'policy_type', diff --git a/database/factories/PolicyFactory.php b/database/factories/PolicyFactory.php new file mode 100644 index 00000000..de713bd3 --- /dev/null +++ b/database/factories/PolicyFactory.php @@ -0,0 +1,26 @@ + + */ +class PolicyFactory extends Factory { + + protected $model = Policy::class; + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array { + return [ + 'policy_type' => $this->faker->randomElement(['terms-of-use','hosting-policy']), + 'active_from' => now(), + 'content_vue_file' => fake()->slug() . '.vue', + ]; + } +} diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php index aa7d5aa6..0c1148ae 100644 --- a/tests/Http/Controllers/PoliciesControllerTest.php +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -2,6 +2,7 @@ namespace Tests\Http\Controllers; +use App\Policy; use Illuminate\Foundation\Testing\DatabaseTransactions; use Tests\TestCase; @@ -9,6 +10,20 @@ class PoliciesControllerTest extends TestCase { use DatabaseTransactions; public function testGetCurrentPolicies(): void { - //$policy = Policy::factory()->create(); + // Future policy + Policy::factory()->create([ + 'active_from' => now()->addDay(), + ]); + // Active policy + Policy::factory()->create(); + // Active policy + Policy::factory()->create([ + 'active_from' => now()->subMonth(), + ]); + + $response = $this->getJson('/policies/current'); + + $response->assertOk(); + $response->assertJsonCount(2, 'data.items'); } } From ee33c8c0775913763c5c16d10776cb796dcc2cad Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Mon, 13 Jul 2026 12:41:14 +0200 Subject: [PATCH 03/11] Fix tests --- app/Http/Controllers/PoliciesController.php | 2 +- tests/Http/Controllers/PoliciesControllerTest.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/PoliciesController.php b/app/Http/Controllers/PoliciesController.php index 960a28ab..782520e8 100644 --- a/app/Http/Controllers/PoliciesController.php +++ b/app/Http/Controllers/PoliciesController.php @@ -13,7 +13,7 @@ public function getCurrentPolicies() { $now = CarbonImmutable::now(); // This works based on the assumption that the latest policy has the highest id given that id is AUTO_INCREMENT - $latestPolicyIds = Policy::where('active_from', '<=', $now) + $latestPolicyIds = Policy::where('active_from', '<', $now) ->selectRaw('MAX(id) as id') ->groupBy('policy_type') ->pluck('id'); diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php index 0c1148ae..61f4a66c 100644 --- a/tests/Http/Controllers/PoliciesControllerTest.php +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -15,8 +15,6 @@ public function testGetCurrentPolicies(): void { 'active_from' => now()->addDay(), ]); // Active policy - Policy::factory()->create(); - // Active policy Policy::factory()->create([ 'active_from' => now()->subMonth(), ]); @@ -24,6 +22,6 @@ public function testGetCurrentPolicies(): void { $response = $this->getJson('/policies/current'); $response->assertOk(); - $response->assertJsonCount(2, 'data.items'); + $response->assertJsonCount(1, 'data.items'); } } From a25966124102060ca5f2b0af6290a13ed3dac4d9 Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Mon, 13 Jul 2026 12:54:12 +0200 Subject: [PATCH 04/11] Fix linting --- app/Http/Controllers/PoliciesController.php | 3 +-- app/Http/Resources/PoliciesCollection.php | 2 +- app/Policy.php | 2 ++ database/factories/PolicyFactory.php | 7 ++++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/PoliciesController.php b/app/Http/Controllers/PoliciesController.php index 782520e8..5c860445 100644 --- a/app/Http/Controllers/PoliciesController.php +++ b/app/Http/Controllers/PoliciesController.php @@ -5,10 +5,8 @@ use App\Http\Resources\PoliciesCollection; use App\Policy; use Carbon\CarbonImmutable; -use Illuminate\Http\Request; class PoliciesController extends Controller { - public function getCurrentPolicies() { $now = CarbonImmutable::now(); @@ -19,6 +17,7 @@ public function getCurrentPolicies() { ->pluck('id'); $currentPolicies = Policy::whereIn('id', $latestPolicyIds)->get(); + return new PoliciesCollection($currentPolicies); } } diff --git a/app/Http/Resources/PoliciesCollection.php b/app/Http/Resources/PoliciesCollection.php index e183cef2..d233312b 100644 --- a/app/Http/Resources/PoliciesCollection.php +++ b/app/Http/Resources/PoliciesCollection.php @@ -13,7 +13,7 @@ class PoliciesCollection extends ResourceCollection { */ public function toArray(Request $request): array { return [ - 'items'=> $this->collection + 'items' => $this->collection, ]; } } diff --git a/app/Policy.php b/app/Policy.php index 95b9f499..d9eb662a 100644 --- a/app/Policy.php +++ b/app/Policy.php @@ -26,10 +26,12 @@ * @method static Builder|Policy wherePolicyType($value) * @method static Builder|Policy whereUpdatedAt($value) * @method static \Database\Factories\PolicyFactory factory(...$parameters) + * * @mixin Eloquent */ class Policy extends Model { use HasFactory; + // define which attributes are mass assignable protected $fillable = [ 'policy_type', diff --git a/database/factories/PolicyFactory.php b/database/factories/PolicyFactory.php index de713bd3..b53aa93b 100644 --- a/database/factories/PolicyFactory.php +++ b/database/factories/PolicyFactory.php @@ -4,13 +4,14 @@ use App\Policy; use Illuminate\Database\Eloquent\Factories\Factory; +use Illuminate\Database\Eloquent\Model; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Model> + * @extends Factory */ class PolicyFactory extends Factory { - protected $model = Policy::class; + /** * Define the model's default state. * @@ -18,7 +19,7 @@ class PolicyFactory extends Factory { */ public function definition(): array { return [ - 'policy_type' => $this->faker->randomElement(['terms-of-use','hosting-policy']), + 'policy_type' => $this->faker->randomElement(['terms-of-use', 'hosting-policy']), 'active_from' => now(), 'content_vue_file' => fake()->slug() . '.vue', ]; From ecc89530291bb7514e77b81ba130a938fbc54fbe Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Tue, 14 Jul 2026 17:37:32 +0200 Subject: [PATCH 05/11] Improve tests --- app/Http/Controllers/PoliciesController.php | 2 +- .../Controllers/PoliciesControllerTest.php | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/PoliciesController.php b/app/Http/Controllers/PoliciesController.php index 5c860445..1a3dfd65 100644 --- a/app/Http/Controllers/PoliciesController.php +++ b/app/Http/Controllers/PoliciesController.php @@ -7,7 +7,7 @@ use Carbon\CarbonImmutable; class PoliciesController extends Controller { - public function getCurrentPolicies() { + public function getCurrentPolicies(): PoliciesCollection { $now = CarbonImmutable::now(); // This works based on the assumption that the latest policy has the highest id given that id is AUTO_INCREMENT diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php index 61f4a66c..fbfdbb8c 100644 --- a/tests/Http/Controllers/PoliciesControllerTest.php +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -10,18 +10,38 @@ class PoliciesControllerTest extends TestCase { use DatabaseTransactions; public function testGetCurrentPolicies(): void { + $currentTime = now(); // Future policy Policy::factory()->create([ - 'active_from' => now()->addDay(), + 'policy_type' => 'terms-of-use', + 'active_from' => $currentTime->addDay(), ]); - // Active policy + // Old policy Policy::factory()->create([ - 'active_from' => now()->subMonth(), + 'policy_type' => 'hosting-policy', + 'active_from' => $currentTime->subMonth(), + ]); + // Active policies + $latestToUPolicy = Policy::factory()->create([ + 'policy_type' => 'terms-of-use', + 'active_from' => $currentTime->subMonth(), + ]); + $latestHostingPolicy = Policy::factory()->create([ + 'policy_type' => 'hosting-policy', + 'active_from' => $currentTime->subWeek(), ]); $response = $this->getJson('/policies/current'); $response->assertOk(); - $response->assertJsonCount(1, 'data.items'); + $response->assertJsonCount(2, 'data.items'); + $response->assertJsonFragment([ + 'id' => $latestToUPolicy->id, + 'active_from' => $latestToUPolicy->active_from, + ]); + $response->assertJsonFragment([ + 'id' => $latestHostingPolicy->id, + 'active_from' => $latestHostingPolicy->active_from, + ]); } } From 91dc8bd5d28826d367ce01874cda5dc8d647fc89 Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Tue, 14 Jul 2026 18:37:24 +0200 Subject: [PATCH 06/11] refactor test --- tests/Http/Controllers/PoliciesControllerTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php index fbfdbb8c..7e2b412f 100644 --- a/tests/Http/Controllers/PoliciesControllerTest.php +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -22,11 +22,11 @@ public function testGetCurrentPolicies(): void { 'active_from' => $currentTime->subMonth(), ]); // Active policies - $latestToUPolicy = Policy::factory()->create([ + $latestActiveToUPolicy = Policy::factory()->create([ 'policy_type' => 'terms-of-use', 'active_from' => $currentTime->subMonth(), ]); - $latestHostingPolicy = Policy::factory()->create([ + $latestActiveHostingPolicy = Policy::factory()->create([ 'policy_type' => 'hosting-policy', 'active_from' => $currentTime->subWeek(), ]); @@ -36,12 +36,12 @@ public function testGetCurrentPolicies(): void { $response->assertOk(); $response->assertJsonCount(2, 'data.items'); $response->assertJsonFragment([ - 'id' => $latestToUPolicy->id, - 'active_from' => $latestToUPolicy->active_from, + 'id' => $latestActiveToUPolicy->id, + 'active_from' => $latestActiveToUPolicy->active_from, ]); $response->assertJsonFragment([ - 'id' => $latestHostingPolicy->id, - 'active_from' => $latestHostingPolicy->active_from, + 'id' => $latestActiveHostingPolicy->id, + 'active_from' => $latestActiveHostingPolicy->active_from, ]); } } From 035956a870a50c3b3999af7a5223dac1d4afd07f Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Wed, 15 Jul 2026 11:47:18 +0200 Subject: [PATCH 07/11] fix nitpick --- database/factories/PolicyFactory.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/database/factories/PolicyFactory.php b/database/factories/PolicyFactory.php index b53aa93b..62f7aa49 100644 --- a/database/factories/PolicyFactory.php +++ b/database/factories/PolicyFactory.php @@ -4,10 +4,9 @@ use App\Policy; use Illuminate\Database\Eloquent\Factories\Factory; -use Illuminate\Database\Eloquent\Model; /** - * @extends Factory + * @extends Factory */ class PolicyFactory extends Factory { protected $model = Policy::class; From 5d6e358151dc63b01c50b27958554a691bdeecc5 Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Wed, 15 Jul 2026 12:02:54 +0200 Subject: [PATCH 08/11] add v1 to route --- routes/api.php | 2 +- tests/Http/Controllers/PoliciesControllerTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/api.php b/routes/api.php index e88422c6..e4e98fc2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -21,7 +21,7 @@ $router->post('user/resetPassword', ['uses' => 'Auth\ResetPasswordController@reset']); $router->post('contact/sendMessage', ['uses' => 'ContactController@sendMessage']); $router->post('complaint/sendMessage', ['uses' => 'ComplaintController@sendMessage']); - $router->get('policies/current', ['uses' => 'PoliciesController@getCurrentPolicies']); + $router->get('v1/policies/current', ['uses' => 'PoliciesController@getCurrentPolicies']); $router->post('auth/login', ['uses' => 'Auth\LoginController@postLogin'])->name('login'); // Authed diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php index 7e2b412f..c0d1cb96 100644 --- a/tests/Http/Controllers/PoliciesControllerTest.php +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -31,7 +31,7 @@ public function testGetCurrentPolicies(): void { 'active_from' => $currentTime->subWeek(), ]); - $response = $this->getJson('/policies/current'); + $response = $this->getJson('/v1/policies/current'); $response->assertOk(); $response->assertJsonCount(2, 'data.items'); From 07bbf50b942522da527d2a1557b40e085d57ade4 Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Wed, 15 Jul 2026 12:10:00 +0200 Subject: [PATCH 09/11] Remove key from the api response --- app/Http/Resources/PoliciesCollection.php | 10 +++++----- tests/Http/Controllers/PoliciesControllerTest.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/Http/Resources/PoliciesCollection.php b/app/Http/Resources/PoliciesCollection.php index d233312b..7b9795a8 100644 --- a/app/Http/Resources/PoliciesCollection.php +++ b/app/Http/Resources/PoliciesCollection.php @@ -4,16 +4,16 @@ use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\ResourceCollection; +use Illuminate\Support\Collection; class PoliciesCollection extends ResourceCollection { /** * Transform the resource collection into an array. * - * @return array + * @param Request $request + * @return Collection */ - public function toArray(Request $request): array { - return [ - 'items' => $this->collection, - ]; + public function toArray(Request $request): Collection { + return $this->collection; } } diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php index c0d1cb96..c04356a1 100644 --- a/tests/Http/Controllers/PoliciesControllerTest.php +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -34,7 +34,7 @@ public function testGetCurrentPolicies(): void { $response = $this->getJson('/v1/policies/current'); $response->assertOk(); - $response->assertJsonCount(2, 'data.items'); + $response->assertJsonCount(2, 'data'); $response->assertJsonFragment([ 'id' => $latestActiveToUPolicy->id, 'active_from' => $latestActiveToUPolicy->active_from, From bfbd3c3b2796d808c97b7331ccd459eb7b3106e5 Mon Sep 17 00:00:00 2001 From: Perside Rosalie Date: Wed, 15 Jul 2026 12:35:32 +0200 Subject: [PATCH 10/11] fix linting --- app/Http/Resources/PoliciesCollection.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/Http/Resources/PoliciesCollection.php b/app/Http/Resources/PoliciesCollection.php index 7b9795a8..c8754e98 100644 --- a/app/Http/Resources/PoliciesCollection.php +++ b/app/Http/Resources/PoliciesCollection.php @@ -9,9 +9,6 @@ class PoliciesCollection extends ResourceCollection { /** * Transform the resource collection into an array. - * - * @param Request $request - * @return Collection */ public function toArray(Request $request): Collection { return $this->collection; From 564103f08fa42320f77018748b6ea34123a53a7c Mon Sep 17 00:00:00 2001 From: Thomas Arrow Date: Wed, 15 Jul 2026 15:07:37 +0100 Subject: [PATCH 11/11] Attempt to match the Response to the ticket spec I attempted to do this by: - adapting the Collection to not be wrapped in a data object[0] - adding the items key to the structure of the ResourceCollection[1] - creating a Resource for the structure to represent each Policy as it looks on the wire[2] - mapping the existing Collection to use the new PolicyResource I was led in this direction by a blog[3] and stackoverflow[4] [0] https://api.laravel.com/docs/11.x/Illuminate/Http/Resources/Json/JsonResource.html#method_wrap [1] https://laravel.com/docs/11.x/eloquent-resources#resource-collections [2] https://laravel.com/docs/11.x/eloquent-resources#introduction [3] https://dev.to/programmerhasan/how-to-use-laravels-api-resource-collections-for-efficient-data-handling-143g [4] https://stackoverflow.com/a/67852854 --- app/Http/Resources/PoliciesCollection.php | 8 +++++-- app/Http/Resources/PolicyResource.php | 23 +++++++++++++++++++ .../Controllers/PoliciesControllerTest.php | 20 +++++++++++++--- 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 app/Http/Resources/PolicyResource.php diff --git a/app/Http/Resources/PoliciesCollection.php b/app/Http/Resources/PoliciesCollection.php index c8754e98..73db9369 100644 --- a/app/Http/Resources/PoliciesCollection.php +++ b/app/Http/Resources/PoliciesCollection.php @@ -7,10 +7,14 @@ use Illuminate\Support\Collection; class PoliciesCollection extends ResourceCollection { + public static $wrap = null; + /** * Transform the resource collection into an array. */ - public function toArray(Request $request): Collection { - return $this->collection; + public function toArray(Request $request): array { + return ['items' => $this->collection->map(function ($policy) { + return new PolicyResource($policy); + }), ]; } } diff --git a/app/Http/Resources/PolicyResource.php b/app/Http/Resources/PolicyResource.php new file mode 100644 index 00000000..240f7de8 --- /dev/null +++ b/app/Http/Resources/PolicyResource.php @@ -0,0 +1,23 @@ + + */ + public function toArray(Request $request): array { + return ['metadata' => [ + 'policy_id' => $this->id, + 'type' => $this->type, + 'active_from' => $this->active_from, + 'content_vue_file' => $this->content_vue_file, + ], + ]; + } +} diff --git a/tests/Http/Controllers/PoliciesControllerTest.php b/tests/Http/Controllers/PoliciesControllerTest.php index c04356a1..b88b0a6c 100644 --- a/tests/Http/Controllers/PoliciesControllerTest.php +++ b/tests/Http/Controllers/PoliciesControllerTest.php @@ -34,13 +34,27 @@ public function testGetCurrentPolicies(): void { $response = $this->getJson('/v1/policies/current'); $response->assertOk(); - $response->assertJsonCount(2, 'data'); + + $response->assertJsonStructure([ + 'items' => [ + '*' => [ + 'metadata' => [ + 'policy_id', + 'active_from', + 'content_vue_file', + 'type', + ], + + ], + ], + ]); + $response->assertJsonFragment([ - 'id' => $latestActiveToUPolicy->id, + 'policy_id' => $latestActiveToUPolicy->id, 'active_from' => $latestActiveToUPolicy->active_from, ]); $response->assertJsonFragment([ - 'id' => $latestActiveHostingPolicy->id, + 'policy_id' => $latestActiveHostingPolicy->id, 'active_from' => $latestActiveHostingPolicy->active_from, ]); }