seed(RolePermissionSeeder::class); } #[Test] public function every_collective_resource_renders(): void { Project::factory()->count(2)->create(); Member::factory()->count(2)->create(); Technology::factory()->count(2)->create(); Call::factory()->create(['project_id' => null]); Repository::factory()->create(); $this->actingAs($this->userWithRoles('admin')); foreach ([ ProjectResource::class, MemberResource::class, TechnologyResource::class, CallResource::class, RepositoryResource::class, ] as $resource) { $this->get($resource::getUrl('index')) ->assertSuccessful(); } } #[Test] public function an_editor_can_manage_content_but_not_sync_repositories(): void { $editor = $this->userWithRoles('editor'); $this->actingAs($editor); $this->assertTrue($editor->can('projects.create')); $this->assertTrue($editor->can('calls.create')); $this->assertTrue($editor->can('members.update')); // Syncing spends a shared rate limit, so it is gated separately from // ordinary editing. $this->assertTrue($editor->can('repositories.view_any')); $this->assertFalse($editor->can('repositories.sync')); $this->assertFalse($editor->can('repositories.create')); } #[Test] public function a_viewer_cannot_reach_the_collective_editors(): void { $viewer = $this->userWithRoles('viewer'); $this->actingAs($viewer); $this->assertTrue(ProjectResource::canViewAny()); $this->assertFalse(ProjectResource::canCreate()); $this->assertFalse(MemberResource::canCreate()); $this->assertFalse(TechnologyResource::canCreate()); } #[Test] public function publishing_a_project_is_a_separate_permission_from_editing_it(): void { $editor = $this->userWithRoles('editor'); $editor->roles()->first()->revokePermissionTo('projects.publish'); $editor->forgetCachedPermissions(); $project = Project::factory()->draft()->create(); $this->assertTrue($editor->can('update', $project)); $this->assertFalse($editor->can('publish', $project)); } #[Test] public function a_member_may_always_edit_their_own_profile(): void { // Someone with no member-editing permission at all. $user = $this->userWithRoles('viewer'); $own = Member::factory()->create(['user_id' => $user->id]); $other = Member::factory()->create(); $this->assertTrue($user->can('update', $own)); $this->assertFalse($user->can('update', $other)); } #[Test] public function a_technology_still_in_use_cannot_be_deleted(): void { $admin = $this->userWithRoles('admin'); $used = Technology::factory()->create(); $unused = Technology::factory()->create(); Project::factory()->create()->technologies()->attach($used); // Deleting it would silently strip the tag across the whole site. $this->assertFalse($admin->can('delete', $used)); $this->assertTrue($admin->can('delete', $unused)); } #[Test] public function a_member_is_not_a_panel_user(): void { $member = Member::factory()->create(); // The two are deliberately separate: most members never need admin // access, and revoking admin must not remove someone from the website. $this->assertNull($member->user_id); $this->assertDatabaseCount('users', 0); $this->assertTrue($member->is_public); } #[Test] public function removing_a_panel_user_leaves_the_member_on_the_site(): void { $user = User::factory()->create(); $member = Member::factory()->create(['user_id' => $user->id]); $user->delete(); $member->refresh(); $this->assertTrue($member->exists); $this->assertNull($member->user_id); $this->assertTrue($member->is_public); } }