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/VariantResolverTest.php
<?php

/**
 * VariantResolverTest — pure logic for picking the Email that drives a send.
 *
 * - Without a variant, returns the campaign's base email unmodified.
 * - With a variant, returns the variant's email and merges the base's
 *   from_email / from_name / reply_to into any field the variant left empty.
 * - Throws when the variant references a non-existent email row.
 *
 * No DB / no factories — uses Mockery + plain Email instances since the
 * resolver only reads $campaign->email and $variant->email()->first().
 */

use App\Library\Sending\Variants\ResolvedEmail;
use App\Library\Sending\Variants\VariantResolver;
use App\Model\AbTestVariant;
use App\Model\Campaign;
use App\Model\Email;
use Tests\TestCase;

uses(TestCase::class);

it('returns the campaign base email when no variant is provided', function () {
    $email = new Email(['from_email' => '[email protected]']);
    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('email')->andReturn($email);

    $resolved = (new VariantResolver())->resolve($campaign, null);

    expect($resolved)->toBeInstanceOf(ResolvedEmail::class);
    expect($resolved->email)->toBe($email);
    expect($resolved->isVariant)->toBeFalse();
});

it('returns the variant email when variant has its own sender identity', function () {
    $baseEmail = new Email([
        'from_email' => '[email protected]',
        'from_name' => 'Base Sender',
        'reply_to' => '[email protected]',
    ]);
    $variantEmail = new Email([
        'from_email' => '[email protected]',
        'from_name' => 'Variant Sender',
        'reply_to' => '[email protected]',
    ]);

    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('email')->andReturn($baseEmail);

    $variant = Mockery::mock(AbTestVariant::class);
    $emailRelation = Mockery::mock(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
    $emailRelation->shouldReceive('first')->andReturn($variantEmail);
    $variant->shouldReceive('email')->andReturn($emailRelation);

    $resolved = (new VariantResolver())->resolve($campaign, $variant);

    expect($resolved->email)->toBe($variantEmail);
    expect($resolved->isVariant)->toBeTrue();
    expect($resolved->email->from_email)->toBe('[email protected]');
    expect($resolved->email->from_name)->toBe('Variant Sender');
    expect($resolved->email->reply_to)->toBe('[email protected]');
});

it('inherits empty sender-identity fields from the base email', function () {
    $baseEmail = new Email([
        'from_email' => '[email protected]',
        'from_name' => 'Base Sender',
        'reply_to' => '[email protected]',
    ]);
    $variantEmail = new Email([
        'from_email' => '',
        'from_name' => null,
        'reply_to' => '',
    ]);

    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('email')->andReturn($baseEmail);

    $variant = Mockery::mock(AbTestVariant::class);
    $emailRelation = Mockery::mock(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
    $emailRelation->shouldReceive('first')->andReturn($variantEmail);
    $variant->shouldReceive('email')->andReturn($emailRelation);

    $resolved = (new VariantResolver())->resolve($campaign, $variant);

    expect($resolved->email->from_email)->toBe('[email protected]');
    expect($resolved->email->from_name)->toBe('Base Sender');
    expect($resolved->email->reply_to)->toBe('[email protected]');
});

it('partially inherits — only fills the empty fields, keeps the variant ones', function () {
    $baseEmail = new Email([
        'from_email' => '[email protected]',
        'from_name' => 'Base Sender',
        'reply_to' => '[email protected]',
    ]);
    $variantEmail = new Email([
        'from_email' => '[email protected]',
        'from_name' => '',
        'reply_to' => '[email protected]',
    ]);

    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('email')->andReturn($baseEmail);

    $variant = Mockery::mock(AbTestVariant::class);
    $emailRelation = Mockery::mock(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
    $emailRelation->shouldReceive('first')->andReturn($variantEmail);
    $variant->shouldReceive('email')->andReturn($emailRelation);

    $resolved = (new VariantResolver())->resolve($campaign, $variant);

    expect($resolved->email->from_email)->toBe('[email protected]');  // variant's
    expect($resolved->email->from_name)->toBe('Base Sender');             // inherited
    expect($resolved->email->reply_to)->toBe('[email protected]');// variant's
});

it('throws when the variant points at a missing email row', function () {
    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('email')->andReturn(null);

    $variant = Mockery::mock(AbTestVariant::class);
    $variant->shouldReceive('getAttribute')->with('id')->andReturn(42);
    $variant->shouldReceive('getAttribute')->with('email_id')->andReturn(999);
    $emailRelation = Mockery::mock(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
    $emailRelation->shouldReceive('first')->andReturn(null);
    $variant->shouldReceive('email')->andReturn($emailRelation);

    expect(fn () => (new VariantResolver())->resolve($campaign, $variant))
        ->toThrow(\RuntimeException::class, 'AbTestVariant 42 has no associated Email row (email_id=999)');
});

it('handles null base email gracefully (variant with no base to inherit from)', function () {
    $variantEmail = new Email([
        'from_email' => '[email protected]',
        'from_name' => 'Variant Sender',
        'reply_to' => '[email protected]',
    ]);

    $campaign = Mockery::mock(Campaign::class);
    $campaign->shouldReceive('getAttribute')->with('email')->andReturn(null);

    $variant = Mockery::mock(AbTestVariant::class);
    $emailRelation = Mockery::mock(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
    $emailRelation->shouldReceive('first')->andReturn($variantEmail);
    $variant->shouldReceive('email')->andReturn($emailRelation);

    $resolved = (new VariantResolver())->resolve($campaign, $variant);

    expect($resolved->email)->toBe($variantEmail);
    expect($resolved->isVariant)->toBeTrue();
});