HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/tests/Unit/SendingServers/Webhooks/ElasticEmailParseWebhookTest.php
<?php

use App\Model\BounceLog;
use App\Model\SendingServer;
use App\SendingServers\Drivers\Vendors\ElasticEmail\ElasticEmailApiDriver;
use App\SendingServers\Webhooks\BounceReceived;
use App\SendingServers\Webhooks\BounceType;
use App\SendingServers\Webhooks\ComplaintReceived;
use App\SendingServers\Webhooks\FeedbackType;
use App\SendingServers\Webhooks\IgnorableWebhookEvent;
use Illuminate\Http\Request;
use Tests\TestCase;

uses(TestCase::class);

/**
 * Wave D.2 parity test: ElasticEmail uses GET-based callbacks with
 * `transaction` and `status` query params (different transport from
 * other vendors which use JSON POST).
 *
 * Parity contract:
 *   - status='Error' → BounceLog HARD blacklist
 *   - status='AbuseReport' → FeedbackLog spam markSpamReported
 *   - case-insensitive comparison (legacy used strcasecmp)
 *   - missing transaction → log + skip
 *   - rawForDb := json_encode(params)
 */

function makeElasticEmailDriver(): ElasticEmailApiDriver
{
    $server = new SendingServer(['type' => 'elasticemail-api', 'name' => 'fixture']);
    $server->uid = 'fixture-uid';
    return new ElasticEmailApiDriver($server);
}

test('elasticemail status=Error → BounceReceived (HARD, blacklist)', function () {
    $driver = makeElasticEmailDriver();
    $req = Request::create('/webhook/elasticemail-api/fixture-uid?transaction=fixture-tx-001&status=Error&[email protected]', 'GET');

    $events = iterator_to_array($driver->parseWebhook($req));

    expect($events)->toHaveCount(1)
        ->and($events[0])->toBeInstanceOf(BounceReceived::class)
        ->and($events[0]->runtimeMessageId)->toBe('fixture-tx-001')
        ->and($events[0]->type)->toBe(BounceType::HARD)
        ->and($events[0]->bounceTypeRaw)->toBe(BounceLog::HARD)
        ->and($events[0]->shouldBlacklist)->toBeTrue();
});

test('elasticemail status=AbuseReport → ComplaintReceived (markSpamReported, no blacklist)', function () {
    $driver = makeElasticEmailDriver();
    $req = Request::create('/webhook/elasticemail-api/fixture-uid?transaction=fixture-tx-002&status=AbuseReport', 'GET');

    $events = iterator_to_array($driver->parseWebhook($req));

    expect($events)->toHaveCount(1)
        ->and($events[0])->toBeInstanceOf(ComplaintReceived::class)
        ->and($events[0]->type)->toBe(FeedbackType::SPAM)
        ->and($events[0]->feedbackTypeRaw)->toBe('spam')
        ->and($events[0]->shouldBlacklist)->toBeFalse()
        ->and($events[0]->shouldMarkSpamReported)->toBeTrue();
});

test('elasticemail case-insensitive status (legacy used strcasecmp)', function () {
    $driver = makeElasticEmailDriver();
    $req = Request::create('/webhook/elasticemail-api/fixture-uid?transaction=tx&status=ERROR', 'GET');

    $events = iterator_to_array($driver->parseWebhook($req));

    expect($events[0])->toBeInstanceOf(BounceReceived::class);
});

test('elasticemail unknown status → IgnorableWebhookEvent (parity skip)', function () {
    $driver = makeElasticEmailDriver();
    $req = Request::create('/webhook/elasticemail-api/fixture-uid?transaction=tx&status=Sent', 'GET');

    $events = iterator_to_array($driver->parseWebhook($req));

    expect($events)->toHaveCount(1)
        ->and($events[0])->toBeInstanceOf(IgnorableWebhookEvent::class);
});

test('elasticemail missing transaction → no events', function () {
    $driver = makeElasticEmailDriver();
    $req = Request::create('/webhook/elasticemail-api/fixture-uid?status=Error', 'GET');

    $events = iterator_to_array($driver->parseWebhook($req));

    expect($events)->toBeEmpty();
});

test('elasticemail rawForDb is json_encode of full param array (parity)', function () {
    $driver = makeElasticEmailDriver();
    $req = Request::create('/webhook/elasticemail-api/fixture-uid?transaction=tx-1&status=Error&extra=x', 'GET');

    $events = iterator_to_array($driver->parseWebhook($req));

    $expected = json_encode(['transaction' => 'tx-1', 'status' => 'Error', 'extra' => 'x']);
    expect($events[0]->rawForDb)->toBe($expected);
});