classifier = new VoucherCodeClassifier(['lw0705' => '2027-04-30']); } /** * @return iterable */ public static function codes(): iterable { yield 'prefixed promo' => ['R-SOMMER26', VoucherCodeKind::Promo]; yield 'prefixed promo in lowercase' => ['r-sommer26', VoucherCodeKind::Promo]; yield 'legacy promo, matched case-insensitively' => ['Lw0705', VoucherCodeKind::Promo]; yield 'purchase code' => ['1F7V6PADRZ', VoucherCodeKind::Purchase]; yield 'purchase code in lowercase' => ['1f7v6padrz', VoucherCodeKind::Purchase]; yield 'surrounding whitespace' => [' 1F7V6PADRZ ', VoucherCodeKind::Purchase]; yield 'hyphen without the promo prefix' => ['X-1F7V6PADRZ', VoucherCodeKind::Malformed]; yield 'characters outside the code alphabet' => ['1F7V 6PADRZ', VoucherCodeKind::Malformed]; yield 'empty' => [' ', VoucherCodeKind::Malformed]; yield 'too long' => [str_repeat('A', 51), VoucherCodeKind::Malformed]; } #[DataProvider('codes')] public function testClassify(string $code, VoucherCodeKind $expected): void { self::assertSame($expected, $this->classifier->classify($code, new \DateTimeImmutable('2026-10-06'))); } public function testLegacyCodeIsRecognisedOnItsLastDay(): void { self::assertSame(VoucherCodeKind::Promo, $this->classifier->classify('LW0705', new \DateTimeImmutable('2027-04-30'))); } public function testLegacyCodeIsAPurchaseCodeOnceExpired(): void { self::assertSame(VoucherCodeKind::Purchase, $this->classifier->classify('LW0705', new \DateTimeImmutable('2027-05-01'))); } public function testNormalizeTrimsAndUppercases(): void { self::assertSame('R-SOMMER26', $this->classifier->normalize(' r-Sommer26 ')); } }