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/Unit/Sending/SendMetricsRecorderTest.php
<?php

/**
 * SendMetricsRecorderTest — verifies the per-message timing accumulator
 * computes the right averages and writes the expected debug() shape.
 *
 * The recorder is purely arithmetic over recorded timestamps, plus one
 * Campaign::debug(closure) flush at the end. The campaign mock records what
 * the closure produces so we can assert the persisted dict shape.
 */

use App\Library\Sending\Metrics\SendMetricsRecorder;
use App\Library\Sending\SendContext;
use App\Model\Campaign;
use App\Model\Subscriber;
use Tests\TestCase;

uses(TestCase::class);

it('flushes a single debug() write with averages computed against the previous count', function () {
    $stored = null;
    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('uid')->andReturn('camp-uid');
    $campaign->shouldReceive('debug')->once()->andReturnUsing(function ($callback) use (&$stored) {
        // Simulate the cache-backed dict starting from a previous send having recorded count=2 with 1.0s avg.
        $stored = $callback([
            'start_at' => now()->subMinute()->toString(),
            'send_message_count' => 2,
            'send_message_avg_time' => 1.0,
            'send_message_prepare_avg_time' => 0.5,
            'send_message_lock_avg_time' => 0.1,
            'send_message_delivery_avg_time' => 0.4,
            'send_message_min_time' => 1.0,
            'send_message_max_time' => 1.0,
        ]);

        return $stored;
    });

    $subscriber = Mockery::mock(Subscriber::class);
    $subscriber->shouldReceive('getEmail')->andReturn('[email protected]');

    $ctx = new SendContext(campaign: $campaign, subscriber: $subscriber, servers: null);

    $recorder = new SendMetricsRecorder();
    $recorder->markPreparingDone();
    $recorder->markGotLock();
    $recorder->markComposed();
    $recorder->markDelivered();
    $recorder->flush($ctx);

    expect($stored)->toBeArray();
    expect($stored['send_message_count'])->toBe(3);    // incremented from 2
    expect($stored['send_message_avg_time'])->toBeFloat();
    expect($stored['last_message_sent_at'])->toBeString();
    expect($stored['last_activity_at'])->toBeString();
    expect($stored['messages_sent_per_second'])->toBeFloat();
});

it('initialises averages on the first flush (count=0 -> first sample becomes the avg)', function () {
    $stored = null;
    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('uid')->andReturn('camp-uid');
    $campaign->shouldReceive('debug')->andReturnUsing(function ($callback) use (&$stored) {
        $stored = $callback([
            'start_at' => null,
            'send_message_count' => 0,
            'send_message_avg_time' => null,
            'send_message_prepare_avg_time' => null,
            'send_message_lock_avg_time' => null,
            'send_message_delivery_avg_time' => null,
            'send_message_min_time' => null,
            'send_message_max_time' => null,
        ]);

        return $stored;
    });

    $subscriber = Mockery::mock(Subscriber::class);
    $subscriber->shouldReceive('getEmail')->andReturn('[email protected]');
    $ctx = new SendContext(campaign: $campaign, subscriber: $subscriber, servers: null);

    $recorder = new SendMetricsRecorder();
    $recorder->markPreparingDone();
    $recorder->markGotLock();
    $recorder->markComposed();
    $recorder->markDelivered();
    $recorder->flush($ctx);

    expect($stored['send_message_count'])->toBe(1);
    expect($stored['send_message_avg_time'])->not->toBeNull();
    expect($stored['send_message_min_time'])->toBe($stored['send_message_max_time']);
});

it('flushes safely when no marks were called (degraded path: missed all timestamps)', function () {
    $stored = null;
    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('uid')->andReturn('camp-uid');
    $campaign->shouldReceive('debug')->andReturnUsing(function ($callback) use (&$stored) {
        $stored = $callback([
            'start_at' => null,
            'send_message_count' => 0,
            'send_message_avg_time' => null,
            'send_message_prepare_avg_time' => null,
            'send_message_lock_avg_time' => null,
            'send_message_delivery_avg_time' => null,
            'send_message_min_time' => null,
            'send_message_max_time' => null,
        ]);

        return $stored;
    });

    $subscriber = Mockery::mock(Subscriber::class);
    $subscriber->shouldReceive('getEmail')->andReturn('[email protected]');
    $ctx = new SendContext(campaign: $campaign, subscriber: $subscriber, servers: null);

    (new SendMetricsRecorder())->flush($ctx);

    expect($stored)->toBeArray();
    expect($stored['send_message_count'])->toBe(1);
});