Commit workspace changes
This commit is contained in:
168
tests/Feature/Groups/GroupPolicyTest.php
Normal file
168
tests/Feature/Groups/GroupPolicyTest.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Group;
|
||||
use App\Models\GroupMember;
|
||||
use App\Models\User;
|
||||
use App\Policies\GroupPolicy;
|
||||
use App\Services\GroupMembershipService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
function attachGroupMember(Group $group, User $user, string $role): GroupMember
|
||||
{
|
||||
return GroupMember::query()->create([
|
||||
'group_id' => $group->id,
|
||||
'user_id' => $user->id,
|
||||
'invited_by_user_id' => $group->owner_user_id,
|
||||
'role' => $role,
|
||||
'status' => Group::STATUS_ACTIVE,
|
||||
'invited_at' => now(),
|
||||
'accepted_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
it('allows contributors into studio but not management or publishing policy actions', function () {
|
||||
$owner = User::factory()->create();
|
||||
$contributor = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create();
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
attachGroupMember($group, $contributor, Group::ROLE_MEMBER);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->viewStudio($contributor, $group))->toBeTrue()
|
||||
->and($policy->update($contributor, $group))->toBeFalse()
|
||||
->and($policy->manageMembers($contributor, $group))->toBeFalse()
|
||||
->and($policy->publishArtworks($contributor, $group))->toBeFalse()
|
||||
->and($policy->manageCollections($contributor, $group))->toBeFalse();
|
||||
});
|
||||
|
||||
it('allows editors to publish artworks and manage collections without member administration', function () {
|
||||
$owner = User::factory()->create();
|
||||
$editor = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create();
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
attachGroupMember($group, $editor, Group::ROLE_EDITOR);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->viewStudio($editor, $group))->toBeTrue()
|
||||
->and($policy->publishArtworks($editor, $group))->toBeTrue()
|
||||
->and($policy->manageCollections($editor, $group))->toBeTrue()
|
||||
->and($policy->manageMembers($editor, $group))->toBeFalse()
|
||||
->and($policy->archive($editor, $group))->toBeFalse();
|
||||
});
|
||||
|
||||
it('allows admins to manage group settings and members but not archive ownership actions', function () {
|
||||
$owner = User::factory()->create();
|
||||
$admin = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create();
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
attachGroupMember($group, $admin, Group::ROLE_ADMIN);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->viewStudio($admin, $group))->toBeTrue()
|
||||
->and($policy->update($admin, $group))->toBeTrue()
|
||||
->and($policy->manageMembers($admin, $group))->toBeTrue()
|
||||
->and($policy->publishArtworks($admin, $group))->toBeTrue()
|
||||
->and($policy->archive($admin, $group))->toBeFalse();
|
||||
});
|
||||
|
||||
it('blocks studio access for suspended groups even for active non-owner members', function () {
|
||||
$owner = User::factory()->create();
|
||||
$editor = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create([
|
||||
'status' => Group::LIFECYCLE_SUSPENDED,
|
||||
]);
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
attachGroupMember($group, $editor, Group::ROLE_EDITOR);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->viewStudio($editor, $group))->toBeFalse()
|
||||
->and($policy->publishArtworks($editor, $group))->toBeFalse()
|
||||
->and($policy->manageCollections($editor, $group))->toBeFalse();
|
||||
});
|
||||
|
||||
it('keeps archive authority with the owner', function () {
|
||||
$owner = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create();
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->update($owner, $group))->toBeTrue()
|
||||
->and($policy->manageMembers($owner, $group))->toBeTrue()
|
||||
->and($policy->publishArtworks($owner, $group))->toBeTrue()
|
||||
->and($policy->archive($owner, $group))->toBeTrue();
|
||||
});
|
||||
|
||||
it('does not allow admins or editors to transfer ownership through policy update access alone', function () {
|
||||
$owner = User::factory()->create();
|
||||
$admin = User::factory()->create();
|
||||
$editor = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create();
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
attachGroupMember($group, $admin, Group::ROLE_ADMIN);
|
||||
attachGroupMember($group, $editor, Group::ROLE_EDITOR);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->update($admin, $group))->toBeTrue()
|
||||
->and($policy->archive($admin, $group))->toBeFalse()
|
||||
->and($policy->manageMembers($editor, $group))->toBeFalse();
|
||||
});
|
||||
|
||||
it('exposes explicit v3 event and private access policy hooks', function () {
|
||||
$owner = User::factory()->create();
|
||||
$editor = User::factory()->create();
|
||||
$member = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create();
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
attachGroupMember($group, $editor, Group::ROLE_EDITOR);
|
||||
attachGroupMember($group, $member, Group::ROLE_MEMBER);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->publishEventUpdates($editor, $group))->toBeTrue()
|
||||
->and($policy->viewInternalEvents($editor, $group))->toBeTrue()
|
||||
->and($policy->viewPrivateProject($editor, $group))->toBeTrue()
|
||||
->and($policy->participateInChallenge($member, $group))->toBeTrue()
|
||||
->and($policy->publishEventUpdates($member, $group))->toBeFalse();
|
||||
});
|
||||
|
||||
it('exposes explicit v4 release, milestone, badge, and trust policy hooks', function () {
|
||||
$owner = User::factory()->create();
|
||||
$admin = User::factory()->create();
|
||||
$editor = User::factory()->create();
|
||||
$member = User::factory()->create();
|
||||
$group = Group::factory()->for($owner, 'owner')->create();
|
||||
|
||||
app(GroupMembershipService::class)->ensureOwnerMembership($group);
|
||||
attachGroupMember($group, $admin, Group::ROLE_ADMIN);
|
||||
attachGroupMember($group, $editor, Group::ROLE_EDITOR);
|
||||
attachGroupMember($group, $member, Group::ROLE_MEMBER);
|
||||
|
||||
$policy = app(GroupPolicy::class);
|
||||
|
||||
expect($policy->manageReleases($editor, $group))->toBeTrue()
|
||||
->and($policy->publishReleases($editor, $group))->toBeTrue()
|
||||
->and($policy->moveReleaseStage($editor, $group))->toBeTrue()
|
||||
->and($policy->manageMilestones($editor, $group))->toBeTrue()
|
||||
->and($policy->assignReleaseLead($editor, $group))->toBeTrue()
|
||||
->and($policy->viewReputationDashboard($editor, $group))->toBeFalse()
|
||||
->and($policy->manageBadges($admin, $group))->toBeTrue()
|
||||
->and($policy->viewInternalTrustMetrics($admin, $group))->toBeTrue()
|
||||
->and($policy->featureRelease($admin, $group))->toBeTrue()
|
||||
->and($policy->manageReleases($member, $group))->toBeFalse()
|
||||
->and($policy->viewReputationDashboard($member, $group))->toBeFalse();
|
||||
});
|
||||
19
tests/Feature/Groups/GroupsFaqPageTest.php
Normal file
19
tests/Feature/Groups/GroupsFaqPageTest.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use Inertia\Testing\AssertableInertia;
|
||||
|
||||
it('renders the groups faq page with related help links', function () {
|
||||
$this->get(route('help.groups.faq'))
|
||||
->assertOk()
|
||||
->assertInertia(fn (AssertableInertia $page) => $page
|
||||
->component('Group/GroupFaqPage')
|
||||
->where('title', 'Groups FAQ')
|
||||
->where('seo.canonical', route('help.groups.faq'))
|
||||
->where('links.full_documentation', route('help.groups'))
|
||||
->where('links.quickstart', route('help.groups.quickstart'))
|
||||
->where('links.group_studio', route('studio.groups.index'))
|
||||
->where('links.create_group', route('studio.groups.create'))
|
||||
->where('links.contact_support', route('contact.show'))
|
||||
->where('links.report_issue', route('bug-report'))
|
||||
);
|
||||
});
|
||||
2088
tests/Feature/Groups/GroupsFeatureTest.php
Normal file
2088
tests/Feature/Groups/GroupsFeatureTest.php
Normal file
File diff suppressed because it is too large
Load Diff
18
tests/Feature/Groups/GroupsHelpPageTest.php
Normal file
18
tests/Feature/Groups/GroupsHelpPageTest.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
use Inertia\Testing\AssertableInertia;
|
||||
|
||||
it('renders the groups help page with real internal links', function () {
|
||||
$this->get(route('help.groups'))
|
||||
->assertOk()
|
||||
->assertInertia(fn (AssertableInertia $page) => $page
|
||||
->component('Group/GroupHelpPage')
|
||||
->where('title', 'Groups Help & Guide')
|
||||
->where('seo.canonical', route('help.groups'))
|
||||
->where('links.groups_directory', route('groups.index'))
|
||||
->where('links.create_group', route('studio.groups.create'))
|
||||
->where('links.group_studio', route('studio.groups.index'))
|
||||
->where('links.contact_support', route('contact.show'))
|
||||
->where('links.report_issue', route('bug-report'))
|
||||
);
|
||||
});
|
||||
17
tests/Feature/Groups/GroupsQuickstartPageTest.php
Normal file
17
tests/Feature/Groups/GroupsQuickstartPageTest.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use Inertia\Testing\AssertableInertia;
|
||||
|
||||
it('renders the groups quickstart page with onboarding links', function () {
|
||||
$this->get(route('help.groups.quickstart'))
|
||||
->assertOk()
|
||||
->assertInertia(fn (AssertableInertia $page) => $page
|
||||
->component('Group/GroupQuickstartPage')
|
||||
->where('title', 'Groups Quickstart')
|
||||
->where('seo.canonical', route('help.groups.quickstart'))
|
||||
->where('links.create_group', route('studio.groups.create'))
|
||||
->where('links.group_studio', route('studio.groups.index'))
|
||||
->where('links.groups_directory', route('groups.index'))
|
||||
->where('links.full_documentation', route('help.groups'))
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user