Add PHP unit tests and page tests.

Run "composer install", then "composer test".
This commit is contained in:
tim
2026-09-26 03:48:09 +02:00
parent 848c447c5b
commit ed959888b4
42 changed files with 5522 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
<?php
/*
* A sendmail for the tests: PHP's mail() runs it through sendmail_path.
* It appends the message to the file in MAIL_LOG, one JSON line each.
*/
$message = stream_get_contents(STDIN);
file_put_contents(getenv('MAIL_LOG'), json_encode(array('args' => array_slice($argv, 1), 'message' => $message),
JSON_INVALID_UTF8_SUBSTITUTE) . "\n", FILE_APPEND | LOCK_EX);
+60
View File
@@ -0,0 +1,60 @@
<?php
/*
* The router for the page tests, which run the site on PHP's built-in
* web server (see tests/php/Support/PageTestCase.php). For each request
* it sets up the test environment, loads the fake tables from the state
* directory in XXX_PAGE_STATE, and runs the page as Apache does, with
* "/article" for article.php. The tables are saved when the page ends.
*
* The built-in server has no TLS, so a request counts as HTTPS unless it
* has an X-Test-Plain header. The captcha passes when its response is
* "pass".
*/
require dirname(__DIR__) . '/environment.php';
use Xxx\Tests\Support\FakeDb;
use Xxx\Tests\Support\FakeRecaptcha;
use Xxx\Tests\Support\SiteData;
// The page file for this request, TRUE when the router answered (404), or
// FALSE for a static file, which the server sends itself
function xxx_page_route() {
$path = rawurldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
$file = realpath(XXX_ROOT . $path);
if ($file !== FALSE && is_dir($file))
$file = realpath($file . '/index.php');
else if ($file === FALSE)
$file = realpath(XXX_ROOT . rtrim($path, '/') . '.php');
if ($file === FALSE || !str_starts_with($file, XXX_ROOT . '/') || str_starts_with($file, XXX_ROOT . '/tests/')) {
http_response_code(404);
return TRUE;
}
if (!str_ends_with($file, '.php'))
return FALSE;
$state = getenv('XXX_PAGE_STATE');
$saved = unserialize(file_get_contents("$state/tables.ser"));
FakeDb::$logFile = "$state/queries.jsonl";
SiteData::install($saved['tables']);
SiteData::$passwordLength = $saved['passwordLength'];
register_shutdown_function(function () use ($state) {
file_put_contents("$state/tables.ser", serialize(array('tables' => SiteData::$tables,
'passwordLength' => SiteData::$passwordLength)), LOCK_EX);
});
FakeRecaptcha::install(function ($post) {
return json_encode(array('success' => ($post['response'] ?? '') === 'pass'));
});
if (!isset($_SERVER['HTTP_X_TEST_PLAIN']))
$_SERVER['HTTPS'] = 'on';
$_SERVER['SERVER_NAME'] = 'xxx.org.za';
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_TEST_ADDRESS'] ?? '192.0.2.1';
$_SERVER['SCRIPT_FILENAME'] = $file;
$_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'] = substr($file, strlen(XXX_ROOT));
chdir(dirname($file));
return $file;
}
if (!is_string($xxx_page = xxx_page_route()))
return $xxx_page;
require $xxx_page;
+10
View File
@@ -0,0 +1,10 @@
# Configuration for the tests (tests/php/bootstrap.php points XXX_ENV_FILE here)
DB_HOST=db.test
DB_USER=test-user
DB_PASS=test-pass
DB_NAME=test-db
RECAPTCHA_SITE_KEY=test-site-key
RECAPTCHA_SECRET=test-secret
GOOGLE_ANALYTICS_ID=
UPLOAD_DIR=
DISPLAY_ERRORS=