<?php declare(strict_types=1);


use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

final class ProxyObjectTest extends TestCase
{
    public function testProxyingWorksForMethodThatReturnsUndeclaredScalarValue(): void
    {
        $proxy = $this->createTestProxy(TestProxyFixture::class);

        $proxy->expects($this->once())
              ->method('returnString');

        \assert($proxy instanceof MockObject);
        \assert($proxy instanceof TestProxyFixture);

        $this->assertSame('result', $proxy->returnString());
    }

    public function testProxyingWorksForMethodThatReturnsDeclaredScalarValue(): void
    {
        $proxy = $this->createTestProxy(TestProxyFixture::class);

        $proxy->expects($this->once())
              ->method('returnTypedString');

        \assert($proxy instanceof MockObject);
        \assert($proxy instanceof TestProxyFixture);

        $this->assertSame('result', $proxy->returnTypedString());
    }

    public function testProxyingWorksForMethodThatReturnsUndeclaredObject(): void
    {
        $proxy = $this->createTestProxy(TestProxyFixture::class);

        $proxy->expects($this->once())
              ->method('returnObject');

        \assert($proxy instanceof MockObject);
        \assert($proxy instanceof TestProxyFixture);

        $this->assertSame('bar', $proxy->returnObject()->foo);
    }

    public function testProxyingWorksForMethodThatReturnsDeclaredObject(): void
    {
        $proxy = $this->createTestProxy(TestProxyFixture::class);

        $proxy->expects($this->once())
              ->method('returnTypedObject');

        \assert($proxy instanceof MockObject);
        \assert($proxy instanceof TestProxyFixture);

        $this->assertSame('bar', $proxy->returnTypedObject()->foo);
    }

    public function testProxyingWorksForMethodThatReturnsUndeclaredObjectOfFinalClass(): void
    {
        $proxy = $this->createTestProxy(TestProxyFixture::class);

        $proxy->expects($this->once())
              ->method('returnObjectOfFinalClass');

        \assert($proxy instanceof MockObject);
        \assert($proxy instanceof TestProxyFixture);

        $this->assertSame('value', $proxy->returnObjectOfFinalClass()->value());
    }

    public function testProxyingWorksForMethodThatReturnsDeclaredObjectOfFinalClass(): void
    {
        $proxy = $this->createTestProxy(TestProxyFixture::class);

        $proxy->expects($this->once())
              ->method('returnTypedObjectOfFinalClass');

        \assert($proxy instanceof MockObject);
        \assert($proxy instanceof TestProxyFixture);

        $this->assertSame('value', $proxy->returnTypedObjectOfFinalClass()->value());
    }
}
