Add browser and unit test suite with Pest + Playwright
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.
This commit is contained in:
parent
0b61643ec5
commit
b8e6d2537d
20 changed files with 1331 additions and 33 deletions
60
tests/Unit/PetitionFormTest.php
Normal file
60
tests/Unit/PetitionFormTest.php
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<?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');
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue