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/be.naniguide.com/tests/Feature/SendingServerWebhooks/RecordComplaintListenerTest.php
<?php

use App\Listeners\SendingServerWebhooks\RecordComplaint;
use App\Model\Blacklist;
use App\Model\Contact;
use App\Model\Customer;
use App\Model\FeedbackLog;
use App\Model\MailList;
use App\Model\SendingServer;
use App\Model\Subscriber;
use App\Model\TrackingLog;
use App\SendingServers\Webhooks\ComplaintReceived;
use App\SendingServers\Webhooks\FeedbackType;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

uses(TestCase::class, DatabaseTransactions::class);

function makeComplaintFixture(): array
{
    $contact = Contact::factory()->create();
    $customer = Customer::factory()->create([
        'contact_id' => $contact->id,
        'uid'        => 'rclstcust' . uniqid(),
    ]);
    $list = MailList::forceCreate([
        'uid'         => 'rclst_' . uniqid(),
        'customer_id' => $customer->id,
        'name'        => 'fixture',
        'from_name'   => 'Fixture',
        'from_email'  => '[email protected]',
    ]);
    $subscriber = Subscriber::factory()->create([
        'mail_list_id' => $list->id,
        'email'        => '[email protected]',
    ]);
    $msgId = 'cpl' . uniqid() . '.' . $customer->uid . '@example.com';
    $server = SendingServer::factory()->create();
    $trackingLog = TrackingLog::forceCreate([
        'runtime_message_id' => $msgId,
        'message_id'         => 'vendor-msg-id-cpl',
        'customer_id'        => $customer->id,
        'subscriber_id'      => $subscriber->id,
        'sending_server_id'  => $server->id,
        'status'             => 'sent',
    ]);

    return compact('customer', 'subscriber', 'msgId', 'trackingLog', 'server');
}

test('ComplaintReceived → FeedbackLog row + markAsSpamReported on subscriber (SendGrid parity)', function () {
    $f = makeComplaintFixture();

    $event = new ComplaintReceived(
        runtimeMessageId: $f['msgId'],
        type: FeedbackType::SPAM,
        feedbackTypeRaw: 'spam',
        shouldBlacklist: false,            // SendGrid: no blacklist
        shouldMarkSpamReported: true,
        rawForDb: '{"raw":"sg-payload"}',
        rawPayload: [],
        server: $f['server'],
    );

    (new RecordComplaint())->handle($event);

    $log = FeedbackLog::where('runtime_message_id', $f['msgId'])->firstOrFail();
    expect($log->feedback_type)->toBe('spam')
        ->and($log->raw_feedback_content)->toBe('{"raw":"sg-payload"}')
        ->and($log->tracking_log_id)->toBe($f['trackingLog']->id)
        ->and($log->message_id)->toBe('vendor-msg-id-cpl');

    expect(Blacklist::where('email', $f['subscriber']->email)->exists())->toBeFalse();
});

test('ComplaintReceived with shouldBlacklist=true → blacklist + markAsSpamReported (Mailgun Q7 parity)', function () {
    $f = makeComplaintFixture();

    $event = new ComplaintReceived(
        runtimeMessageId: $f['msgId'],
        type: FeedbackType::SPAM,
        feedbackTypeRaw: 'spam',
        shouldBlacklist: true,             // Q7: Mailgun unique
        shouldMarkSpamReported: false,     // PARITY: Mailgun did NOT call markAsSpamReported
        rawForDb: '{"raw":"mg-payload"}',
        rawPayload: [],
        server: $f['server'],
        messageIdAlwaysRuntime: true,      // Mailgun parity
    );

    (new RecordComplaint())->handle($event);

    $log = FeedbackLog::where('runtime_message_id', $f['msgId'])->firstOrFail();
    expect($log->message_id)->toBe($f['msgId']);   // Mailgun-only override

    expect(Blacklist::where('email', $f['subscriber']->email)->exists())->toBeTrue();
});

test('ComplaintReceived preserves raw feedbackTypeRaw (AWS abuse vs spam)', function () {
    $f = makeComplaintFixture();

    $event = new ComplaintReceived(
        runtimeMessageId: $f['msgId'],
        type: FeedbackType::SPAM,
        feedbackTypeRaw: 'abuse',          // PARITY: AWS sends 'abuse' verbatim
        shouldBlacklist: false,
        shouldMarkSpamReported: true,
        rawForDb: '{"sns":"payload"}',
        rawPayload: [],
        server: $f['server'],
    );

    (new RecordComplaint())->handle($event);

    $log = FeedbackLog::where('runtime_message_id', $f['msgId'])->firstOrFail();
    expect($log->feedback_type)->toBe('abuse');
});

test('ComplaintReceived for unknown customer → log + skip (no DB write)', function () {
    $server = SendingServer::factory()->create();

    $event = new ComplaintReceived(
        runtimeMessageId: '[email protected]',
        type: FeedbackType::SPAM,
        feedbackTypeRaw: 'spam',
        shouldBlacklist: true,
        shouldMarkSpamReported: true,
        rawForDb: '{}',
        rawPayload: [],
        server: $server,
    );

    (new RecordComplaint())->handle($event);

    expect(FeedbackLog::where('runtime_message_id', '[email protected]')->exists())
        ->toBeFalse();
});