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'); }); });