mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Add PHPUnit setup (Phase 0) and pure-logic tests (Phase 1): Crypto, EmailObfuscator, SystemController helpers, StudentEmail, TfeController OG tags
This commit is contained in:
166
tests/phpunit/EmailObfuscatorTest.php
Normal file
166
tests/phpunit/EmailObfuscatorTest.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* EmailObfuscatorTest — Pure logic tests for EmailObfuscator.
|
||||
*/
|
||||
class EmailObfuscatorTest extends TestCase
|
||||
{
|
||||
// ── encode() ──────────────────────────────────────────────────────────────
|
||||
|
||||
public function testEncodeContainsNoAtSign(): void
|
||||
{
|
||||
$result = EmailObfuscator::email('test@example.com');
|
||||
|
||||
$this->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 = '<a href="mailto:contact@example.com">contact</a>';
|
||||
$result = EmailObfuscator::mailtoInText($input);
|
||||
|
||||
$this->assertStringNotContainsString('contact@example.com', $result);
|
||||
$this->assertStringContainsString('mailto:', $result);
|
||||
$this->assertStringContainsString('@', $result);
|
||||
}
|
||||
|
||||
// ── obfuscateHtml() ───────────────────────────────────────────────────────
|
||||
|
||||
public function testObfuscateHtmlReplacesAnchorTag(): void
|
||||
{
|
||||
$input = '<a href="mailto:contact@example.com">contact@example.com</a>';
|
||||
$result = EmailObfuscator::obfuscateHtml($input);
|
||||
|
||||
$this->assertStringNotContainsString('contact@example.com', $result);
|
||||
$this->assertStringContainsString('<a ', $result);
|
||||
$this->assertStringContainsString('href="mailto:', $result);
|
||||
// @ entity should appear twice (href + link text)
|
||||
$this->assertGreaterThanOrEqual(2, substr_count($result, '@'));
|
||||
}
|
||||
|
||||
public function testObfuscateHtmlKeepsNonMailtoLinksUnchanged(): void
|
||||
{
|
||||
$input = '<a href="https://erg.be">ERG</a> and <a href="mailto:x@y.z">x@y.z</a>';
|
||||
$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 = '<a href="mailto:foobar@test.com">custom text</a>';
|
||||
$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); // '@'
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user