value); } #[Test] public function constructNormalizesToUppercase(): void { $code = new SubjectCode('math'); self::assertSame('MATH', $code->value); } #[Test] public function constructTrimsWhitespace(): void { $code = new SubjectCode(' MATH '); self::assertSame('MATH', $code->value); } #[Test] public function constructWithMinimumLength(): void { $code = new SubjectCode('FR'); self::assertSame('FR', $code->value); } #[Test] public function constructWithMaximumLength(): void { $code = new SubjectCode('HISTGEO123'); self::assertSame('HISTGEO123', $code->value); } #[Test] public function constructWithDigits(): void { $code = new SubjectCode('EPS1'); self::assertSame('EPS1', $code->value); } #[Test] #[DataProvider('invalidCodesProvider')] public function constructThrowsExceptionForInvalidCode(string $invalidCode): void { $this->expectException(SubjectCodeInvalideException::class); new SubjectCode($invalidCode); } /** * @return iterable */ public static function invalidCodesProvider(): iterable { yield 'empty string' => ['']; yield 'single character' => ['M']; yield 'whitespace only' => [' ']; yield 'too long' => ['MATHEMATICS']; // 11 chars yield 'with special characters' => ['MATH-1']; yield 'with spaces' => ['MA TH']; yield 'lowercase with special' => ['math!']; } #[Test] public function equalsReturnsTrueForSameValue(): void { $code1 = new SubjectCode('MATH'); $code2 = new SubjectCode('MATH'); self::assertTrue($code1->equals($code2)); } #[Test] public function equalsReturnsTrueForDifferentCase(): void { $code1 = new SubjectCode('MATH'); $code2 = new SubjectCode('math'); self::assertTrue($code1->equals($code2)); } #[Test] public function equalsReturnsFalseForDifferentValue(): void { $code1 = new SubjectCode('MATH'); $code2 = new SubjectCode('FR'); self::assertFalse($code1->equals($code2)); } #[Test] public function toStringReturnsValue(): void { $code = new SubjectCode('MATH'); self::assertSame('MATH', (string) $code); } }