setEnv('RECAPTCHA_SITE_KEY', ''); } public function testEnabledWithASiteKey(): void { $this->assertTrue(captcha_enabled()); $this->disable(); $this->assertFalse(captcha_enabled()); } public function testScriptAndWidget(): void { $this->assertSame('', captcha_script()); $this->assertSame('
', captcha_widget()); } public function testWidgetEscapesTheSiteKey(): void { $this->setEnv('RECAPTCHA_SITE_KEY', '">'); $this->assertSame('
', 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()); } }