ldc-crm/tests/CRM/ApiV2/SingleOptinTest.php

230 lines
7.8 KiB
PHP

<?php
namespace Tests\CRM\ApiV2;
use App\Enums\ApiError;
use App\Enums\ApiStatus;
use App\Enums\Country;
use App\Models\ModelAnswer;
use App\Models\Question;
use App\Models\Service;
use App\Models\SingleOptin;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\CreatesApplication;
class SingleOptinTest extends ApiBase
{
use CreatesApplication;
use DatabaseTransactions;
/** @var string $email */
private $email = 'singleoptin@hotmail.fr';
/**
* Test set single optin on.
* route: apiV2.optin
*
* @return void
*/
public function testSetSingleOptinOn(): void
{
$service = Service::firstOrFail();
$response = $this->callApiWithToken($service, 'post', route('apiV2.optin'), [
'email' => $this->email,
'opt_in' => 1,
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$this->assertTrue(
SingleOptin::query()->where('email', $this->email)->exists(),
'Single optin should have been set for email "singleoptin@hotmail.fr"'
);
}
/**
* Test set single optin on with answer associated.
* route: apiV2.optin
*
* @return void
*/
public function testSetSingleOptinOnWithAnswerAssociated(): void
{
$service = Service::firstOrFail();
/** @var \Illuminate\Database\Eloquent\Collection $questions */
$questions = Question::query()->whereHas('brand', function ($q) use ($service) {
$q->whereId($service->brand->getKey());
})->with('answers')->get()->keyBy('id');
// * Make sure a customer answer is set.
$firstAnswer = $questions->first()->answers->first();
$response = $this->callApiWithToken($service, 'post', route('apiV2.optin'), [
'email' => $this->email,
'opt_in' => 1,
'answer_id' => [$firstAnswer->getkey()],
]);
$singleOptin = SingleOptin::query()->where('email', $this->email);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$this->assertTrue(
$singleOptin->exists() && ModelAnswer::query()->where([
['answer_id', $firstAnswer->getkey()],
['model_id', !is_null($singleOptin->first()) ? $singleOptin->first()->getKey() : null],
['model_type', SingleOptin::class],
])->exists(),
'Single optin should have been set for email "singleoptin@hotmail.fr"'
);
}
/**
* Test set single optin off.
* route: apiV2.optin
*
* @return void
*/
public function testSetSingleOptinOff(): void
{
$service = Service::firstOrFail();
$response = $this->callApiWithToken($service, 'post', route('apiV2.optin'), [
'email' => $this->email,
'opt_in' => 0,
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$this->assertFalse(
SingleOptin::query()->where('email', $this->email)->exists(),
'Single optin should have been removed for email "singleoptin@hotmail.fr"'
);
}
/**
* Should throw an ApiError exception if trying to set
* optin to an email that already have an account.
*
* @return void
*/
public function testSingleOptinShouldFailIfOptinAlreadyExists(): void
{
$service = Service::firstOrFail();
$this->storeCustomer($service);
// * Make sure a single optin exists.
$singleOptin = SingleOptin::query()->where('email', $this->email)->firstOrNew();
$singleOptin->brand()->associate($service->brand);
$singleOptin->email = $this->email;
$singleOptin->saveOrFail();
$response = $this->callApiWithToken($service, 'post', route('apiV2.optin'), [
'email' => $this->email,
'opt_in' => 1,
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO);
$this->assertEquals(ApiError::singleOptinCustomerExists->value(), $json->json('data.code'));
$this->assertEquals(ApiError::singleOptinCustomerExists->label(), $json->json('data.message'));
}
/**
* Test set single optin on with anexisting answer associated.
*
* @return void
*/
public function testSingleOptinShouldFailIfAnswerIdDoesntExist(): void
{
$service = Service::query()->firstOrFail();
$response = $this->callApiWithToken($service, 'post', route('apiV2.optin'), [
'email' => $this->email,
'opt_in' => 1,
'answer_id' => [0],
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO);
$this->assertEquals(ApiError::validationFailed->value(), $json->json('data.code'));
}
/**
* Test set single optin off using hashcode.
* route: apiV2.optout-hashcode
*
* @return void
*/
public function testSetSingleOptoutWithHashcode(): void
{
$service = Service::firstOrFail();
// * Make sure a single optin exists.
$singleOptin = SingleOptin::query()->where('email', 'singleoptout@hotmail.fr')->firstOrNew();
$singleOptin->brand()->associate($service->brand);
$singleOptin->email = 'singleoptout@hotmail.fr';
$singleOptin->saveOrFail();
$singleOptin->refresh();
$response = $this->callApiWithToken($service, 'post', route('apiV2.optout-hashcode'), [
'hashcode' => $singleOptin->hashcode,
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::OK);
$this->assertFalse(
SingleOptin::query()->where('email', 'singleoptout@hotmail.fr')->exists(),
'Single optin should have been removed for email "singleoptout@hotmail.fr"'
);
}
/**
* Test set single optin off using hashcode fails if does not exists.
* route: apiV2.optout-hashcode
*
* @return void
*/
public function testSetSingleOptoutWithHashcodeFailsIfDoesNotExists(): void
{
$service = Service::firstOrFail();
// * Make sure a single optin exists.
$singleOptin = SingleOptin::query()->where('email', 'singleoptout@hotmail.fr')->firstOrNew();
$singleOptin->brand()->associate($service->brand);
$singleOptin->email = 'singleoptout@hotmail.fr';
$singleOptin->saveOrFail();
$singleOptin->refresh();
// * Make sure a single optin does exists.
$singleOptin->delete();
$response = $this->callApiWithToken($service, 'post', route('apiV2.optout-hashcode'), [
'hashcode' => $singleOptin->hashcode,
]);
$json = $response->decodeResponseJson();
$this->assertApiResponseStatusIs($json, ApiStatus::KO);
$this->assertEquals(ApiError::modelNotFound->value(), $json->json('data.code'));
}
/**
* Store a customer in DB.
*
* @param \App\Models\Service $service
* @return void
*/
private function storeCustomer(Service $service): void
{
$data = [
'firstname' => 'Jean',
'lastname' => 'Bond',
'birth_date' => \date('1992-03-08'),
'address' => '10 rue des totos',
'email' => $this->email,
'password' => '123.Mot.De.P4sse',
'phone' => '+33654821562',
'country' => Country::france->value(),
'city' => 'Connerré',
'postcode' => '72160',
'opt_in' => true
];
$this->callApiWithToken($service, 'post', route('apiV2.customers.store'), $data);
}
}