From a4c2b4e95ab9c361ccdc6f9caa50418b9b435ea7 Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Thu, 7 May 2026 10:44:15 +0200 Subject: [PATCH] Add `BrandingApiTest` to validate branding CRUD operations, permissions, and department assignments. --- .../nginx/app/tests/Api/BrandingApiTest.php | 233 ++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 services/nginx/app/tests/Api/BrandingApiTest.php diff --git a/services/nginx/app/tests/Api/BrandingApiTest.php b/services/nginx/app/tests/Api/BrandingApiTest.php new file mode 100644 index 00000000..5a097f91 --- /dev/null +++ b/services/nginx/app/tests/Api/BrandingApiTest.php @@ -0,0 +1,233 @@ +createUserSession([ + 'list_branding_options', + 'add_branding_option', + 'edit_branding_option', + ]); + + $createPayload = [ + 'name' => 'API Brand ' . uniqid('', false), + 'description' => 'Created through the branding API', + 'cvr' => 41004355, + 'address' => 'Skagerrakvej 15, 6715 Esbjerg', + 'phone_country_code' => 45, + 'phone' => 76123456, + 'email' => 'brand@example.test', + 'website' => 'https://brand.example.test', + 'banner' => 'https://cdn.example.test/banner.png', + 'logo' => 'https://cdn.example.test/logo.png', + 'favicon' => 'https://cdn.example.test/favicon.ico', + 'signature' => 'https://cdn.example.test/signature.png', + ]; + + $createResponse = api_client()->post('/branding', $createPayload, $session['headers']); + + $createResponse + ->assertStatus(200) + ->assertEnvelope() + ->assertSuccess(); + + $createdId = (int)($createResponse->data()['id'] ?? 0); + expect($createdId)->toBeGreaterThan(0); + api_fixtures()->cleanupDeleteById('branding', $createdId); + + $singleResponse = api_client()->get('/branding?id=' . $createdId, $session['headers']); + + $singleResponse + ->assertStatus(200) + ->assertEnvelope() + ->assertSuccess(); + + expect($singleResponse->data()) + ->toBeArray() + ->toHaveKey('id', $createdId) + ->toHaveKey('name', $createPayload['name']) + ->toHaveKey('logo', $createPayload['logo']); + + $listResponse = api_client()->get('/branding', $session['headers']); + + $listResponse + ->assertStatus(200) + ->assertEnvelope() + ->assertSuccess(); + + $listedIds = array_map( + static fn(array $branding): int => (int)($branding['id'] ?? 0), + is_array($listResponse->data()) ? $listResponse->data() : [] + ); + expect($listedIds)->toContain($createdId); + + $updatePayload = [ + 'id' => $createdId, + 'name' => 'Updated Brand', + 'description' => 'Updated description', + 'cvr' => 43423010, + 'address' => 'Updatedvej 1, 1000 Kobenhavn', + 'phone_country_code' => 46, + 'phone' => 87654321, + 'email' => 'updated@example.test', + 'website' => 'https://updated.example.test', + 'banner' => 'https://cdn.example.test/updated-banner.png', + 'logo' => 'https://cdn.example.test/updated-logo.png', + 'favicon' => 'https://cdn.example.test/updated-favicon.ico', + 'signature' => '', + ]; + + $updateResponse = api_client()->put('/branding', $updatePayload, $session['headers']); + + $updateResponse + ->assertStatus(200) + ->assertEnvelope() + ->assertSuccess(); + + $updatedRow = api_fixtures()->fetchRowById('branding', $createdId); + expect($updatedRow)->not->toBeNull(); + expect($updatedRow['name'] ?? null)->toBe('Updated Brand'); + expect((int)($updatedRow['cvr'] ?? 0))->toBe(43423010); + expect($updatedRow['logo'] ?? null)->toBe('https://cdn.example.test/updated-logo.png'); + expect(array_key_exists('signature', $updatedRow))->toBeTrue(); + expect($updatedRow['signature'])->toBeNull(); +}); + +it('rejects branding requests without permissions or valid input', function (): void { + api_test_covers('GET /branding', 'auth'); + api_test_covers('POST /branding', 'failure'); + api_test_covers('PUT /branding', 'failure'); + + $unauthorizedSession = api_fixtures()->createUserSession([]); + + api_client()->get('/branding', $unauthorizedSession['headers']) + ->assertStatus(403) + ->assertEnvelope() + ->assertSuccess(false) + ->assertMissingPermissions(['list_branding_options']); + + $createSession = api_fixtures()->createUserSession(['add_branding_option']); + + api_client()->post('/branding', [ + 'name' => 'Invalid Brand', + 'description' => 'Missing CVR', + ], $createSession['headers']) + ->assertStatus(400) + ->assertEnvelope() + ->assertSuccess(false) + ->assertMessage('Missing required parameters: cvr'); + + api_client()->post('/branding', [ + 'name' => 'Invalid Brand', + 'description' => 'Bad CVR', + 'cvr' => 'not-a-number', + ], $createSession['headers']) + ->assertStatus(400) + ->assertEnvelope() + ->assertSuccess(false) + ->assertMessage('cvr must be an integer'); + + $editSession = api_fixtures()->createUserSession(['edit_branding_option']); + + api_client()->put('/branding', [ + 'id' => 99999999, + 'name' => 'Missing Brand', + ], $editSession['headers']) + ->assertStatus(400) + ->assertEnvelope() + ->assertSuccess(false) + ->assertMessage('Invalid id'); +}); + +it('assigns and clears department branding for superusers', function (): void { + api_test_covers('PUT /superuser/department/branding', 'happy'); + + $branding = api_fixtures()->createBranding([ + 'name' => 'Assignable Brand', + 'description' => 'Brand for assignment', + ]); + $department = api_fixtures()->createDepartment([ + 'name' => 'Branding Department', + ]); + $session = api_fixtures()->createUserSession([ + 'superuser_set_department_branding', + 'superuser_fetch_department', + ]); + + $assignResponse = api_client()->put('/superuser/department/branding', [ + 'department_id' => $department['id'], + 'branding_id' => $branding['id'], + ], $session['headers']); + + $assignResponse + ->assertStatus(200) + ->assertEnvelope() + ->assertSuccess(); + + $assignedRow = api_fixtures()->fetchRowById('departments', (int)$department['id']); + expect((int)($assignedRow['branding'] ?? 0))->toBe((int)$branding['id']); + + $departmentResponse = api_client()->get('/superuser/department?department_id=' . $department['id'], $session['headers']); + + $departmentResponse + ->assertStatus(200) + ->assertEnvelope() + ->assertSuccess(); + expect((int)($departmentResponse->data()['branding'] ?? 0))->toBe((int)$branding['id']); + + $clearResponse = api_client()->put('/superuser/department/branding', [ + 'department_id' => $department['id'], + 'branding_id' => null, + ], $session['headers']); + + $clearResponse + ->assertStatus(200) + ->assertEnvelope() + ->assertSuccess(); + + $clearedRow = api_fixtures()->fetchRowById('departments', (int)$department['id']); + expect(array_key_exists('branding', $clearedRow))->toBeTrue(); + expect($clearedRow['branding'])->toBeNull(); +}); + +it('rejects invalid department branding assignments', function (): void { + api_test_covers('PUT /superuser/department/branding', 'failure'); + + $department = api_fixtures()->createDepartment(); + $unauthorizedSession = api_fixtures()->createUserSession([]); + + api_client()->put('/superuser/department/branding', [ + 'department_id' => $department['id'], + 'branding_id' => null, + ], $unauthorizedSession['headers']) + ->assertStatus(403) + ->assertEnvelope() + ->assertSuccess(false) + ->assertMissingPermissions(['superuser_set_department_branding']); + + $session = api_fixtures()->createUserSession(['superuser_set_department_branding']); + + api_client()->put('/superuser/department/branding', [ + 'department_id' => $department['id'], + 'branding_id' => 99999999, + ], $session['headers']) + ->assertStatus(404) + ->assertEnvelope() + ->assertSuccess(false) + ->assertMessage('Branding not found'); + + api_client()->put('/superuser/department/branding', [ + 'department_id' => 99999999, + 'branding_id' => null, + ], $session['headers']) + ->assertStatus(404) + ->assertEnvelope() + ->assertSuccess(false) + ->assertMessage('Department not found'); +});