<commit_before><?php

declare(strict_types=1);

namespace ShlinkioTest\Shlink\Rest\Action;

use Cake\Chronos\Chronos;
use Laminas\Diactoros\Response\JsonResponse;
use Laminas\Diactoros\ServerRequestFactory;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Common\Mercure\JwtProviderInterface;
use Shlinkio\Shlink\Rest\Action\MercureInfoAction;
use Shlinkio\Shlink\Rest\Exception\MercureException;

class MercureInfoActionTest extends TestCase
{
    use ProphecyTrait;

    private ObjectProphecy $provider;

    protected function setUp(): void
    {
        $this->provider = $this->prophesize(JwtProviderInterface::class);
    }

    /**
     * @test
     * @dataProvider provideNoHostConfigs
     */
    public function throwsExceptionWhenConfigDoesNotHavePublicHost(array $mercureConfig): void
    {
        $buildToken = $this->provider->buildSubscriptionToken(Argument::any())->willReturn('abc.123');

        $action = new MercureInfoAction($this->provider->reveal(), $mercureConfig);

        $this->expectException(MercureException::class);
        $buildToken->shouldNotBeCalled();

        $action->handle(ServerRequestFactory::fromGlobals());
    }

    public function provideNoHostConfigs(): iterable
    {
        yield 'host not defined' => [[]];
        yield 'host is null' => [['public_hub_url' => null]];
    }

    public function provideValidConfigs(): iterable
    {
        yield 'days not defined' => [['public_hub_url' => 'http://foobar.com']];
        yield 'days defined' => [['public_hub_url' => 'http://foobar.com', 'jwt_days_duration' => 20]];
    }

    /**
     * @test
     * @dataProvider provideDays
     */
    public function returnsExpectedInfoWhenEverythingIsOk(?int $days): void
    {
        $buildToken = $this->provider->buildSubscriptionToken(Argument::any())->willReturn('<PASSWORD>');

        $action = new MercureInfoAction($this->provider->reveal(), [
            'public_hub_url' => 'http://foobar.com',
            'jwt_days_duration' => $days,
        ]);

        /** @var JsonResponse $resp */
        $resp = $action->handle(ServerRequestFactory::fromGlobals());
        $payload = $resp->getPayload();

        self::assertArrayHasKey('mercureHubUrl', $payload);
        self::assertEquals('http://foobar.com/.well-known/mercure', $payload['mercureHubUrl']);
        self::assertArrayHasKey('token', $payload);
        self::assertArrayHasKey('jwtExpiration', $payload);
        self::assertEquals(
            Chronos::now()->addDays($days ?? 1)->startOfDay(),
            Chronos::parse($payload['jwtExpiration'])->startOfDay(),
        );
        $buildToken->shouldHaveBeenCalledOnce();
    }

    public function provideDays(): iterable
    {
        yield 'days not defined' => [null];
        yield 'days defined' => [10];
    }<commit_msg>Migrated MercureInfoActionTest to use PHPUnit mocks<commit_after><?php

declare(strict_types=1);

namespace ShlinkioTest\Shlink\Rest\Action;

use Cake\Chronos\Chronos;
use Laminas\Diactoros\Response\JsonResponse;
use Laminas\Diactoros\ServerRequestFactory;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Common\Mercure\JwtProviderInterface;
use Shlinkio\Shlink\Rest\Action\MercureInfoAction;
use Shlinkio\Shlink\Rest\Exception\MercureException;

class MercureInfoActionTest extends TestCase
{
    private MockObject $provider;

    protected function setUp(): void
    {
        $this->provider = $this->createMock(JwtProviderInterface::class);
    }

    /**
     * @test
     * @dataProvider provideNoHostConfigs
     */
    public function throwsExceptionWhenConfigDoesNotHavePublicHost(array $mercureConfig): void
    {
        $this->provider->expects($this->never())->method('buildSubscriptionToken');

        $action = new MercureInfoAction($this->provider, $mercureConfig);

        $this->expectException(MercureException::class);

        $action->handle(ServerRequestFactory::fromGlobals());
    }

    public function provideNoHostConfigs(): iterable
    {
        yield 'host not defined' => [[]];
        yield 'host is null' => [['public_hub_url' => null]];
    }

    public function provideValidConfigs(): iterable
    {
        yield 'days not defined' => [['public_hub_url' => 'http://foobar.com']];
        yield 'days defined' => [['public_hub_url' => 'http://foobar.com', 'jwt_days_duration' => 20]];
    }

    /**
     * @test
     * @dataProvider provideDays
     */
    public function returnsExpectedInfoWhenEverythingIsOk(?int $days): void
    {
        $this->provider->expects($this->once())->method('buildSubscriptionToken')->willReturn('<PASSWORD>');

        $action = new MercureInfoAction($this->provider, [
            'public_hub_url' => 'http://foobar.com',
            'jwt_days_duration' => $days,
        ]);

        /** @var JsonResponse $resp */
        $resp = $action->handle(ServerRequestFactory::fromGlobals());
        $payload = $resp->getPayload();

        self::assertArrayHasKey('mercureHubUrl', $payload);
        self::assertEquals('http://foobar.com/.well-known/mercure', $payload['mercureHubUrl']);
        self::assertArrayHasKey('token', $payload);
        self::assertArrayHasKey('jwtExpiration', $payload);
        self::assertEquals(
            Chronos::now()->addDays($days ?? 1)->startOfDay(),
            Chronos::parse($payload['jwtExpiration'])->startOfDay(),
        );
    }

    public function provideDays(): iterable
    {
        yield 'days not defined' => [null];
        yield 'days defined' => [10];
    }
{'fraction_non_alphanumeric': 0.14647987231778684, 'fraction_numerical': 0.0026600461074658627, 'mean_word_length': 3.5228548516439453, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 70, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3514637', 'n_tokens_mistral': 1727, 'n_tokens_neox': 1670, 'n_words': 269}