create([ 'name' => 'Owner Alice', 'email' => 'alice-owner-' . uniqid() . '@example.com', 'password' => bcrypt('password'), ]); $participant = User::factory()->create([ 'name' => 'Submissive Bob', 'email' => 'bob-participant-' . uniqid() . '@example.com', 'password' => bcrypt('password'), ]); $dynamic = Dynamic::create([ 'name' => 'The Velvet Realtime Test Sanctuary', 'rules' => 'Rules for realtime testing.', ]); $dynamic->participants()->attach($owner->id, ['role' => 'owner']); $dynamic->participants()->attach($participant->id, ['role' => 'participant']); // 2. Spawn two separate browser sessions/browsers in parallel $this->browse(function (Browser $sessionA, Browser $sessionB) use ($dynamic, $owner, $participant) { try { // --- SESSION A: Owner --- $sessionA->loginAs($owner) ->visit('/dynamics/' . $dynamic->uuid) ->waitForText('The Velvet Realtime Test Sanctuary') ->assertSee('Owner Alice'); // --- SESSION B: Participant --- $sessionB->loginAs($participant) ->visit('/dynamics/' . $dynamic->uuid) ->waitForText('The Velvet Realtime Test Sanctuary') ->assertSee('Submissive Bob'); // --- REAL-TIME COMMUNICATING --- // Owner types and sends a message in chat $sessionA->type('#content', 'Hello Submissive Bob, did you complete your daily chores?') ->click('.c-chat__button') ->waitForText('Hello Submissive Bob, did you complete your daily chores?'); // Since websockets broadcast in real-time, Session B receives it without reloading $sessionB->waitForText('Hello Submissive Bob, did you complete your daily chores?', 10) ->assertSee('Hello Submissive Bob, did you complete your daily chores?'); // Participant replies in real-time $sessionB->type('#content', 'Yes Master, everything is complete and logged!') ->click('.c-chat__button') ->waitForText('Yes Master, everything is complete and logged!'); // Session A receives the reply in real-time without reloading $sessionA->waitForText('Yes Master, everything is complete and logged!', 10) ->assertSee('Yes Master, everything is complete and logged!'); } catch (\Exception $e) { echo "\n=== SESSION A CONSOLE LOGS ===\n"; print_r($sessionA->driver->manage()->getLog('browser')); echo "\n=== SESSION B CONSOLE LOGS ===\n"; print_r($sessionB->driver->manage()->getLog('browser')); throw $e; } }); // Clean up $dynamic->participants()->detach(); $dynamic->delete(); $owner->delete(); $participant->delete(); } }