163 lines
6 KiB
PHP
163 lines
6 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
// PetitionFormTest.php (which loads first alphabetically) already required
|
||
|
|
// petition-form.php and defined Context / Hook / Hooks stubs.
|
||
|
|
// This file only adds tests — no re-requires or re-declarations needed.
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Build a minimal Context mock that supports get('translations') and get('currentLang').
|
||
|
|
*/
|
||
|
|
function mockContext(array $translations = [], string $lang = 'no'): object
|
||
|
|
{
|
||
|
|
return new class($translations, $lang) extends Context {
|
||
|
|
public function __construct(
|
||
|
|
private array $translations,
|
||
|
|
private string $lang
|
||
|
|
) {}
|
||
|
|
|
||
|
|
public function get(string $key, mixed $default = null): mixed
|
||
|
|
{
|
||
|
|
return match ($key) {
|
||
|
|
'translations' => $this->translations,
|
||
|
|
'currentLang' => $this->lang,
|
||
|
|
default => $default,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- petitionT ---
|
||
|
|
|
||
|
|
it('returns the key when no translation is found', function () {
|
||
|
|
$ctx = mockContext([]);
|
||
|
|
expect(petitionT($ctx, 'petition', 'missing_key'))->toBe('missing_key');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('returns the translated string when found', function () {
|
||
|
|
$ctx = mockContext(['petition.greeting' => 'Hei!']);
|
||
|
|
expect(petitionT($ctx, 'petition', 'greeting'))->toBe('Hei!');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies placeholder replacements', function () {
|
||
|
|
$ctx = mockContext(['petition.email_greeting' => 'Hei {name}!']);
|
||
|
|
expect(petitionT($ctx, 'petition', 'email_greeting', ['name' => 'Kari']))->toBe('Hei Kari!');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies multiple replacements in a single string', function () {
|
||
|
|
$ctx = mockContext(['petition.thanks' => 'Takk {name} for {title}']);
|
||
|
|
$result = petitionT($ctx, 'petition', 'thanks', ['name' => 'Ola', 'title' => 'kampanjen']);
|
||
|
|
expect($result)->toBe('Takk Ola for kampanjen');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('uses the section as part of the translation key', function () {
|
||
|
|
$ctx = mockContext(['regions.oslo' => 'Oslo', 'petition.oslo' => 'Wrong']);
|
||
|
|
expect(petitionT($ctx, 'regions', 'oslo'))->toBe('Oslo');
|
||
|
|
});
|
||
|
|
|
||
|
|
// --- petitionGetIdFromPath ---
|
||
|
|
|
||
|
|
it('returns the basename of a path as the petition ID', function () {
|
||
|
|
expect(petitionGetIdFromPath('/content/underskriftskampanje/my-petition'))->toBe('my-petition');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('strips a leading numeric prefix from the folder name', function () {
|
||
|
|
expect(petitionGetIdFromPath('/content/01-my-petition'))->toBe('my-petition');
|
||
|
|
expect(petitionGetIdFromPath('/content/001-my-petition'))->toBe('my-petition');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('leaves non-prefixed names intact', function () {
|
||
|
|
expect(petitionGetIdFromPath('/content/medisinsk-cannabis'))->toBe('medisinsk-cannabis');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('returns null when the basename is empty', function () {
|
||
|
|
expect(petitionGetIdFromPath('/'))->toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
// --- petitionFormatDate ---
|
||
|
|
|
||
|
|
it('formats a date in Norwegian by default', function () {
|
||
|
|
date_default_timezone_set('UTC');
|
||
|
|
$ctx = mockContext([], 'no');
|
||
|
|
// 2024-03-15 10:05:00 UTC
|
||
|
|
$ts = mktime(10, 5, 0, 3, 15, 2024);
|
||
|
|
expect(petitionFormatDate($ts, $ctx))->toBe('15. mars 2024, 10:05');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('formats a date in English when lang is en', function () {
|
||
|
|
date_default_timezone_set('UTC');
|
||
|
|
$ctx = mockContext([], 'en');
|
||
|
|
$ts = mktime(10, 5, 0, 3, 15, 2024);
|
||
|
|
expect(petitionFormatDate($ts, $ctx))->toBe('March 15, 2024, 10:05');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('uses Norwegian month names for an unknown language', function () {
|
||
|
|
date_default_timezone_set('UTC');
|
||
|
|
$ctx = mockContext([], 'fr');
|
||
|
|
$ts = mktime(0, 0, 0, 1, 1, 2024);
|
||
|
|
$result = petitionFormatDate($ts, $ctx);
|
||
|
|
expect($result)->toContain('januar');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('uses the correct Norwegian month names', function () {
|
||
|
|
date_default_timezone_set('UTC');
|
||
|
|
$ctx = mockContext([], 'no');
|
||
|
|
$months = ['januar','februar','mars','april','mai','juni',
|
||
|
|
'juli','august','september','oktober','november','desember'];
|
||
|
|
foreach ($months as $i => $name) {
|
||
|
|
$ts = mktime(0, 0, 0, $i + 1, 1, 2024);
|
||
|
|
expect(petitionFormatDate($ts, $ctx))->toContain($name);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// --- petitionFormatSignature ---
|
||
|
|
|
||
|
|
it('shows only first name and region for semi display', function () {
|
||
|
|
$ctx = mockContext([
|
||
|
|
'petition.from_region' => 'fra',
|
||
|
|
'regions.oslo' => 'Oslo',
|
||
|
|
]);
|
||
|
|
$sig = ['firstname' => 'Kari', 'surname' => 'Hansen', 'region' => 'oslo', 'display' => 'semi'];
|
||
|
|
$result = petitionFormatSignature($sig, $ctx);
|
||
|
|
expect($result)->toBe('Kari fra Oslo');
|
||
|
|
expect($result)->not->toContain('Hansen');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('shows full name and region for full display', function () {
|
||
|
|
$ctx = mockContext([
|
||
|
|
'petition.from_region' => 'fra',
|
||
|
|
'regions.oslo' => 'Oslo',
|
||
|
|
]);
|
||
|
|
$sig = ['firstname' => 'Kari', 'surname' => 'Hansen', 'region' => 'oslo', 'display' => 'full'];
|
||
|
|
expect(petitionFormatSignature($sig, $ctx))->toBe('Kari Hansen fra Oslo');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('shows anonymous label for anonymous display', function () {
|
||
|
|
$ctx = mockContext([
|
||
|
|
'petition.from_region' => 'fra',
|
||
|
|
'petition.anonymous_name' => 'Anonym',
|
||
|
|
'regions.oslo' => 'Oslo',
|
||
|
|
]);
|
||
|
|
$sig = ['firstname' => 'Kari', 'surname' => 'Hansen', 'region' => 'oslo', 'display' => 'anonymous'];
|
||
|
|
$result = petitionFormatSignature($sig, $ctx);
|
||
|
|
expect($result)->toContain('Anonym');
|
||
|
|
expect($result)->not->toContain('Kari');
|
||
|
|
expect($result)->not->toContain('Hansen');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('HTML-escapes names in full display mode', function () {
|
||
|
|
$ctx = mockContext([
|
||
|
|
'petition.from_region' => 'fra',
|
||
|
|
'regions.oslo' => 'Oslo',
|
||
|
|
]);
|
||
|
|
$sig = ['firstname' => '<b>Kari</b>', 'surname' => '<script>', 'region' => 'oslo', 'display' => 'full'];
|
||
|
|
$result = petitionFormatSignature($sig, $ctx);
|
||
|
|
expect($result)->toContain('<b>');
|
||
|
|
expect($result)->not->toContain('<b>');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('falls back to the region key when no translation exists', function () {
|
||
|
|
$ctx = mockContext(['petition.from_region' => 'fra']);
|
||
|
|
$sig = ['firstname' => 'Ola', 'surname' => 'Nilsen', 'region' => 'trondelag', 'display' => 'semi'];
|
||
|
|
expect(petitionFormatSignature($sig, $ctx))->toContain('trondelag');
|
||
|
|
});
|