added unit tests

This commit is contained in:
2026-06-04 21:40:59 +02:00
parent d80a8de559
commit 48a619ee4b
64 changed files with 3807 additions and 33 deletions

View File

@ -0,0 +1,233 @@
<?php
declare(strict_types=1);
namespace Tests\Support;
use PDO;
/**
* Seeds a minimal org graph for integration tests.
*/
final class DatabaseSeeder
{
public const PASSWORD = 'TestPass1!';
public const ADMIN_USERNAME = 'test_admin';
public const SUPERVISOR_USERNAME = 'test_supervisor';
public const COACH_USERNAME = 'test_coach';
public static function seed(PDO $pdo): FixtureIds
{
$now = time();
$passwordHash = password_hash(self::PASSWORD, PASSWORD_DEFAULT);
// Stable IDs so fixture metadata always matches seeded rows.
$adminId = 'admin-test';
$adminUserId = 'u-admin-test';
$supervisorId = 'sv-test';
$supervisorUserId = 'u-sv-test';
$coachId = 'coach-test';
$coachUserId = 'u-coach-test';
$qnId = 'qn-test';
$questionId = $qnId . '__q1';
$optionId = 'opt-test-q1-yes';
$freeTextQuestionId = $qnId . '__q2';
$glassQuestionId = $qnId . '__q3';
$glassSymptomKey = 'pain';
$multiQuestionId = $qnId . '__q4';
$multiOptionAId = 'opt-test-q4-a';
$multiOptionBId = 'opt-test-q4-b';
$draftQuestionnaireId = 'qn-draft-test';
$pdo->prepare('INSERT INTO admin (adminID, username, location) VALUES (:id, :u, :loc)')
->execute([':id' => $adminId, ':u' => self::ADMIN_USERNAME, ':loc' => 'HQ']);
$pdo->prepare(
'INSERT INTO users (userID, username, passwordHash, role, entityID, mustChangePassword, createdAt)
VALUES (:uid, :u, :h, :role, :eid, 0, :now)'
)->execute([
':uid' => $adminUserId,
':u' => self::ADMIN_USERNAME,
':h' => $passwordHash,
':role' => 'admin',
':eid' => $adminId,
':now' => $now,
]);
$pdo->prepare('INSERT INTO supervisor (supervisorID, username, location) VALUES (:id, :u, :loc)')
->execute([':id' => $supervisorId, ':u' => self::SUPERVISOR_USERNAME, ':loc' => 'Region A']);
$pdo->prepare(
'INSERT INTO users (userID, username, passwordHash, role, entityID, mustChangePassword, createdAt)
VALUES (:uid, :u, :h, :role, :eid, 0, :now)'
)->execute([
':uid' => $supervisorUserId,
':u' => self::SUPERVISOR_USERNAME,
':h' => $passwordHash,
':role' => 'supervisor',
':eid' => $supervisorId,
':now' => $now,
]);
$pdo->prepare('INSERT INTO coach (coachID, supervisorID, username) VALUES (:id, :sid, :u)')
->execute([':id' => $coachId, ':sid' => $supervisorId, ':u' => self::COACH_USERNAME]);
$pdo->prepare(
'INSERT INTO users (userID, username, passwordHash, role, entityID, mustChangePassword, createdAt)
VALUES (:uid, :u, :h, :role, :eid, 0, :now)'
)->execute([
':uid' => $coachUserId,
':u' => self::COACH_USERNAME,
':h' => $passwordHash,
':role' => 'coach',
':eid' => $coachId,
':now' => $now,
]);
$pdo->prepare('INSERT INTO client (clientCode, coachID) VALUES (:cc, :cid)')
->execute([':cc' => 'CLIENT-TEST-001', ':cid' => $coachId]);
$pdo->prepare(
'INSERT INTO questionnaire (questionnaireID, name, version, state, orderIndex, showPoints, conditionJson, categoryKey)
VALUES (:id, :n, :v, :s, 1, 0, :cj, :ck)'
)->execute([
':id' => $qnId,
':n' => 'Test questionnaire',
':v' => '1',
':s' => 'active',
':cj' => '{}',
':ck' => '',
]);
$pdo->prepare('UPDATE questionnaire SET showPoints = 1 WHERE questionnaireID = :id')
->execute([':id' => $qnId]);
$pdo->prepare(
'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
VALUES (:id, :qn, :txt, :type, 0, 1, :cfg)'
)->execute([
':id' => $questionId,
':qn' => $qnId,
':txt' => 'Consent?',
':type' => 'single_choice_question',
':cfg' => json_encode(['questionKey' => 'consent_q'], JSON_THROW_ON_ERROR),
]);
$pdo->prepare(
'INSERT INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId)
VALUES (:id, :qid, :txt, 0, 0, :next)'
)->execute([
':next' => '',
':id' => $optionId,
':qid' => $questionId,
':txt' => 'yes',
]);
$pdo->prepare(
'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
VALUES (:id, :qn, :txt, :type, 1, 0, :cfg)'
)->execute([
':id' => $freeTextQuestionId,
':qn' => $qnId,
':txt' => 'Notes',
':type' => 'free_text_question',
':cfg' => json_encode(['questionKey' => 'notes_q'], JSON_THROW_ON_ERROR),
]);
$glassConfig = json_encode(
['questionKey' => 'symptoms_q', 'symptoms' => [$glassSymptomKey, 'fatigue']],
JSON_THROW_ON_ERROR
);
$pdo->prepare(
'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
VALUES (:id, :qn, :txt, :type, 2, 0, :cfg)'
)->execute([
':id' => $glassQuestionId,
':qn' => $qnId,
':txt' => 'Symptoms',
':type' => 'glass_scale_question',
':cfg' => $glassConfig,
]);
require_once dirname(__DIR__, 2) . '/lib/settings.php';
qdb_settings_save_on_pdo($pdo, qdb_settings_defaults());
$pdo->prepare(
'INSERT INTO question (questionID, questionnaireID, defaultText, type, orderIndex, isRequired, configJson)
VALUES (:id, :qn, :txt, :type, 3, 0, :cfg)'
)->execute([
':id' => $multiQuestionId,
':qn' => $qnId,
':txt' => 'Pick several',
':type' => 'multi_check_box_question',
':cfg' => json_encode(['questionKey' => 'multi_q'], JSON_THROW_ON_ERROR),
]);
$pdo->prepare(
'INSERT INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId)
VALUES (:id, :qid, :txt, 1, 0, :next)'
)->execute([':next' => '', ':id' => $multiOptionAId, ':qid' => $multiQuestionId, ':txt' => 'opt_a']);
$pdo->prepare(
'INSERT INTO answer_option (answerOptionID, questionID, defaultText, points, orderIndex, nextQuestionId)
VALUES (:id, :qid, :txt, 2, 1, :next)'
)->execute([':next' => '', ':id' => $multiOptionBId, ':qid' => $multiQuestionId, ':txt' => 'opt_b']);
qdb_upsert_source_translation($pdo, 'answer_option', $multiOptionAId, 'A');
qdb_upsert_source_translation($pdo, 'answer_option', $multiOptionBId, 'B');
$pdo->prepare(
'INSERT INTO questionnaire (questionnaireID, name, version, state, orderIndex, showPoints, conditionJson, categoryKey)
VALUES (:id, :n, :v, :s, 2, 0, :cj, :ck)'
)->execute([
':id' => $draftQuestionnaireId,
':n' => 'Draft only',
':v' => '1',
':s' => 'draft',
':cj' => '{}',
':ck' => '',
]);
qdb_upsert_source_translation($pdo, 'answer_option', $optionId, 'Ja');
return new FixtureIds(
adminUserId: $adminUserId,
supervisorUserId: $supervisorUserId,
coachUserId: $coachUserId,
coachId: $coachId,
supervisorId: $supervisorId,
questionnaireId: $qnId,
questionId: $questionId,
questionShortId: 'q1',
optionId: $optionId,
freeTextQuestionId: $freeTextQuestionId,
freeTextShortId: 'q2',
glassQuestionId: $glassQuestionId,
glassShortId: 'q3',
glassSymptomKey: $glassSymptomKey,
multiCheckQuestionId: $multiQuestionId,
multiCheckShortId: 'q4',
draftQuestionnaireId: $draftQuestionnaireId,
clientCode: 'CLIENT-TEST-001',
);
}
}
final class FixtureIds
{
public function __construct(
public readonly string $adminUserId,
public readonly string $supervisorUserId,
public readonly string $coachUserId,
public readonly string $coachId,
public readonly string $supervisorId,
public readonly string $questionnaireId,
public readonly string $questionId,
public readonly string $questionShortId,
public readonly string $optionId,
public readonly string $freeTextQuestionId,
public readonly string $freeTextShortId,
public readonly string $glassQuestionId,
public readonly string $glassShortId,
public readonly string $glassSymptomKey,
public readonly string $multiCheckQuestionId,
public readonly string $multiCheckShortId,
public readonly string $draftQuestionnaireId,
public readonly string $clientCode,
) {
}
}