feat: refactored accommodation booking status model
This commit is contained in:
@@ -8,7 +8,7 @@ use App\Entity\Groups\AccommodationBooking;
|
||||
use App\Enum\Groups\AccommodationBookingStatus;
|
||||
use App\Form\Admin\Groups\AccommodationBookingCreateType;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Email;
|
||||
use Symfony\Component\Validator\Constraints\EmailValidator;
|
||||
@@ -17,76 +17,74 @@ use Symfony\Component\Validator\Validation;
|
||||
|
||||
class AccommodationBookingCreateTypeTest extends TestCase
|
||||
{
|
||||
public function testDraftsAreValidatedWithoutTheOfferGroup(): void
|
||||
public function testCreationIsAlwaysValidatedAsAScratchRecord(): void
|
||||
{
|
||||
self::assertSame(['Default'], $this->resolveValidationGroups(AccommodationBookingStatus::Draft));
|
||||
self::assertSame(['Default'], $this->resolveValidationGroups());
|
||||
}
|
||||
|
||||
public function testOffersAddTheOfferGroup(): void
|
||||
public function testTheStatusCannotBeChosenOnCreation(): void
|
||||
{
|
||||
self::assertSame(['Default', 'offer'], $this->resolveValidationGroups(AccommodationBookingStatus::Open));
|
||||
// A new record is always an Entwurf and only leaves that status through a named
|
||||
// action, so offering the choice here would let it start out somewhere it cannot
|
||||
// have arrived at legitimately.
|
||||
self::assertNotContains('status', $this->builtFieldNames());
|
||||
}
|
||||
|
||||
public function testDraftCanBeCreatedWithoutAnEmail(): void
|
||||
public function testANewBookingStartsAsADraft(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setStatus(AccommodationBookingStatus::Draft);
|
||||
self::assertTrue((new AccommodationBooking())->isDraft());
|
||||
}
|
||||
|
||||
$violations = $this->validate($booking, $this->resolveValidationGroups(AccommodationBookingStatus::Draft));
|
||||
public function testABookingCanBeCreatedWithoutAnEmail(): void
|
||||
{
|
||||
// The address is enforced when the booking is actually sent somewhere — see
|
||||
// SendOfferController and ConfirmController — not while it is still a scratch record.
|
||||
$violations = $this->validate(new AccommodationBooking(), $this->resolveValidationGroups());
|
||||
|
||||
self::assertCount(0, $violations);
|
||||
}
|
||||
|
||||
public function testOfferCannotBeCreatedWithoutAnEmail(): void
|
||||
public function testAMalformedEmailIsStillRejectedOnceTheBookingIsEdited(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setStatus(AccommodationBookingStatus::Open);
|
||||
$booking->setStatus(AccommodationBookingStatus::Requested);
|
||||
$booking->setEmail('not-an-address');
|
||||
|
||||
$violations = $this->validate($booking, $this->resolveValidationGroups(AccommodationBookingStatus::Open));
|
||||
$violations = $this->validate($booking, ['edit']);
|
||||
|
||||
$properties = array_map(static fn ($violation) => $violation->getPropertyPath(), iterator_to_array($violations));
|
||||
|
||||
self::assertSame(['email'], $properties, 'only the address is enforced here — the rest of the contact data belongs to the edit form');
|
||||
}
|
||||
|
||||
public function testOfferRejectsAMalformedEmail(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setStatus(AccommodationBookingStatus::Open);
|
||||
$booking->setEmail('not-an-address');
|
||||
|
||||
$violations = $this->validate($booking, $this->resolveValidationGroups(AccommodationBookingStatus::Open));
|
||||
|
||||
self::assertCount(1, $violations);
|
||||
self::assertSame('email', $violations[0]->getPropertyPath());
|
||||
}
|
||||
|
||||
public function testOfferWithAnEmailIsValid(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setStatus(AccommodationBookingStatus::Open);
|
||||
$booking->setEmail('[email protected]');
|
||||
|
||||
$violations = $this->validate($booking, $this->resolveValidationGroups(AccommodationBookingStatus::Open));
|
||||
|
||||
self::assertCount(0, $violations);
|
||||
self::assertContains('email', $properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveValidationGroups(AccommodationBookingStatus $status): array
|
||||
private function resolveValidationGroups(): array
|
||||
{
|
||||
$resolver = new OptionsResolver();
|
||||
(new AccommodationBookingCreateType())->configureOptions($resolver);
|
||||
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setStatus($status);
|
||||
return $resolver->resolve()['validation_groups'];
|
||||
}
|
||||
|
||||
$form = $this->createMock(FormInterface::class);
|
||||
$form->method('getData')->willReturn($booking);
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function builtFieldNames(): array
|
||||
{
|
||||
$names = [];
|
||||
|
||||
return ($resolver->resolve()['validation_groups'])($form);
|
||||
$builder = $this->createMock(FormBuilderInterface::class);
|
||||
$builder->method('add')->willReturnCallback(static function (string $name) use (&$names, $builder) {
|
||||
$names[] = $name;
|
||||
|
||||
return $builder;
|
||||
});
|
||||
|
||||
(new AccommodationBookingCreateType())->buildForm($builder, ['data' => new AccommodationBooking()]);
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace App\Tests\Form\Model\Filter;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Enum\Groups\AccommodationBookingOrigin;
|
||||
use App\Enum\Groups\AccommodationBookingStatus;
|
||||
use App\Enum\Groups\AccommodationBookingType;
|
||||
use App\Form\Model\Filter\AccommodationBookingFilterDto;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -17,9 +17,14 @@ class AccommodationBookingFilterDtoTest extends TestCase
|
||||
$filter = AccommodationBookingFilterDto::defaults(true, new User('[email protected]'));
|
||||
|
||||
self::assertSame(
|
||||
[AccommodationBookingStatus::Draft, AccommodationBookingStatus::Open, AccommodationBookingStatus::Received],
|
||||
[
|
||||
AccommodationBookingStatus::Draft,
|
||||
AccommodationBookingStatus::Requested,
|
||||
AccommodationBookingStatus::Open,
|
||||
AccommodationBookingStatus::Received,
|
||||
],
|
||||
$filter->status,
|
||||
'accepted and discarded bookings need no further work, so they stay out of the way',
|
||||
'confirmed and discarded bookings need no further work, so they stay out of the way',
|
||||
);
|
||||
self::assertSame((new \DateTimeImmutable('today'))->format('Y-m-d'), $filter->dateFrom?->format('Y-m-d'));
|
||||
self::assertNull($filter->managedBy, 'a group admin sees everybody’s bookings');
|
||||
@@ -83,11 +88,11 @@ class AccommodationBookingFilterDtoTest extends TestCase
|
||||
$filter->q = 'meier';
|
||||
$filter->dateFrom = new \DateTimeImmutable('2026-08-01');
|
||||
$filter->status = [AccommodationBookingStatus::Open, AccommodationBookingStatus::Confirmed];
|
||||
$filter->type = [AccommodationBookingType::Booking];
|
||||
$filter->origin = [AccommodationBookingOrigin::Direct];
|
||||
|
||||
self::assertSame(4, $filter->activeCount());
|
||||
self::assertSame('Offen, Bestätigt', $this->chipFor($filter, 'Status')?->value);
|
||||
self::assertSame('Buchung', $this->chipFor($filter, 'Art')?->value);
|
||||
self::assertSame('Direktbuchung', $this->chipFor($filter, 'Herkunft')?->value);
|
||||
self::assertSame('01.08.2026', $this->chipFor($filter, 'Aufenthalt ab')?->value);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user