innhold/tests/Unit/PetitionMapTest.php

135 lines
5 KiB
PHP
Raw Normal View History

<?php
// petition-map.php defines cache-path constants and functions.
// petitionMapBuildData() takes an explicit $csvPath so it can be tested
// with temp files; the cache constants are not touched by these tests.
//
// Context is already stubbed in PetitionFormTest.php (loaded first alphabetically),
// so we do not redeclare it here.
require_once CUSTOM_DIR . '/plugins/page/petition-map.php';
// CSV header row shared across tests
const PETITION_MAP_CSV_HEADER = ['timestamp', 'email', 'firstname', 'surname', 'region', 'display', 'status', 'token', 'token_created', 'ip_hash'];
/**
* Write rows to a temp file and return its path.
* The caller is responsible for unlinking it.
*/
function mapTestCsv(array $rows): string
{
$path = tempnam(sys_get_temp_dir(), 'map_test_');
$fp = fopen($path, 'w');
foreach ($rows as $row) {
fputcsv($fp, $row, ',', '"', '');
}
fclose($fp);
return $path;
}
// --- petitionMapBuildData: missing / empty file ---
it('returns empty data when CSV does not exist', function () {
$result = petitionMapBuildData('/tmp/nonexistent-petition-map-test.csv');
expect($result['total'])->toBe(0);
expect($result)->toHaveKey('generated');
});
it('returns zero total for a CSV with only pending signatures', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'a@b.com', 'Ola', 'Hansen', 'oslo', 'semi', 'pending', 'tok1', time(), 'hash1'],
]);
expect(petitionMapBuildData($path)['total'])->toBe(0);
unlink($path);
});
it('returns zero total for a CSV with only the header', function () {
$path = mapTestCsv([PETITION_MAP_CSV_HEADER]);
expect(petitionMapBuildData($path)['total'])->toBe(0);
unlink($path);
});
// --- petitionMapBuildData: counting confirmed signatures ---
it('counts confirmed signatures and groups them by region', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'a@b.com', 'Kari', 'Hansen', 'oslo', 'semi', 'confirmed', 't1', time(), 'h1'],
[time(), 'b@b.com', 'Ola', 'Nilsen', 'oslo', 'semi', 'confirmed', 't2', time(), 'h2'],
[time(), 'c@b.com', 'Per', 'Olsen', 'bergen', 'semi', 'confirmed', 't3', time(), 'h3'],
]);
$result = petitionMapBuildData($path);
expect($result['total'])->toBe(3);
expect($result['regions']['oslo']['count'])->toBe(2);
expect($result['regions']['bergen']['count'])->toBe(1);
unlink($path);
});
it('ignores non-confirmed rows (pending, deleted, etc.)', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'a@b.com', 'Kari', 'Hansen', 'oslo', 'semi', 'confirmed', 't1', time(), 'h1'],
[time(), 'b@b.com', 'Ola', 'Nilsen', 'oslo', 'semi', 'pending', 't2', time(), 'h2'],
[time(), 'c@b.com', 'Per', 'Olsen', 'oslo', 'semi', 'deleted', 't3', time(), 'h3'],
]);
$result = petitionMapBuildData($path);
expect($result['total'])->toBe(1);
unlink($path);
});
it('skips confirmed entries that have no region', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'a@b.com', 'Kari', 'Hansen', '', 'semi', 'confirmed', 't1', time(), 'h1'],
]);
expect(petitionMapBuildData($path)['total'])->toBe(0);
unlink($path);
});
// --- petitionMapBuildData: name handling ---
it('uses only the first word of the firstname', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'a@b.com', 'Kari Marte', 'Hansen', 'oslo', 'semi', 'confirmed', 't1', time(), 'h1'],
]);
$signer = petitionMapBuildData($path)['regions']['oslo']['signers'][0];
expect($signer['n'])->toBe('Kari');
unlink($path);
});
it('sets name to null and anonymous flag true for anonymous display', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'a@b.com', 'Kari', 'Hansen', 'oslo', 'anonymous', 'confirmed', 't1', time(), 'h1'],
]);
$signer = petitionMapBuildData($path)['regions']['oslo']['signers'][0];
expect($signer['n'])->toBeNull();
expect($signer['a'])->toBeTrue();
unlink($path);
});
it('sets anonymous flag false for non-anonymous display', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'a@b.com', 'Lars', 'Berg', 'oslo', 'semi', 'confirmed', 't1', time(), 'h1'],
]);
$signer = petitionMapBuildData($path)['regions']['oslo']['signers'][0];
expect($signer['a'])->toBeFalse();
unlink($path);
});
it('does not include emails, surnames, tokens, or ip_hashes in the output', function () {
$path = mapTestCsv([
PETITION_MAP_CSV_HEADER,
[time(), 'secret@b.com', 'Lars', 'SecretSurname', 'oslo', 'semi', 'confirmed', 'secret-token', time(), 'secret-hash'],
]);
$result = petitionMapBuildData($path);
$json = json_encode($result);
expect($json)->not->toContain('secret@b.com');
expect($json)->not->toContain('SecretSurname');
expect($json)->not->toContain('secret-token');
expect($json)->not->toContain('secret-hash');
unlink($path);
});