Add comprehensive test coverage for core site features (content, navigation, language, FAQ, news, petition, newsletter) using Pest browser tests and unit tests for custom plugins. Includes test infrastructure (Containerfile.test, compose.test.yaml), test documentation, and test files covering petition form logic, CSV handling, translation, date formatting, rate limiting, and map data building.
60 lines
2.2 KiB
PHP
60 lines
2.2 KiB
PHP
<?php
|
|
|
|
// Stubs for framework classes used by petition-form.php
|
|
class Context {}
|
|
class Hook { const TEMPLATE_VARS = 'template_vars'; }
|
|
class Hooks { public static function add(string $hook, callable $fn): void {} }
|
|
|
|
// petition-form.php calls session_start() at load time — stub $_SESSION and $_SERVER first
|
|
$_SESSION = [];
|
|
$_SERVER['REMOTE_ADDR'] ??= '127.0.0.1';
|
|
$_SERVER['HTTP_HOST'] ??= 'localhost';
|
|
|
|
require_once CUSTOM_DIR . '/plugins/page/petition-form.php';
|
|
|
|
// --- petitionSanitizeCSV ---
|
|
|
|
it('leaves safe values unchanged', function () {
|
|
expect(petitionSanitizeCSV('John Doe'))->toBe('John Doe');
|
|
expect(petitionSanitizeCSV('john@example.com'))->toBe('john@example.com');
|
|
expect(petitionSanitizeCSV(''))->toBe('');
|
|
});
|
|
|
|
it('prefixes formula-starting characters to prevent CSV injection', function () {
|
|
expect(petitionSanitizeCSV('=SUM(A1)'))->toBe("'=SUM(A1)");
|
|
expect(petitionSanitizeCSV('+evil'))->toBe("'+evil");
|
|
expect(petitionSanitizeCSV('-evil'))->toBe("'-evil");
|
|
expect(petitionSanitizeCSV('@evil'))->toBe("'@evil");
|
|
});
|
|
|
|
it('prefixes tab and newline characters', function () {
|
|
expect(petitionSanitizeCSV("\t data"))->toBe("'\t data");
|
|
expect(petitionSanitizeCSV("\r data"))->toBe("'\r data");
|
|
expect(petitionSanitizeCSV("\n data"))->toBe("'\n data");
|
|
});
|
|
|
|
it('only checks the first character', function () {
|
|
expect(petitionSanitizeCSV('safe=still safe'))->toBe('safe=still safe');
|
|
});
|
|
|
|
// --- petitionGetCsvPath ---
|
|
|
|
it('builds the correct CSV path for a valid petition ID', function () {
|
|
$path = petitionGetCsvPath('my-petition');
|
|
expect($path)->toEndWith('/data/petitions/my-petition.csv');
|
|
});
|
|
|
|
it('strips non-alphanumeric characters from petition ID', function () {
|
|
$path = petitionGetCsvPath('my petition!');
|
|
expect($path)->toEndWith('/data/petitions/mypetition.csv');
|
|
});
|
|
|
|
it('throws for an empty petition ID', function () {
|
|
petitionGetCsvPath('');
|
|
})->throws(Exception::class);
|
|
|
|
it('strips path traversal characters rather than throwing', function () {
|
|
// Dots and slashes are stripped by the regex, leaving a safe ID
|
|
$path = petitionGetCsvPath('../evil');
|
|
expect($path)->toEndWith('/data/petitions/evil.csv');
|
|
});
|