assertStringNotContainsString('@', $result); $this->assertStringContainsString('@', $result); // decimal entity for @ } public function testEncodeOutputIsNumericEntities(): void { $result = EmailObfuscator::email('a@b.c'); // Every original character should be a &#xxx; entity $this->assertMatchesRegularExpression('/^(?:&#\d+;)+$/', $result); $this->assertNotEmpty($result); } // ── email() ─────────────────────────────────────────────────────────────── public function testEmailReturnsObfuscatedAddress(): void { $result = EmailObfuscator::email('hello@world.org'); $this->assertStringNotContainsString('hello', $result); $this->assertStringNotContainsString('@', $result); $this->assertStringContainsString('h', $result); // 'h' $this->assertStringContainsString('@', $result); // '@' } // ── mailto() ────────────────────────────────────────────────────────────── public function testMailtoBuildsCorrectHrefStructure(): void { $result = EmailObfuscator::mailto('x@y.com'); $this->assertStringStartsWith('mailto:', $result); $this->assertStringNotContainsString('@', $result); $this->assertStringContainsString('@', $result); } // ── emailText() ─────────────────────────────────────────────────────────── public function testEmailTextReplacesBareEmail(): void { $input = 'Contact xamxam@erg.be for help'; $result = EmailObfuscator::emailText($input); $this->assertStringNotContainsString('xamxam@erg.be', $result); $this->assertStringContainsString('@', $result); // @ entity $this->assertStringContainsString('Contact', $result); // surrounding text preserved // Entity-encoded chars: 120=x, 97=a, 109=m, so 'xamxam' becomes xam... $this->assertStringContainsString('x', $result); // 'x' $this->assertStringContainsString('a', $result); // 'a' $this->assertStringContainsString('m', $result); // 'm' } public function testEmailTextReplacesMultipleEmails(): void { $input = 'a@b.com and c@d.org'; $result = EmailObfuscator::emailText($input); $this->assertStringNotContainsString('@', $result); $this->assertStringContainsString('@', $result); // Should have two occurrences of the @ entity $this->assertEquals(2, substr_count($result, '@')); } // ── mailtoInText() ──────────────────────────────────────────────────────── public function testMailtoInTextReplacesMailtoLinks(): void { $input = 'contact'; $result = EmailObfuscator::mailtoInText($input); $this->assertStringNotContainsString('contact@example.com', $result); $this->assertStringContainsString('mailto:', $result); $this->assertStringContainsString('@', $result); } // ── obfuscateHtml() ─────────────────────────────────────────────────────── public function testObfuscateHtmlReplacesAnchorTag(): void { $input = 'contact@example.com'; $result = EmailObfuscator::obfuscateHtml($input); $this->assertStringNotContainsString('contact@example.com', $result); $this->assertStringContainsString('assertStringContainsString('href="mailto:', $result); // @ entity should appear twice (href + link text) $this->assertGreaterThanOrEqual(2, substr_count($result, '@')); } public function testObfuscateHtmlKeepsNonMailtoLinksUnchanged(): void { $input = 'ERG and x@y.z'; $result = EmailObfuscator::obfuscateHtml($input); $this->assertStringContainsString('https://erg.be', $result); $this->assertStringContainsString('ERG', $result); $this->assertStringNotContainsString('x@y.z', $result); } public function testObfuscateHtmlPreservesCustomLinkText(): void { // When the link text differs from the email, only the href is obfuscated $input = 'custom text'; $result = EmailObfuscator::obfuscateHtml($input); $this->assertStringNotContainsString('foobar@test.com', $result); $this->assertStringContainsString('@', $result); // in href $this->assertStringContainsString('custom text', $result); // link text unchanged } // ── Edge cases ──────────────────────────────────────────────────────────── public function testEmptyStringReturnsEmpty(): void { $this->assertSame('', EmailObfuscator::email('')); } public function testStringWithNoEmailsIsUnchanged(): void { $input = 'Hello, world! No emails here.'; $this->assertSame($input, EmailObfuscator::emailText($input)); } public function testAlreadyObfuscatedContentIsNotDoubleEncoded(): void { // Already entity-encoded email — no literal '@' to match $input = 'Contact xamxam@erg.be here'; $result = EmailObfuscator::emailText($input); // Should be unchanged (regex won't match entity-encoded @) $this->assertSame($input, $result); } public function testMultipleEmailsInOneString(): void { $input = 'Mail to a@b.com or c@d.org pls'; $result = EmailObfuscator::emailText($input); $this->assertStringNotContainsString('a@b.com', $result); $this->assertStringNotContainsString('c@d.org', $result); // Two @ entities $this->assertEquals(2, substr_count($result, '@')); } public function testEmailWithPlusSign(): void { $result = EmailObfuscator::email('user+tag@domain.com'); $this->assertStringContainsString('+', $result); // '+' $this->assertStringContainsString('@', $result); // '@' } }