Your level?', $html); self::assertStringContainsString('', $html); } public function testARequiredQuestionIsMarkedAndEnforced(): void { $question = new Question(7, 'Your level?', isRequired: true, id: 3); $html = QuestionField::render($question, 'us_answers[3]', 'us-q-3'); self::assertStringContainsString('us-required', $html); self::assertStringContainsString(' required', $html); } /** * A block that may not apply at all keeps the marker and drops the attribute, * so the browser cannot refuse a submit over a field that is out of play. */ public function testNotEnforcingRequiredKeepsTheMarkerButDropsTheAttribute(): void { $question = new Question(7, 'Your level?', isRequired: true, id: 3); $html = QuestionField::render($question, 'us_answers[3]', 'us-q-3', enforceRequired: false); self::assertStringContainsString('us-required', $html); self::assertStringNotContainsString(' required>', $html); } /** * Which of the question's two required flags applies depends on whose block * this is, and only the caller knows that. */ public function testTheCallerCanOverrideWhichRequiredFlagApplies(): void { $question = new Question( null, 'Previous experience', scope: Question::SCOPE_ACCOUNT, isRequired: false, isRequiredChild: true, id: 3 ); $forSelf = QuestionField::render($question, 'us_answers[3]', 'us-q-3', isRequired: $question->isRequiredForSelf()); $forChild = QuestionField::render($question, 'children[0][answers][3]', 'us-child-0-q-3', isRequired: $question->isRequiredForChild()); self::assertStringNotContainsString('us-required', $forSelf); self::assertStringNotContainsString(' required', $forSelf); self::assertStringContainsString('us-required', $forChild); self::assertStringContainsString(' required', $forChild); } public function testASelectRendersItsOptionsBehindAnEmptyChoice(): void { $question = new Question( 7, 'Pick a level', fieldType: Question::FIELD_SELECT, options: ['Beginner', 'Advanced'], id: 3 ); $html = QuestionField::render($question, 'us_answers[3]', 'us-q-3'); self::assertStringContainsString('