Files
myep-team/tests/Twig/QuestionnaireTemplateTest.php
T

134 lines
4.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Twig;
use App\Config\QuestionnaireCatalog;
use App\Entity\Application;
use App\Entity\Assignment;
use App\Entity\Disposition;
use App\Entity\QuestionnaireResponse;
use App\Entity\Teamer;
use App\Form\QuestionnaireType;
use App\Model\Questionnaire\Definition;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\Form\FormFactoryInterface;
use Twig\Environment;
/**
* The questionnaire's form-theme blocks and the read-only answers partial, rendered for real:
* a misspelt block prefix silently falls back to Symfony's default markup, which would drop the
* data attributes the show/hide controller needs.
*/
class QuestionnaireTemplateTest extends KernelTestCase
{
public function testEveryQuestionRowCarriesItsKeyAndConditionalOnesTheirCondition(): void
{
$crawler = $this->renderForm();
$this->assertCount(
count($this->definition()->getQuestions()) + count($this->busDefinition()->getQuestions()),
$crawler->filter('[data-question-key]'),
);
$this->assertSame(
'{"question":"bus_feedback.bus_company","operator":"equals","value":"other"}',
$crawler->filter('[data-question-key="bus_feedback.bus_company_other"]')->attr('data-show-if'),
);
}
public function testSectionsAreFieldsetsWithTheirTitle(): void
{
$crawler = $this->renderForm();
$this->assertSame('Organisation & Ablauf', trim($crawler->filter('fieldset legend')->first()->text()));
$this->assertCount(
count($this->definition()->sections) + count($this->busDefinition()->sections),
$crawler->filter('fieldset'),
);
}
/**
* On one page, each questionnaire keeps its own heading.
*/
public function testEachQuestionnaireHasItsHeading(): void
{
$headings = $this->renderForm()->filter('section > h2')->each(static fn (Crawler $h2): string => trim($h2->text()));
$this->assertSame([$this->definition()->title, $this->busDefinition()->title], $headings);
}
public function testRatingIsFiveRadiosInARadioGroup(): void
{
$group = $this->renderForm()->filter('[data-question-key="teamer_feedback.office_briefing_rating"] [role="radiogroup"]');
$this->assertCount(5, $group->filter('input[type="radio"]'));
}
public function testAnswersShowLabelsNotKeysAndSkipHiddenQuestions(): void
{
$definition = $this->definition();
$response = QuestionnaireResponse::forDisposition($definition, new Disposition(new Application(new Assignment(), new Teamer())))
->submit($definition, [
'office_briefing_rating' => 2,
'office_briefing_low_reason' => 'Briefing kam zu spät',
'had_organisational_problems' => 'no',
'organisational_problems' => 'hidden, so dropped',
], [], new \DateTimeImmutable())
;
$html = $this->renderAnswers($definition, $response->getAnswers());
$this->assertStringContainsString('2 von 5', $html);
$this->assertStringContainsString('Briefing kam zu spät', $html);
$this->assertStringContainsString('Nein', $html);
$this->assertStringNotContainsString('hidden, so dropped', $html);
// nothing was answered there, so the section is left out
$this->assertStringNotContainsString('Kommunikation &amp; Zusammenarbeit', $html);
$html = $this->renderAnswers($this->busDefinition(), ['bus_company' => 'heess']);
$this->assertStringContainsString('Heeß', $html);
$this->assertStringNotContainsString('heess', $html);
}
private function renderForm(): Crawler
{
self::bootKernel();
$container = self::getContainer();
$form = $container->get(FormFactoryInterface::class)->create(QuestionnaireType::class, [], [
'definitions' => [$this->definition(), $this->busDefinition()],
'csrf_protection' => false,
]);
$html = $container->get(Environment::class)
->createTemplate('{{ form(form) }}')
->render(['form' => $form->createView()])
;
return new Crawler($html);
}
private function renderAnswers(Definition $definition, array $answers): string
{
self::bootKernel();
return self::getContainer()->get(Environment::class)->render('questionnaire/_answers.html.twig', [
'definition' => $definition,
'answers' => $answers,
]);
}
private function definition(): Definition
{
return new QuestionnaireCatalog(__DIR__.'/../../config/questionnaires')->get(QuestionnaireCatalog::TEAMER_FEEDBACK);
}
private function busDefinition(): Definition
{
return new QuestionnaireCatalog(__DIR__.'/../../config/questionnaires')->get(QuestionnaireCatalog::BUS_FEEDBACK);
}
}