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

use App\Events\MailListSubscription;
use App\Events\MailListUpdated;
use App\Model\Contact;
use App\Model\Customer;
use App\Model\Form;
use App\Model\MailList;
use App\Model\MailListTemplate;
use App\Model\Subscriber;
use App\Model\Template;
use App\Services\SubscriberService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;

uses(TestCase::class);

beforeEach(function () {
    Config::set('sharding.enabled', false);
});

afterEach(function () {
    $listIds = DB::table('mail_lists')
        ->where('uid', 'like', 'subflow_list_%')
        ->pluck('id');

    $subscriberIds = DB::table('subscribers')
        ->whereIn('mail_list_id', $listIds)
        ->pluck('id');

    $mailListTemplateIds = DB::table('mail_list_templates')
        ->whereIn('mail_list_id', $listIds)
        ->pluck('id');

    $templateIds = DB::table('mail_list_templates')
        ->whereIn('id', $mailListTemplateIds)
        ->pluck('template_id');

    DB::table('timelines')->whereIn('subscriber_id', $subscriberIds)->delete();
    DB::table('forms')->whereIn('mail_list_id', $listIds)->delete();
    DB::table('mail_list_templates')->whereIn('id', $mailListTemplateIds)->delete();
    DB::table('subscribers')->whereIn('id', $subscriberIds)->delete();
    DB::table('fields')->whereIn('mail_list_id', $listIds)->delete();
    DB::table('mail_lists')->whereIn('id', $listIds)->delete();
    DB::table('templates')->whereIn('id', $templateIds)->delete();

    $customerIds = DB::table('customers')
        ->where('uid', 'like', 'subflow_customer_%')
        ->pluck('id');

    DB::table('customers')->whereIn('id', $customerIds)->delete();
    DB::table('contacts')->where('uid', 'like', 'subflow_contact_%')->delete();
});

function subscriberFlowFixture(array $listOverrides = []): array
{
    $contact = Contact::forceCreate([
        'uid'        => uniqid('subflow_contact_'),
        'first_name' => 'Subflow',
        'last_name'  => 'Tester',
        'email'      => uniqid('subflow_') . '@example.test',
    ]);

    $customer = Customer::forceCreate([
        'uid'        => uniqid('subflow_customer_'),
        'contact_id' => $contact->id,
        'status'     => 'active',
        'timezone'   => 'UTC',
    ]);

    $list = MailList::forceCreate(array_merge([
        'uid'                   => uniqid('subflow_list_'),
        'name'                  => 'Subscriber Flow List',
        'customer_id'           => $customer->id,
        'from_email'            => '[email protected]',
        'from_name'             => 'Sender',
        'subscribe_confirmation'=> false,
    ], $listOverrides));

    $thankYouTemplate = Template::forceCreate([
        'uid'     => uniqid('subflow_tpl_'),
        'name'    => 'Thank You',
        'content' => '<html><body><p>Thanks for confirming.</p></body></html>',
        'json'    => \App\Model\Template::DEFAULT_BUILDER_JSON,
    ]);

    MailListTemplate::forceCreate([
        'uid'         => uniqid('subflow_mltpl_'),
        'mail_list_id'=> $list->id,
        'customer_id' => $customer->id,
        'template_id' => $thankYouTemplate->id,
        'alias'       => 'sign_up_thankyou_page',
    ]);

    $confirmationTemplate = Template::forceCreate([
        'uid'     => uniqid('subflow_tpl_'),
        'name'    => 'Confirmation Email',
        'content' => '<html><body><a href="{{ SUBSCRIBE_CONFIRM_URL }}">Confirm</a></body></html>',
        'json'    => \App\Model\Template::DEFAULT_BUILDER_JSON,
    ]);

    $confirmationMailTemplate = MailListTemplate::forceCreate([
        'uid'         => uniqid('subflow_mltpl_'),
        'mail_list_id'=> $list->id,
        'customer_id' => $customer->id,
        'template_id' => $confirmationTemplate->id,
        'alias'       => 'sign_up_confirmation_email',
    ]);

    $form = Form::forceCreate([
        'uid'         => uniqid('subflow_form_'),
        'name'        => 'Popup Form',
        'status'      => Form::STATUS_PUBLISHED,
        'customer_id' => $customer->id,
        'mail_list_id'=> $list->id,
    ]);

    return [
        'contact'                  => $contact,
        'customer'                 => $customer,
        'list'                     => $list->fresh(),
        'form'                     => $form,
        'confirmationMailTemplate' => $confirmationMailTemplate->fresh(),
        'emailField'               => $list->getFieldByTag('EMAIL'),
        'firstNameField'           => $list->getFieldByTag('FIRST_NAME'),
    ];
}

it('requires a signed confirmation url and confirms only once', function () {
    Event::fake([MailListSubscription::class]);

    $fixture = subscriberFlowFixture(['subscribe_confirmation' => true]);
    $subscriber = Subscriber::forceCreate([
        'uid'          => uniqid('subflow_sub_'),
        'email'        => uniqid('confirm_') . '@example.test',
        'status'       => Subscriber::STATUS_UNCONFIRMED,
        'mail_list_id' => $fixture['list']->id,
    ]);

    $renderedConfirmation = $fixture['confirmationMailTemplate']->renderContent(null, $subscriber);
    expect($renderedConfirmation)->toContain('signature=');

    $unsignedUrl = route('lists.subscribe_confirm', [
        'list_uid'     => $fixture['list']->uid,
        'id'           => $subscriber->id,
        'customer_uid' => $fixture['customer']->uid,
    ], true);

    $this->get($unsignedUrl)->assertForbidden();
    expect($subscriber->fresh()->status)->toBe(Subscriber::STATUS_UNCONFIRMED);

    $signedUrl = app(SubscriberService::class)->generateSignedConfirmationUrl($subscriber);

    $this->get($signedUrl)->assertOk();
    expect($subscriber->fresh()->status)->toBe(Subscriber::STATUS_SUBSCRIBED);
    Event::assertDispatchedTimes(MailListSubscription::class, 1);

    $this->get($signedUrl)->assertOk();
    Event::assertDispatchedTimes(MailListSubscription::class, 1);
});

it('preserves existing subscriber fields when web opt in omits them', function () {
    Event::fake([MailListSubscription::class, MailListUpdated::class]);

    $fixture = subscriberFlowFixture(['subscribe_confirmation' => false]);
    $subscriber = Subscriber::forceCreate([
        'uid'          => uniqid('subflow_sub_'),
        'email'        => uniqid('resub_') . '@example.test',
        'status'       => Subscriber::STATUS_UNSUBSCRIBED,
        'mail_list_id' => $fixture['list']->id,
    ]);

    $subscriber->setFieldValue($fixture['firstNameField'], 'Existing Name');
    $subscriber->save();

    $request = Request::create('/frontend/lists/test/sign-up', 'POST', [
        'EMAIL' => $subscriber->email,
    ]);

    [$validator, $updatedSubscriber] = app(SubscriberService::class)->optInFromWeb($fixture['list'], $request);

    expect($validator->fails())->toBeFalse();
    expect($updatedSubscriber->id)->toBe($subscriber->id);
    expect($updatedSubscriber->fresh()->getValueByField($fixture['firstNameField']))->toBe('Existing Name');
});

it('dispatches mail list updated only once for popup opt in', function () {
    Event::fake([MailListUpdated::class, MailListSubscription::class]);

    $fixture = subscriberFlowFixture(['subscribe_confirmation' => false]);

    $response = $this->postJson('/frontend/forms/' . $fixture['form']->uid . '/save', [
        'EMAIL' => uniqid('popup_') . '@example.test',
    ]);

    $response->assertOk()->assertJson([
        'message' => 'OK',
    ]);

    Event::assertDispatchedTimes(MailListUpdated::class, 1);
    Event::assertDispatchedTimes(MailListSubscription::class, 1);
});