ldc-boutique-cnc-sable/tests/Unit/Services/CrmServiceTest.php
Jérémy Munsch 8b96ce90be
test(casts): add tests for EmployeeSitesCast functionality
test(casts): add tests for ShopperEstablishmentCodeCast functionality

test(casts): add tests for ShopperServiceCodeCast functionality

test(casts): add tests for ShopperSiteCodeCast functionality

test(dto): update ProductDtoTest to include additional fields

test(dto): update SettingDtoTest to remove arcadiaSites assertions

test(events): update AnOrderHasBeenPlacedTest to use value objects

test(entities): update OrderTest to use value objects for employee details

test(value-objects): update EmployeeUpsertDataTest to use value objects

test(pagination): update PaginationTest to access value properties

test(services): update AppCustomerAuthServiceTest to use CrmHashcode

test(services): update CrmServiceTest to use CrmHashcode for customer retrieval
2026-10-27 09:58:45 +01:00

217 lines
7.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Services;
use App\Services\CrmService;
use Domain\Enums\Country;
use Domain\Models\ValueObjects\CrmCustomer;
use GuzzleHttp\Psr7\Response;
use Illuminate\Contracts\Cache\Repository as CacheRepository;
use LDC\LDCCRM\CrmApiV4;
use LDC\LDCCRM\Enums\ApiError;
use LDC\LDCCRM\Enums\ApiStatus;
use LDC\LDCCRM\Enums\Country as EnumsCountry;
use LDC\LDCCRM\Exceptions\ApiErrorException;
use LDC\LDCCRM\Models\ClientModel;
use LDC\LDCCRM\Models\Customer;
use LDC\LDCCRM\Transport\ApiInterface;
use LDC\LDCCRM\Utils;
use Mockery;
use Ramsey\Uuid\Uuid;
use Shared\ValueObjects\CrmHashcode;
describe('CrmService', function (): void {
it('returns customer from hashcode and caches it', function (): void {
// GIVEN
$crmApi = Mockery::mock(CrmApiV4::class);
$cacheRepository = Mockery::mock(CacheRepository::class);
$uuidObj = Uuid::uuid4();
$uuid = $uuidObj->toString();
$libCustomer = new Customer([
'hashcode' => $uuid,
'email' => 'john@example.com',
'password' => 'Secret123!',
'firstname' => 'John',
'lastname' => 'Doe',
'birth_date' => '1990-01-01',
'phone' => '0123456789',
'address' => '123 Main St',
'address2' => null,
'city' => 'Paris',
'postcode' => '75000',
'country' => EnumsCountry::france,
'opt_in' => true,
'status' => true,
'last_connection' => null,
]);
$cacheKey = "crm_customer_hashcode_{$uuid}";
$cacheRepository->shouldReceive('remember')
->once()
->with($cacheKey, Mockery::any(), Mockery::on(function ($closure) use ($crmApi, $libCustomer, $uuid) {
$crmApi->shouldReceive('getCustomer')->with((string) $uuid)->once()->andReturn($libCustomer);
$result = $closure();
return $result instanceof CrmCustomer && $result->hashcode === (string) $uuid;
}))
->andReturn(new CrmCustomer(
hashcode: (string) $uuid,
email: 'john@example.com',
password: 'Secret123!',
firstname: 'John',
lastname: 'Doe',
birthDate: '1990-01-01',
phone: '0123456789',
address: '123 Main St',
address2: null,
city: 'Paris',
postcode: '75000',
country: Country::france,
optIn: true,
status: true,
lastConnection: null,
));
$service = new CrmService($crmApi, $cacheRepository);
$hashcode = new CrmHashcode($uuidObj);
// WHEN
$firstCall = $service->getCustomerFromHashCode($hashcode);
// Second call should return from internal memory cache without querying CacheRepository again
$secondCall = $service->getCustomerFromHashCode($hashcode);
// THEN
expect($firstCall)->toBeInstanceOf(CrmCustomer::class)
->and($firstCall->hashcode)->toBe($uuid)
->and($secondCall)->toBe($firstCall);
});
it('returns customer from email with sha256 cache key', function (): void {
// GIVEN
$crmApi = Mockery::mock(CrmApiV4::class);
$cacheRepository = Mockery::mock(CacheRepository::class);
$email = 'test@example.com';
$cacheKey = 'crm_customer_email_' . hash('sha256', $email);
$expectedCustomer = new CrmCustomer(
hashcode: (string) Uuid::uuid4(),
email: $email,
password: 'Secret123!',
firstname: 'Jane',
lastname: 'Doe',
birthDate: '1992-05-10',
phone: '0123456789',
address: '456 Side St',
address2: null,
city: 'Lyon',
postcode: '69000',
country: Country::france,
optIn: false,
status: true,
lastConnection: null,
);
$cacheRepository->shouldReceive('remember')
->once()
->with($cacheKey, Mockery::any(), Mockery::type('Closure'))
->andReturn($expectedCustomer);
$service = new CrmService($crmApi, $cacheRepository);
// WHEN
$result = $service->getCustomerFromEmail($email);
// THEN
expect($result)->toBeInstanceOf(CrmCustomer::class)
->and($result->email)->toBe($email);
});
it('returns null on modelNotFound ApiErrorException and caches result', function (): void {
// GIVEN
$crmApi = Mockery::mock(CrmApiV4::class);
$cacheRepository = Mockery::mock(CacheRepository::class);
$uuid = Uuid::uuid4();
$cacheKey = "crm_customer_hashcode_{$uuid}";
$cacheRepository->shouldReceive('remember')
->once()
->with($cacheKey, Mockery::any(), Mockery::on(function ($closure) use ($crmApi, $uuid) {
$exception = Mockery::mock(ApiErrorException::class);
$exception->shouldReceive('getApiError')->andReturn(ApiError::modelNotFound);
$crmApi->shouldReceive('getCustomer')->with((string) $uuid)->once()->andThrow($exception);
$res = $closure();
return $res === null;
}))
->andReturnNull();
$service = new CrmService($crmApi, $cacheRepository);
// WHEN
$result = $service->getCustomerFromHashCode(new CrmHashcode($uuid));
// THEN
expect($result)->toBeNull();
});
it('invalidates cache on activate', function (): void {
// GIVEN
$crmApi = Mockery::mock(CrmApiV4::class);
$cacheRepository = Mockery::mock(CacheRepository::class);
$uuid = (string) Uuid::uuid4();
$customer = new CrmCustomer(
hashcode: $uuid,
email: 'activate@example.com',
password: 'Secret123!',
firstname: 'John',
lastname: 'Doe',
birthDate: '1990-01-01',
phone: '0123456789',
address: '123 Main St',
address2: null,
city: 'Paris',
postcode: '75000',
country: Country::france,
optIn: true,
status: false,
lastConnection: null,
);
$expectedHashKey = "crm_customer_hashcode_{$uuid}";
$expectedEmailKey = 'crm_customer_email_' . hash('sha256', 'activate@example.com');
$cacheRepository->shouldReceive('delete')->with($expectedHashKey)->once();
$cacheRepository->shouldReceive('delete')->with($expectedEmailKey)->once();
$apiInterface = Mockery::mock(ApiInterface::class);
$apiInterface->shouldReceive('call')->once()->andReturn(
new \LDC\LDCCRM\Transport\Response(
ApiStatus::OK,
new Response(200, [], (string) json_encode([
'version' => Utils::getPackageInfo()['version'],
'data' => [],
]))
)
);
$refProp = new \ReflectionProperty(ClientModel::class, 'apiInterface');
$refProp->setValue(null, $apiInterface);
$service = new CrmService($crmApi, $cacheRepository);
// WHEN
$result = $service->activate($customer);
// THEN
expect($result)->toHaveProperty('result');
});
});