登录
ZH
games/webrtc-demo / tests / WebRtcTest.php · commit 87ad512
<?phpnamespace Tests;use App\Scene\LinkScene;use JumPHP\Testing\GameTestCase;use JumPHP\WebRtc\Backend;use JumPHP\WebRtc\DataChannel;use JumPHP\WebRtc\WebRtc;/** Peer and DataChannel against a fake backend (what the sidecar / the page would answer): commands out, events in. */final class WebRtcTest extends GameTestCase{    private FakeBackend $fake;    private WebRtc $webrtc;    protected function setUp(): void    {        parent::setUp();        $this->game->start(LinkScene::class);        $this->webrtc = $this->game->peek('webrtc');      // the scene's WebRtc service        $this->webrtc->setBackend($this->fake = new FakeBackend());    }    public function testAnOfferBecomesASignalForTheOtherSide(): void    {        $peer = $this->webrtc->peer(['stun' => 'stun:example.org:3478']);        $signals = [];        $peer->on('signal', function (array $s) use (&$signals): void {            $signals[] = $s;        });        $peer->channel('chat');        $peer->offer();        self::assertSame(['peer', 'channel', 'offer'], array_column($this->fake->sent, 'op'));        self::assertSame('stun:example.org:3478', $this->fake->sent[0]['stun']);        $this->fake->emit(['ev' => 'offer', 'id' => $peer->id, 'sdp' => 'v=0']);        $this->fake->emit(['ev' => 'ice', 'id' => $peer->id, 'candidate' => 'candidate:1 1 UDP 1 10.0.0.2 5000 typ host', 'mline' => 0]);        self::assertSame([['type' => 'offer', 'sdp' => 'v=0'], ['candidate' => 'candidate:1 1 UDP 1 10.0.0.2 5000 typ host', 'mline' => 0]], $signals);    }    public function testTheOtherSidesSignalsGoToTheBackend(): void    {        $peer = $this->webrtc->peer();        $peer->signal(['type' => 'answer', 'sdp' => 'v=0']);        $peer->signal(['candidate' => 'candidate:2', 'mline' => 1]);        $peer->signal(['nonsense' => true]);        $last = array_slice($this->fake->sent, -2);        self::assertSame(['id' => $peer->id, 'op' => 'remote', 'type' => 'answer', 'sdp' => 'v=0'], $last[0]);        self::assertSame('ice', $last[1]['op']);        self::assertSame(1, $last[1]['mline']);    }    public function testAChannelOpenedByTheOtherSideArrivesWithItsMessages(): void    {        $peer = $this->webrtc->peer();        $got = [];        $peer->on('channel', function (DataChannel $ch) use (&$got): void {            $ch->on('message', function (string $data, bool $binary) use (&$got, $ch): void {                $got[] = [$ch->label, $data, $binary];            });        });        $this->fake->emit(['ev' => 'open', 'id' => $peer->id, 'label' => 'files']);        $this->fake->emit(['ev' => 'message', 'id' => $peer->id, 'label' => 'files', 'text' => 'hello']);        $this->fake->emit(['ev' => 'message', 'id' => $peer->id, 'label' => 'files', 'b64' => base64_encode("\x00\x01")]);        self::assertSame([['files', 'hello', false], ['files', "\x00\x01", true]], $got);        $peer->channel('files')->sendBinary("\xff");        self::assertSame(['id' => $peer->id, 'op' => 'send', 'label' => 'files', 'b64' => '/w=='], end($this->fake->sent));    }    public function testStatesAndErrorsReachThePeer(): void    {        $peer = $this->webrtc->peer();        $errors = [];        $peer->on('error', function (string $e) use (&$errors): void {            $errors[] = $e;        });        $this->fake->emit(['ev' => 'state', 'id' => $peer->id, 'state' => 'connected']);        self::assertTrue($peer->isConnected());        $this->fake->emit(['ev' => 'exit', 'message' => 'the WebRTC sidecar stopped']);        self::assertSame(['the WebRTC sidecar stopped'], $errors);    }}final class FakeBackend implements Backend{    /** @var list<array<string, mixed>> */    public array $sent = [];    /** @var list<callable> */    private array $listeners = [];    public function name(): string    {        return 'fake';    }    public function isSupported(): bool    {        return true;    }    public function send(array $command): void    {        $this->sent[] = $command;    }    public function listen(callable $listener): void    {        $this->listeners[] = $listener;    }    public function poll(): void    {    }    public function emit(array $event): void    {        foreach ($this->listeners as $fn) {            $fn($event);        }    }}