validate($this->createDto(), self::STEP_1)); } public function testTheBoundsAreInclusiveAndComeFromBusPro(): void { $dto = $this->createDto(); foreach ([10 => 0, 5000 => 0, 9 => 1, 5001 => 1] as $amount => $violations) { $dto->amount = $amount; $result = $this->validate($dto, self::STEP_1); self::assertCount($violations, $result, sprintf('amount %d', $amount)); if (1 === $violations) { self::assertSame('amount', $result->get(0)->getPropertyPath()); } } } public function testStep1RequiresDesignNamesAndValue(): void { $dto = $this->createDto(); $dto->template = null; $dto->from = ''; $dto->to = null; $dto->amount = null; self::assertSame( ['template', 'from', 'to', 'amount'], $this->propertyPaths($this->validate($dto, self::STEP_1)), ); } /** * The mandatory fields of the live voucher shop: no phone, no gender, no salutation. */ public function testStep2RequiresWhatTheLiveShopRequires(): void { $dto = new VoucherPurchaseDto(); $dto->address->country = null; self::assertEqualsCanonicalizing( ['lastName', 'firstName', 'address.street', 'address.postCode', 'address.city', 'address.country', 'email'], $this->propertyPaths($this->validate($dto, self::STEP_2)), ); } public function testACompleteBuyerPassesStep2(): void { self::assertCount(0, $this->validate($this->createDto(), self::STEP_2)); } public function testTheCountryDefaultsToGermany(): void { self::assertSame('D', (new VoucherPurchaseDto())->address->country); } public function testStep2RejectsAnInvalidEmailAndSalutation(): void { $dto = $this->createDto(); $dto->email = 'kein-mail'; $dto->salutation = 'Divers'; self::assertEqualsCanonicalizing(['email', 'salutation'], $this->propertyPaths($this->validate($dto, self::STEP_2))); } public function testStep3RequiresBothConfirmations(): void { $dto = $this->createDto(); self::assertSame(['termsAccepted', 'purchaseConfirmed'], $this->propertyPaths($this->validate($dto, self::STEP_3))); $dto->termsAccepted = true; $dto->purchaseConfirmed = true; self::assertCount(0, $this->validate($dto, self::STEP_3)); } public function testPrefillTakesTheLoginEmailAndKeepsAnUnknownSalutationOut(): void { $personalData = new PersonalData(); $personalData->name = 'Muster'; $personalData->firstName = 'Erika'; $personalData->salutation = 'Familie'; $personalData->address->street = ' Hauptstr. 1 '; $personalData->address->postCode = '12345'; $personalData->address->city = 'Musterstadt'; $personalData->address->country = 'A'; $personalData->communication->email = 'household@example.invalid'; $personalData->communication->mobile = '0170'; $dto = new VoucherPurchaseDto(); $dto->prefillBuyer($personalData, 'erika@example.invalid'); self::assertSame('Muster', $dto->lastName); self::assertSame('Erika', $dto->firstName); self::assertNull($dto->salutation); self::assertSame('Hauptstr. 1', $dto->address->street); self::assertSame('A', $dto->address->country); self::assertSame('erika@example.invalid', $dto->email); self::assertSame('0170', $dto->mobile); self::assertTrue($dto->hasBuyerData()); self::assertNotSame($personalData->address, $dto->address); } private function createDto(): VoucherPurchaseDto { $dto = new VoucherPurchaseDto(); $dto->minAmount = 10; $dto->maxAmount = 5000; $dto->template = new VoucherTemplate(3, 'K', 'Allgemein'); $dto->from = 'Oma'; $dto->to = 'Max'; $dto->amount = 111; $dto->lastName = 'Muster'; $dto->firstName = 'Erika'; $dto->address->street = 'Hauptstr. 1'; $dto->address->postCode = '12345'; $dto->address->city = 'Musterstadt'; $dto->email = 'erika@example.invalid'; return $dto; } /** * @param list $groups */ private function validate(VoucherPurchaseDto $dto, array $groups): ConstraintViolationListInterface { return Validation::createValidatorBuilder() ->enableAttributeMapping() ->getValidator() ->validate($dto, null, $groups); } /** * @return list */ private function propertyPaths(ConstraintViolationListInterface $violations): array { $paths = []; foreach ($violations as $violation) { $paths[] = $violation->getPropertyPath(); } return $paths; } }