create(); $role = Role::create(['name' => 'ROLE_ADMIN']); $admin->roles()->attach($role); return $admin; } it('index returns forbidden for non admin', function (): void { $controller = new AttachmentExtensionController(); $request = Request::create('/api/attachment-extensions', 'GET'); $request->setUserResolver(fn () => null); $response = $controller->index($request); expect($response->getStatusCode())->toBe(403); }); it('store update destroy return forbidden for non admin', function (): void { $controller = new AttachmentExtensionController(); $user = User::factory()->create(); $store = Request::create('/api/attachment-extensions', 'POST', [ 'extension' => 'png', ]); $store->setUserResolver(fn () => $user); $response = $controller->store($store); expect($response->getStatusCode())->toBe(403); $extension = AttachmentExtension::create(['extension' => 'gif']); $update = Request::create('/api/attachment-extensions/'.$extension->id, 'PATCH', [ 'allowed_mimes' => ['image/gif'], ]); $update->setUserResolver(fn () => $user); $response = $controller->update($update, $extension); expect($response->getStatusCode())->toBe(403); $destroy = Request::create('/api/attachment-extensions/'.$extension->id, 'DELETE'); $destroy->setUserResolver(fn () => $user); $response = $controller->destroy($destroy, $extension); expect($response->getStatusCode())->toBe(403); }); it('store rejects invalid or duplicate extension', function (): void { $controller = new AttachmentExtensionController(); $admin = makeAdminUserForExtensions(); $request = Request::create('/api/attachment-extensions', 'POST', [ 'extension' => '.', ]); $request->setUserResolver(fn () => $admin); $response = $controller->store($request); expect($response->getStatusCode())->toBe(422); AttachmentExtension::create(['extension' => 'png']); $request = Request::create('/api/attachment-extensions', 'POST', [ 'extension' => 'PNG', ]); $request->setUserResolver(fn () => $admin); $response = $controller->store($request); expect($response->getStatusCode())->toBe(422); }); it('store and update serialize group info', function (): void { $controller = new AttachmentExtensionController(); $admin = makeAdminUserForExtensions(); $group = AttachmentGroup::create([ 'name' => 'Images', 'max_size_kb' => 100, 'is_active' => true, ]); $request = Request::create('/api/attachment-extensions', 'POST', [ 'extension' => 'png', 'attachment_group_id' => $group->id, 'allowed_mimes' => ['image/png'], ]); $request->setUserResolver(fn () => $admin); $response = $controller->store($request); expect($response->getStatusCode())->toBe(201); $extension = AttachmentExtension::query()->where('extension', 'png')->firstOrFail(); $request = Request::create('/api/attachment-extensions/'.$extension->id, 'PATCH', [ 'allowed_mimes' => ['image/png', 'image/webp'], ]); $request->setUserResolver(fn () => $admin); $response = $controller->update($request, $extension); expect($response->getStatusCode())->toBe(200); $payload = $response->getData(true); expect($payload['group']['name'])->toBe('Images'); }); it('destroy returns error when extension in use then succeeds', function (): void { $controller = new AttachmentExtensionController(); $admin = makeAdminUserForExtensions(); $extension = AttachmentExtension::create(['extension' => 'pdf']); Attachment::create([ 'thread_id' => null, 'post_id' => null, 'attachment_extension_id' => $extension->id, 'attachment_group_id' => null, 'user_id' => null, 'disk' => 'local', 'path' => 'attachments/test.pdf', 'original_name' => 'test.pdf', 'extension' => 'pdf', 'mime_type' => 'application/pdf', 'size_bytes' => 10, ]); $request = Request::create('/api/attachment-extensions/'.$extension->id, 'DELETE'); $request->setUserResolver(fn () => $admin); $response = $controller->destroy($request, $extension); expect($response->getStatusCode())->toBe(422); Attachment::query()->delete(); $response = $controller->destroy($request, $extension); expect($response->getStatusCode())->toBe(204); }); it('public index only returns active grouped extensions', function (): void { $controller = new AttachmentExtensionController(); $activeGroup = AttachmentGroup::create([ 'name' => 'Active', 'max_size_kb' => 100, 'is_active' => true, ]); $inactiveGroup = AttachmentGroup::create([ 'name' => 'Inactive', 'max_size_kb' => 100, 'is_active' => false, ]); AttachmentExtension::create([ 'extension' => 'png', 'attachment_group_id' => $activeGroup->id, ]); AttachmentExtension::create([ 'extension' => 'zip', 'attachment_group_id' => $inactiveGroup->id, ]); AttachmentExtension::create([ 'extension' => 'orphan', 'attachment_group_id' => null, ]); $response = $controller->publicIndex(); $payload = $response->getData(true); expect($payload)->toBe(['png']); });