ldc-boutique-cnc-sable/tests/Unit/Infra/Adapters/Services/AppCustomerAuthServiceTest.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

404 lines
14 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit\Infra\Adapters\Services;
use App\Exceptions\AuthServiceException;
use App\Exceptions\CrmServiceException;
use App\Models\Customer;
use App\Services\CrmService;
use Domain\Contracts\CustomerDetails;
use Domain\Enums\Country;
use Domain\Models\ValueObjects\CrmCustomer;
use Domain\Models\ValueObjects\Email;
use Domain\Services\ShopperService;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Infrastructure\Adapters\Services\AppCustomerAuthService;
use Mockery;
use Ramsey\Uuid\Uuid;
use Shared\ValueObjects\CrmHashcode;
describe('AppCustomerAuthService', function (): void {
it('checks abilities with customer', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new class () extends Customer
{
public function can($abilities, $arguments = [])
{
return $abilities === 'view-order';
}
};
$guard->shouldReceive('user')->andReturn($customer);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$result = $service->canWithCustomer('view-order');
// THEN
expect($result)->toBeTrue();
});
it('returns false for abilities if customer is null', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$guard->shouldReceive('user')->andReturn(null);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$result = $service->canWithCustomer('view-order');
// THEN
expect($result)->toBeFalse();
});
it('logs in customer when active', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$customer->id = (string) Uuid::uuid7();
$shopperService->shouldReceive('canCustomerPassOrdersApp')->withAnyArgs()->andReturn(true);
$guard->shouldReceive('login')->with($customer)->once();
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$service->logIn($customer);
// THEN
expect(true)->toBeTrue();
});
it('throws exception if logging in non-authenticatable', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$invalidCustomer = new class () implements CustomerDetails
{
};
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$action = fn () => $service->logIn($invalidCustomer);
// THEN
expect($action)->toThrow(\InvalidArgumentException::class, 'Expected an instance of Authenticatable and Customer for logging in');
});
it('logs out', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$guard->shouldReceive('logout')->once();
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$service->logout();
// THEN
expect(true)->toBeTrue();
});
it('checks if user is logged in', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$guard->shouldReceive('check')->andReturn(true);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$check = $service->check();
$guest = $service->guest();
// THEN
expect($check)->toBeTrue()
->and($guest)->toBeFalse();
});
it('gets customer safely', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$guard->shouldReceive('user')->andReturn($customer);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$returned = $service->getCustomer();
// THEN
expect($returned)->toBeInstanceOf(Customer::class)
->and($returned)->not->toBe($customer); // Should be a clone
});
it('throws exception when customer is not a frontend Customer model', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$user = new class () implements Authenticatable
{
public function getAuthIdentifierName()
{
return 'id';
}
public function getAuthIdentifier()
{
return 1;
}
public function getAuthPassword()
{
return 'password';
}
public function getAuthPasswordName()
{
return 'password';
}
public function getRememberToken()
{
return '';
}
public function setRememberToken($value)
{
}
public function getRememberTokenName()
{
return '';
}
};
$guard->shouldReceive('user')->andReturn($user);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$action = fn () => $service->getCustomer();
// THEN
expect($action)->toThrow(\InvalidArgumentException::class, 'Auth service needs a frontend guard');
});
it('gets customer as mandatory', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$guard->shouldReceive('user')->andReturn($customer);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$returned = $service->getCustomerAsMandatory();
// THEN
expect($returned)->toBeInstanceOf(Customer::class);
});
it('throws exception when getting customer as mandatory but null', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$guard->shouldReceive('user')->andReturn(null);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$action = fn () => $service->getCustomerAsMandatory();
// THEN
expect($action)->toThrow(AuthServiceException::class, 'Authenticated user is required from here');
});
it('resets password', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$customer->email = new Email('test@example.com');
$crmService->shouldReceive('resetPasswordFor')->with($customer->email, 'newpass')->andReturn(true);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$result = $service->resetPasswordFor($customer, 'newpass');
// THEN
expect($result)->toBeTrue();
});
it('checks if email is verified', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$hashcode = new CrmHashcode(Uuid::uuid4());
$customer->hashcode = $hashcode;
// DO NOT MOCK CrmCustomer
$crmCustomer = new CrmCustomer(
hashcode: $hashcode->value,
email: 'test@example.com',
password: 'password',
firstname: 'John',
lastname: 'Doe',
birthDate: '1990-01-01',
phone: '123456789',
address: '123 Main St',
address2: null,
city: 'Paris',
postcode: '75000',
country: Country::france,
optIn: true,
status: true,
lastConnection: null
);
$crmService->shouldReceive('getCustomerFromHashCode')->with($customer->hashcode)->andReturn($crmCustomer);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$result = $service->hasVerifiedEmail($customer);
// THEN
expect($result)->toBeTrue();
});
it('returns false for hasVerifiedEmail if crm customer not found', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$hashcode = new CrmHashcode(Uuid::uuid4());
$customer->hashcode = $hashcode;
$crmService->shouldReceive('getCustomerFromHashCode')->with($customer->hashcode)->andReturn(null);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$result = $service->hasVerifiedEmail($customer);
// THEN
expect($result)->toBeFalse();
});
it('verifies email successfully', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$hashcode = new CrmHashcode(Uuid::uuid4());
$customer->hashcode = $hashcode;
$crmCustomer = new CrmCustomer(
hashcode: $hashcode->value,
email: 'test@example.com',
password: 'password',
firstname: 'John',
lastname: 'Doe',
birthDate: '1990-01-01',
phone: '123456789',
address: '123 Main St',
address2: null,
city: 'Paris',
postcode: '75000',
country: Country::france,
optIn: true,
status: true,
lastConnection: null
);
$crmService->shouldReceive('getCustomerFromHashCode')->with($customer->hashcode)->andReturn($crmCustomer);
$activation = new \stdClass();
$activation->result = true;
$crmService->shouldReceive('activate')->with($crmCustomer)->andReturn($activation);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$result = $service->verifyEmail($customer);
// THEN
expect($result)->toBeTrue();
});
it('returns false for verifyEmail if crm customer not found', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$hashcode = new CrmHashcode(Uuid::uuid4());
$customer->hashcode = $hashcode;
$crmService->shouldReceive('getCustomerFromHashCode')->with($customer->hashcode)->andReturn(null);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$result = $service->verifyEmail($customer);
// THEN
expect($result)->toBeFalse();
});
it('throws CrmServiceException from getCrmCustomerFrom', function (): void {
// GIVEN
$guard = Mockery::mock(StatefulGuard::class);
$crmService = Mockery::mock(CrmService::class);
$shopperService = Mockery::mock(ShopperService::class);
$customer = new Customer();
$hashcode = new CrmHashcode(Uuid::uuid4());
$customer->hashcode = $hashcode;
app()->instance(ExceptionHandler::class, Mockery::mock(ExceptionHandler::class)->shouldIgnoreMissing());
$exception = new CrmServiceException('Crm Error');
$crmService->shouldReceive('getCustomerFromHashCode')->with($customer->hashcode)->andReturn($exception);
$service = new AppCustomerAuthService($guard, $crmService, $shopperService);
// WHEN
$action = fn () => $service->hasVerifiedEmail($customer);
// THEN
expect($action)->toThrow(CrmServiceException::class, 'Crm Error');
});
});