Newer
Older
gn-synapse-client-php / tests / EnvelopeBuilderTest.php
@Eugene Sukhodolskiy Eugene Sukhodolskiy 1 day ago 4 KB Initial client library skeleton (v0.1.0)
<?php

declare(strict_types=1);

namespace GNexus\Synapse\Tests\EnvelopeBuilder;

use GNexus\Synapse\Envelope\EnvelopeBuilder;
use GNexus\Synapse\Exception\ValidationException;
use GNexus\Synapse\Tests\FakeLogger;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class EnvelopeBuilderTest extends TestCase
{
    public function testBuildsMinimalEnvelope(): void
    {
        self::assertSame(
            ['source' => 's', 'subject' => 'x', 'action' => 'y'],
            EnvelopeBuilder::build('s', 'x', 'y'),
        );
        // сервер extra="forbid": None/пустых полей в конверте нет
        $env = EnvelopeBuilder::build('s', 'x', 'y', payload: null, dedupKey: '', ttlSeconds: null);
        self::assertSame(['source' => 's', 'subject' => 'x', 'action' => 'y'], $env);
    }

    public function testBuildsFullEnvelope(): void
    {
        $ts = new \DateTimeImmutable('2026-10-03 12:00:00', new \DateTimeZone('UTC'));
        $env = EnvelopeBuilder::build('s', 'x', 'y', 'high', ['user_id' => '42'], 'd1', 60, $ts);
        self::assertSame([
            'source' => 's', 'subject' => 'x', 'action' => 'y', 'priority' => 'high',
            'payload' => ['user_id' => '42'], 'dedup_key' => 'd1', 'ttl_seconds' => 60,
            'scheduled_at' => '2026-10-03T12:00:00+00:00',
        ], $env);
        // дефолтный priority не шлётся
        self::assertSame(
            ['source' => 's', 'subject' => 'x', 'action' => 'y'],
            EnvelopeBuilder::build('s', 'x', 'y', 'normal'),
        );
    }

    public static function badNamesProvider(): iterable
    {
        yield 'uppercase' => ['Bugtrail'];
        yield 'space' => ['a b'];
        yield 'leading dash' => ['-lead'];
        yield 'trailing dash' => ['trail-'];
        yield 'empty' => [''];
        yield 'too long' => [str_repeat('a', 65)];
        yield 'cyrillic' => ['спецсимволы'];
    }

    #[DataProvider('badNamesProvider')]
    public function testRejectsBadNames(string $bad): void
    {
        foreach ([[$bad, 'x', 'y'], ['s', $bad, 'y'], ['s', 'x', $bad]] as $args) {
            try {
                EnvelopeBuilder::build(...$args);
                self::fail("ожидалась ValidationException для '$args[0]', '$args[1]', '$args[2]'");
            } catch (ValidationException $ex) {
                self::assertIsString($ex->detail);
            }
        }
    }

    public function testRejectsPriorityTtlDedup(): void
    {
        try {
            EnvelopeBuilder::build('s', 'x', 'y', 'urgent');
            self::fail('ожидалась ValidationException');
        } catch (ValidationException $ex) {
            self::assertStringContainsString('priority', $ex->detail);
        }
        foreach ([0, -5, 604801] as $ttl) {
            try {
                EnvelopeBuilder::build('s', 'x', 'y', ttlSeconds: $ttl);
                self::fail("ожидалась ValidationException для ttlSeconds=$ttl");
            } catch (ValidationException $ex) {
                self::assertStringContainsString('ttlSeconds', $ex->detail);
            }
        }
        self::assertSame(604800, EnvelopeBuilder::build('s', 'x', 'y', ttlSeconds: 604800)['ttl_seconds']);
        try {
            EnvelopeBuilder::build('s', 'x', 'y', dedupKey: str_repeat('d', 256));
            self::fail('ожидалась ValidationException');
        } catch (ValidationException $ex) {
            self::assertStringContainsString('dedup_key', $ex->detail);
        }
    }

    public function testRejectsListPayload(): void
    {
        $this->expectException(ValidationException::class);
        $this->expectExceptionMessage('словар');
        EnvelopeBuilder::build('s', 'x', 'y', payload: ['не', 'словарь']);
    }

    public function testWarnsOnBadUserId(): void
    {
        $logs = new FakeLogger();
        EnvelopeBuilder::warnBadUserId(['user_id' => '42'], $logs);
        EnvelopeBuilder::warnBadUserId(['user_id' => 42], $logs);
        self::assertCount(0, $logs->warnings());
        EnvelopeBuilder::warnBadUserId(['user_id' => ''], $logs);
        EnvelopeBuilder::warnBadUserId(['user_id' => null], $logs);
        EnvelopeBuilder::warnBadUserId([], $logs);
        self::assertCount(3, $logs->warnings());
    }
}