Files
nat-as-server/tests/Integration/QuestionnaireEditingTest.php
Tom Hempel 12d63fdd9f
Some checks failed
PHPUnit / test (push) Has been cancelled
remove empty translation keys
2026-07-18 14:02:49 +02:00

146 lines
5.7 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Integration;
use Tests\Support\DatabaseSeeder;
use Tests\Support\QdbTestCase;
final class QuestionnaireEditingTest extends QdbTestCase
{
public function testAdminCreatesQuestion(): void
{
$token = $this->api()->loginWebAndGetToken(
DatabaseSeeder::ADMIN_USERNAME,
DatabaseSeeder::PASSWORD
)['token'];
$f = $this->fixture();
$res = $this->api()->withToken($token, 'POST', 'questions', [
'questionnaireID' => $f->questionnaireId,
'questionKey' => 'extra_q',
'defaultText' => 'Extra question text',
'type' => 'free_text',
'isRequired' => 0,
'configJson' => '{}',
]);
$this->assertApiOk($res);
$this->assertSame('extra_q', $res['data']['question']['questionKey'] ?? '');
}
public function testAdminCreatesAnswerOption(): void
{
$token = $this->api()->loginWebAndGetToken(
DatabaseSeeder::ADMIN_USERNAME,
DatabaseSeeder::PASSWORD
)['token'];
$f = $this->fixture();
$res = $this->api()->withToken($token, 'POST', 'answer_options', [
'questionID' => $f->questionId,
'optionKey' => 'no_option',
'defaultText' => 'No',
'points' => 0,
]);
$this->assertApiOk($res);
$this->assertSame('no_option', $res['data']['answerOption']['optionKey'] ?? '');
}
public function testAnswerOptionsRequireQuestionId(): void
{
$token = $this->api()->loginWebAndGetToken(
DatabaseSeeder::ADMIN_USERNAME,
DatabaseSeeder::PASSWORD
)['token'];
$res = $this->api()->withToken($token, 'GET', 'answer_options');
$this->assertApiError($res, 'MISSING_PARAM', 400);
}
public function testSavingNoteBeforeBumpsStructureRevisionAndExportsKey(): void
{
$adminToken = $this->api()->loginWebAndGetToken(
DatabaseSeeder::ADMIN_USERNAME,
DatabaseSeeder::PASSWORD
)['token'];
$coachLogin = $this->api()->loginMobileAndGetToken(
DatabaseSeeder::COACH_USERNAME,
DatabaseSeeder::PASSWORD
);
$f = $this->fixture();
$before = $this->api()->withMobileToken($coachLogin['token'], 'GET', 'app_questionnaires', null, [
'id' => $f->questionnaireId,
]);
$this->assertApiOk($before);
$revBefore = (int)($before['data']['structureRevision'] ?? 1);
$put = $this->api()->withToken($adminToken, 'PUT', 'questions', [
'questionID' => $f->questionId,
'questionKey' => 'consent_q',
'defaultText' => 'Consent?',
'type' => 'single_choice_question',
'isRequired' => 1,
'configJson' => json_encode(['questionKey' => 'consent_q'], JSON_UNESCAPED_UNICODE),
'noteBefore' => 'Bitte dem Klienten deutlich machen: Ohne Einwilligung keine Teilnahme.',
'noteAfter' => '',
]);
$this->assertApiOk($put);
$revAfter = (int)($put['data']['structureRevision'] ?? 0);
$this->assertGreaterThan($revBefore, $revAfter, 'note-only edit must bump structureRevision for app sync');
$detail = $this->api()->withMobileToken($coachLogin['token'], 'GET', 'app_questionnaires', null, [
'id' => $f->questionnaireId,
]);
$this->assertApiOk($detail);
$questions = $detail['data']['questions'] ?? [];
$this->assertIsArray($questions);
$matched = null;
foreach ($questions as $q) {
if (($q['question'] ?? '') === 'consent_q' || ($q['id'] ?? '') === 'q1') {
$matched = $q;
break;
}
}
$this->assertNotNull($matched, 'expected consent question in app export');
$this->assertSame('consent_q_note_before', $matched['noteBeforeKey'] ?? null);
$de = $detail['data']['translations']['de'] ?? [];
$this->assertSame(
'Bitte dem Klienten deutlich machen: Ohne Einwilligung keine Teilnahme.',
$de['consent_q_note_before'] ?? null
);
$clear = $this->api()->withToken($adminToken, 'PUT', 'questions', [
'questionID' => $f->questionId,
'questionKey' => 'consent_q',
'defaultText' => 'Consent?',
'type' => 'single_choice_question',
'isRequired' => 1,
'configJson' => json_encode(['questionKey' => 'consent_q'], JSON_UNESCAPED_UNICODE),
'noteBefore' => '',
'noteAfter' => '',
]);
$this->assertApiOk($clear);
$this->assertGreaterThan(
$revAfter,
(int)($clear['data']['structureRevision'] ?? 0),
'clearing notes must bump structureRevision'
);
$detailCleared = $this->api()->withMobileToken($coachLogin['token'], 'GET', 'app_questionnaires', null, [
'id' => $f->questionnaireId,
]);
$this->assertApiOk($detailCleared);
$matchedCleared = null;
foreach ($detailCleared['data']['questions'] ?? [] as $q) {
if (($q['question'] ?? '') === 'consent_q' || ($q['id'] ?? '') === 'q1') {
$matchedCleared = $q;
break;
}
}
$this->assertNotNull($matchedCleared);
$this->assertArrayNotHasKey('noteBeforeKey', $matchedCleared);
$this->assertArrayNotHasKey('noteAfterKey', $matchedCleared);
$deCleared = $detailCleared['data']['translations']['de'] ?? [];
$this->assertArrayNotHasKey('consent_q_note_before', $deCleared);
}
}