create([ 'name' => 'Owner Alice', 'email' => 'alice-owner@example.com', 'password' => bcrypt('password'), ]); $participant = User::factory()->create([ 'name' => 'Participant Bob', 'email' => 'bob-sub@example.com', 'password' => bcrypt('password'), ]); $outsider = User::factory()->create([ 'name' => 'Outsider Charlie', 'email' => 'charlie-outsider@example.com', 'password' => bcrypt('password'), ]); $dynamic = Dynamic::create([ 'name' => 'Private Club', 'rules' => 'Strict access control.', ]); $dynamic->participants()->attach($owner->id, ['role' => 'owner']); $dynamic->participants()->attach($participant->id, ['role' => 'participant']); $ledger = Ledger::create([ 'dynamic_id' => $dynamic->id, 'name' => 'Rules Compliance', 'rules' => 'Score rules.', 'score' => 100, 'alignment' => 'neutral', ]); $this->browse(function (Browser $sessionOwner, Browser $sessionParticipant, Browser $sessionOutsider) use ($dynamic, $ledger, $owner, $participant, $outsider) { // 1. Test Outsider trying to access dynamic they DO NOT belong to (should be forbidden / 403) $sessionOutsider->loginAs($outsider) ->visit(route('dynamics.show', $dynamic)) ->assertSee('403') // Laravel / Inertia forbidden page ->assertDontSee('Private Club'); // 2. Test Participant accessing dynamic they DO belong to (should be allowed) $sessionParticipant->loginAs($participant) ->visit(route('dynamics.show', $dynamic)) ->waitForText('Private Club') ->assertSee('Private Club') ->assertSee('Participant Bob'); // 3. Test Participant adding a mutation suggestion $sessionParticipant->visit(route('dynamics.ledgers.show', [$dynamic, $ledger])) ->waitForText('Add Mutation') ->type('amount', '20') ->type('description', 'Cleaned the main room') ->press('Add Mutation') ->waitForText('PENDING') ->assertSee('PENDING') // Mutation should show up as pending ->assertDontSee('Approve'); // Standard participant should NOT see approve button! // 4. Test Owner logging in, seeing the pending suggestion, and approving it! $sessionOwner->loginAs($owner) ->visit(route('dynamics.ledgers.show', [$dynamic, $ledger])) ->waitForText('Cleaned the main room') ->assertSee('PENDING') ->assertSee('Approve') // Owner should see the Approve button! ->press('Approve') ->waitForText('Score: 120') // Score updated from 100 to 120 after approval! ->assertDontSee('PENDING'); // No longer pending! }); });