destroy(); // Сбрасываем синглтон сессии через рефлексию $ref = new \ReflectionClass(Session::class); $prop = $ref->getProperty('instances'); $prop->setAccessible(true); $prop->setValue(null, []); } public function testTokenIsNonEmptyHex(): void { $token = CSRF::token(); $this->assertNotEmpty($token); $this->assertSame(64, strlen($token)); // 32 байта → 64 hex-символа $this->assertMatchesRegularExpression('/^[0-9a-f]+$/', $token); } public function testTokenIsStable(): void { $this->assertSame(CSRF::token(), CSRF::token()); } public function testValidateAcceptsCorrectToken(): void { $token = CSRF::token(); $this->assertTrue(CSRF::validate($token)); } public function testValidateRejectsWrongToken(): void { CSRF::token(); $this->assertFalse(CSRF::validate('deadbeef')); } public function testValidateRejectsNullAndEmpty(): void { CSRF::token(); $this->assertFalse(CSRF::validate(null)); $this->assertFalse(CSRF::validate('')); } public function testValidateFailsWhenNoTokenInSession(): void { // Токен ещё не создавали — в сессии его нет. $this->assertFalse(CSRF::validate('whatever')); } public function testFieldContainsToken(): void { $field = CSRF::field(); $this->assertStringContainsString('name="' . CSRF::$key . '"', $field); $this->assertStringContainsString('value="' . CSRF::token() . '"', $field); } }