Add PHP unit tests and page tests.
Run "composer install", then "composer test".
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
namespace Xxx\Tests\Unit;
|
||||
|
||||
use Xxx\Tests\Support\FakeRecaptcha;
|
||||
use Xxx\Tests\Support\TestCase;
|
||||
|
||||
// captcha.lib.php. FakeRecaptcha answers in place of Google.
|
||||
class CaptchaTest extends TestCase {
|
||||
private function disable(): void {
|
||||
$this->setEnv('RECAPTCHA_SITE_KEY', '');
|
||||
}
|
||||
|
||||
public function testEnabledWithASiteKey(): void {
|
||||
$this->assertTrue(captcha_enabled());
|
||||
$this->disable();
|
||||
$this->assertFalse(captcha_enabled());
|
||||
}
|
||||
|
||||
public function testScriptAndWidget(): void {
|
||||
$this->assertSame('<script src="https://www.google.com/recaptcha/api.js" async defer></script>', captcha_script());
|
||||
$this->assertSame('<div class="g-recaptcha" data-sitekey="test-site-key"></div>', captcha_widget());
|
||||
}
|
||||
|
||||
public function testWidgetEscapesTheSiteKey(): void {
|
||||
$this->setEnv('RECAPTCHA_SITE_KEY', '"><script>x</script>');
|
||||
$this->assertSame('<div class="g-recaptcha" data-sitekey=""><script>x</script>"></div>', captcha_widget());
|
||||
}
|
||||
|
||||
public function testNothingFromGoogleWithoutASiteKey(): void {
|
||||
$this->disable();
|
||||
$this->assertSame('', captcha_script());
|
||||
$this->assertSame('', captcha_widget());
|
||||
}
|
||||
|
||||
public function testEveryCheckPassesWithoutASiteKey(): void {
|
||||
$this->disable();
|
||||
FakeRecaptcha::install(FALSE);
|
||||
$this->assertTrue(captcha_verify_response());
|
||||
$this->assertTrue(captcha_check());
|
||||
$this->assertSame(array(), FakeRecaptcha::$requests);
|
||||
}
|
||||
|
||||
public function testNoResponseFailsWithoutAskingGoogle(): void {
|
||||
FakeRecaptcha::install();
|
||||
$this->assertFalse(captcha_verify_response());
|
||||
$this->request(array(), array('g-recaptcha-response' => ''));
|
||||
$this->assertFalse(captcha_verify_response());
|
||||
$this->request(array(), array('g-recaptcha-response' => array('x')));
|
||||
$this->assertFalse(captcha_verify_response());
|
||||
$this->assertSame(array(), FakeRecaptcha::$requests);
|
||||
}
|
||||
|
||||
public function testSolvedCaptchaPasses(): void {
|
||||
FakeRecaptcha::install('{"success": true, "hostname": "xxx.org.za"}');
|
||||
$_SERVER['REMOTE_ADDR'] = '198.51.100.7';
|
||||
$this->request(array(), array('g-recaptcha-response' => 'token-from-widget'));
|
||||
$this->assertTrue(captcha_verify_response());
|
||||
}
|
||||
|
||||
// The secret goes in the POST body, never in the URL
|
||||
public function testRequestSendsTheSecretByPost(): void {
|
||||
FakeRecaptcha::install();
|
||||
$_SERVER['REMOTE_ADDR'] = '198.51.100.7';
|
||||
$this->request(array(), array('g-recaptcha-response' => 'token-from-widget'));
|
||||
captcha_verify_response();
|
||||
$this->assertCount(1, FakeRecaptcha::$requests);
|
||||
$request = FakeRecaptcha::$requests[0];
|
||||
$this->assertSame('https://www.google.com/recaptcha/api/siteverify', $request['url']);
|
||||
$this->assertSame('POST', $request['http']['method']);
|
||||
$this->assertSame(array('secret' => 'test-secret', 'response' => 'token-from-widget', 'remoteip' => '198.51.100.7'), $request['post']);
|
||||
$this->assertStringContainsString('application/x-www-form-urlencoded', $request['http']['header']);
|
||||
$this->assertSame(10, $request['http']['timeout']);
|
||||
}
|
||||
|
||||
public function testUnsolvedCaptchaFails(): void {
|
||||
FakeRecaptcha::install('{"success": false, "error-codes": ["invalid-input-response"]}');
|
||||
$this->request(array(), array('g-recaptcha-response' => 'bad'));
|
||||
$this->assertFalse(captcha_verify_response());
|
||||
}
|
||||
|
||||
public function testOddRepliesFail(): void {
|
||||
$this->request(array(), array('g-recaptcha-response' => 'token'));
|
||||
foreach (array('', 'not json', '[]', '"success"', '{"success": 0}', '{}') as $reply) {
|
||||
FakeRecaptcha::install($reply);
|
||||
$this->assertFalse(captcha_verify_response(), $reply);
|
||||
}
|
||||
}
|
||||
|
||||
public function testUnreachableServerFailsAndIsLogged(): void {
|
||||
FakeRecaptcha::install(FALSE);
|
||||
$this->request(array(), array('g-recaptcha-response' => 'token'));
|
||||
$this->assertFalse(captcha_verify_response());
|
||||
$this->assertStringContainsString('xxx: could not reach the reCAPTCHA server', $this->loggedErrors());
|
||||
}
|
||||
|
||||
public function testMissingSecretFailsAndIsLogged(): void {
|
||||
$this->setEnv('RECAPTCHA_SECRET', '');
|
||||
FakeRecaptcha::install();
|
||||
$this->request(array(), array('g-recaptcha-response' => 'token'));
|
||||
$this->assertFalse(captcha_verify_response());
|
||||
$this->assertSame(array(), FakeRecaptcha::$requests);
|
||||
$this->assertStringContainsString('RECAPTCHA_SECRET is not set', $this->loggedErrors());
|
||||
}
|
||||
|
||||
public function testPassLastsHalfAnHour(): void {
|
||||
$this->assertFalse(captcha_passed());
|
||||
$_SESSION['captcha_ok'] = time() - CAPTCHA_PASS_SECONDS + 5;
|
||||
$this->assertTrue(captcha_passed());
|
||||
$_SESSION['captcha_ok'] = time() - CAPTCHA_PASS_SECONDS - 1;
|
||||
$this->assertFalse(captcha_passed());
|
||||
}
|
||||
|
||||
public function testCheckRemembersASolvedCaptcha(): void {
|
||||
FakeRecaptcha::install();
|
||||
$this->request(array(), array('g-recaptcha-response' => 'token'));
|
||||
$this->assertTrue(captcha_check());
|
||||
$this->assertEqualsWithDelta(time(), $_SESSION['captcha_ok'], 2);
|
||||
// The next check needs no new answer from Google
|
||||
FakeRecaptcha::install(FALSE);
|
||||
$this->request();
|
||||
$this->assertTrue(captcha_check());
|
||||
$this->assertSame(array(), FakeRecaptcha::$requests);
|
||||
}
|
||||
|
||||
public function testCheckFailsWithoutAPassOrAnAnswer(): void {
|
||||
FakeRecaptcha::install();
|
||||
$this->assertFalse(captcha_check());
|
||||
$this->assertArrayNotHasKey('captcha_ok', $_SESSION);
|
||||
}
|
||||
|
||||
public function testUsedEndsThePass(): void {
|
||||
$_SESSION['captcha_ok'] = time();
|
||||
captcha_used();
|
||||
$this->assertFalse(captcha_passed());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user