fix: offer the questionnaire after every placement, the bus part to escorts

This commit is contained in:
fromme committed 2026-10-27 17:12:24 +01:00
1 parent 9fedc5b5d3
commit 2f4f9800dd
30 files changed
+311 -77

No files matched your search

+65 -6
View File
@@ -7,6 +7,7 @@ namespace App\Tests\Config;
use App\Config\QuestionnaireCatalog;
use App\Enum\ChoiceWidget;
use App\Enum\ConditionOperator;
use App\Enum\QuestionnaireFlag;
use App\Enum\QuestionType;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
@@ -50,18 +51,18 @@ class QuestionnaireCatalogTest extends TestCase
* What the disposition already knows was decided not to be asked; it is snapshotted into the
* response instead. These are the Google forms' keys for those questions.
*/
public function testTeamerEscortDoesNotAskWhatTheDispositionKnows(): void
public function testTeamerAssignmentDoesNotAskWhatTheDispositionKnows(): void
{
$definition = new QuestionnaireCatalog(self::SHIPPED_DIR)->get('teamer_escort');
$definition = new QuestionnaireCatalog(self::SHIPPED_DIR)->get('teamer_assignment');
foreach (['name', 'job_profile', 'house', 'assignment_start', 'travel_date', 'destination', 'guide_name', 'first_pickup_location'] as $key) {
$this->assertNull($definition->getQuestion($key), $key);
}
}
public function testTeamerEscortLowRatingReasonIsRequiredOnlyForLowRatings(): void
public function testTeamerAssignmentLowRatingReasonIsRequiredOnlyForLowRatings(): void
{
$question = new QuestionnaireCatalog(self::SHIPPED_DIR)->get('teamer_escort')->getQuestion('office_briefing_low_reason');
$question = new QuestionnaireCatalog(self::SHIPPED_DIR)->get('teamer_assignment')->getQuestion('office_briefing_low_reason');
$this->assertTrue($question->required);
$this->assertSame('office_briefing_rating', $question->showIf->question);
@@ -73,9 +74,9 @@ class QuestionnaireCatalogTest extends TestCase
* Google's single "Bitte ankreuzen:" checkbox list allowed "WC defekt" and "WC funktionstüchtig"
* together; it was split into one single choice per topic.
*/
public function testTeamerEscortEquipmentIsOneSingleChoicePerTopic(): void
public function testTeamerAssignmentEquipmentIsOneSingleChoicePerTopic(): void
{
$definition = new QuestionnaireCatalog(self::SHIPPED_DIR)->get('teamer_escort');
$definition = new QuestionnaireCatalog(self::SHIPPED_DIR)->get('teamer_assignment');
foreach (['video', 'wc', 'luggage', 'smoking', 'snow_chains'] as $key) {
$question = $definition->getQuestion($key);
@@ -84,6 +85,28 @@ class QuestionnaireCatalogTest extends TestCase
}
}
/**
* Every teamer gets the questionnaire; only a bus escort gets the bus part, and nobody gets a
* bus section without it.
*/
public function testTeamerAssignmentBusPartIsOnlyForBusEscorts(): void
{
$definition = new QuestionnaireCatalog(self::SHIPPED_DIR)->get(QuestionnaireCatalog::TEAMER_ASSIGNMENT);
foreach ($definition->sections as $section) {
$this->assertSame(
str_starts_with($section->key, 'bus_') ? QuestionnaireFlag::BUS_ESCORT : null,
$section->onlyFor,
$section->key,
);
}
$withoutBus = $definition->forFlags([]);
$this->assertNull($withoutBus->getQuestion('bus_company'));
$this->assertNotNull($withoutBus->getQuestion('office_briefing_rating'));
$this->assertNotNull($definition->forFlags([QuestionnaireFlag::BUS_ESCORT])->getQuestion('bus_company'));
}
public function testChoiceDefaultsToRadio(): void
{
$this->write('sample', $this->sample());
@@ -181,12 +204,41 @@ class QuestionnaireCatalogTest extends TestCase
static fn (array $d): array => self::withQuestion(self::withQuestion($d, 0, ['type' => 'rating', 'options' => null]), 1, ['show_if' => ['question' => 'answer', 'lte' => 6]]),
'lte needs a rating from 1 to 5',
];
yield 'unknown only_for' => [
static fn (array $d): array => self::withSection($d, ['only_for' => 'ferry']),
'unknown only_for "ferry"',
];
yield 'key does not match the file name' => [
static fn (array $d): array => ['key' => 'other'] + $d,
'does not match the file name',
];
}
/**
* A question everyone gets cannot depend on a bus-only question: without the bus part it
* would never be shown.
*/
public function testQuestionCannotDependOnAQuestionOnlyAskedWithAFlag(): void
{
$definition = $this->sample();
$definition['sections'][0]['only_for'] = 'bus_escort';
$definition['sections'][] = [
'key' => 'later',
'questions' => [[
'key' => 'other_reason',
'label' => 'Warum?',
'type' => 'text',
'show_if' => ['question' => 'answer', 'equals' => 'yes'],
]],
];
$this->write('sample', $definition);
$this->expectException(\UnexpectedValueException::class);
$this->expectExceptionMessage('"answer" is only asked for bus_escort');
new QuestionnaireCatalog($this->dir)->get('sample');
}
public function testArchivedFileWithTheWrongVersionIsRejected(): void
{
$this->write('sample', ['version' => 3] + $this->sample());
@@ -238,6 +290,13 @@ class QuestionnaireCatalogTest extends TestCase
return $definition;
}
private static function withSection(array $definition, array $fields): array
{
$definition['sections'][0] = $fields + $definition['sections'][0];
return $definition;
}
private function write(string $name, array $definition): void
{
file_put_contents(sprintf('%s/%s.yaml', $this->dir, $name), Yaml::dump($definition, 10));