. /** * Unit tests for core\output\choice class. * * @package core * @category test * @copyright 2023 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\output; use advanced_testcase; /** * Unit tests for the `icon_system` class. * * @coversDefaultClass \core\output\choicelist */ class choicelist_test extends advanced_testcase { /** * Test for a choice without options. * * @covers ::_construct * @covers ::add_option * @covers ::export_for_template */ public function test_empty_export(): void { $page = new \moodle_page(); $page->set_url('/user/profile.php'); $page->set_context(\context_system::instance()); $renderer = $page->get_renderer('core'); $choice = new choicelist('Choose an option'); $export = $choice->export_for_template($renderer); $this->assertEquals('Choose an option', $export['description']); $this->assertEquals(false, $export['hasoptions']); $this->assertEquals([], $export['options']); } /** * Test for a choice with basic options. * * @covers ::_construct * @covers ::add_option * @covers ::export_for_template */ public function test_basic_export(): void { $page = new \moodle_page(); $page->set_url('/user/profile.php'); $page->set_context(\context_system::instance()); $renderer = $page->get_renderer('core'); $choice = new choicelist('Choose an option'); $choice->add_option('option1', 'Option 1'); $choice->add_option('option2', 'Option 2'); $export = $choice->export_for_template($renderer); $this->assertEquals('Choose an option', $export['description']); $this->assertEquals(true, $export['hasoptions']); $this->assertCount(2, $export['options']); $this->validate_option($export['options'][0], 'option1', 'Option 1', []); $this->validate_option($export['options'][1], 'option2', 'Option 2', []); } /** * Test for a choice with extras options definition. * * @covers ::_construct * @covers ::add_option * @covers ::set_option_extras * @covers ::export_for_template */ public function test_option_defintion_export(): void { $page = new \moodle_page(); $page->set_url('/user/profile.php'); $page->set_context(\context_system::instance()); $renderer = $page->get_renderer('core'); $choice = new choicelist('Choose an option'); $definition1 = [ 'disabled' => true, 'description' => 'Description', 'url' => new \moodle_url('/user/profile.php'), 'icon' => new \pix_icon('i/grade', 'Grade'), 'extras' => [ 'data-attribute' => 'value', ], ]; $choice->add_option('option1', 'Option 1', $definition1); $definition2 = [ 'disabled' => false, 'description' => null, 'url' => null, 'icon' => null, 'extras' => null, ]; $choice->add_option('option2', 'Option 2', $definition2); $export = $choice->export_for_template($renderer); $this->assertEquals('Choose an option', $export['description']); $this->assertEquals(true, $export['hasoptions']); $this->assertCount(2, $export['options']); $definition1['iconexport'] = $definition1['icon']->export_for_pix($renderer); $this->validate_option($export['options'][0], 'option1', 'Option 1', $definition1); $this->validate_option($export['options'][1], 'option2', 'Option 2', $definition2); } /** * Test for a choice with option selected. * * @covers ::_construct * @covers ::add_option * @covers ::set_selected_value * @covers ::get_selected_value * @covers ::export_for_template */ public function test_option_selected_export(): void { $page = new \moodle_page(); $page->set_url('/user/profile.php'); $page->set_context(\context_system::instance()); $renderer = $page->get_renderer('core'); $choice = new choicelist('Choose an option'); $choice->add_option('option1', 'Option 1'); $choice->add_option('option2', 'Option 2'); $choice->set_selected_value('option1'); $export = $choice->export_for_template($renderer); $this->assertEquals('Choose an option', $export['description']); $this->assertEquals(true, $export['hasoptions']); $this->assertCount(2, $export['options']); $this->assertEquals('option1', $choice->get_selected_value()); $this->validate_option($export['options'][0], 'option1', 'Option 1', [], true); $this->validate_option($export['options'][1], 'option2', 'Option 2', []); } /** * Validate a choice option export. * @param array $option the option export * @param string $value the option value * @param string $name the option name * @param array|null $definition the option definition * @param bool $selected if the option is selected */ private function validate_option( array $option, string $value, string $name, ?array $definition, bool $selected = false ): void { $this->assertEquals($value, $option['value']); $this->assertEquals($name, $option['name']); $this->assertEquals($definition['disabled'] ?? false, $option['disabled']); $this->assertEquals($definition['description'] ?? null, $option['description']); if (isset($definition['url'])) { $this->assertEquals($definition['url']->out(true), $option['url']); $this->assertTrue($option['hasurl']); } if (isset($definition['icon'])) { $this->assertEquals($definition['iconexport'], $option['icon']); $this->assertTrue($option['hasicon']); } if ($selected) { $this->assertTrue($option['selected']); } if (isset($definition['extras'])) { foreach ($option['extras'] as $extra) { $attribute = $extra['attribute']; $this->assertEquals($definition['extras'][$attribute], $extra['value']); } } else { $this->assertFalse(isset($option['extras'])); } } /** * Test for a choice with option selected. * * @covers ::_construct * @covers ::add_option * @covers ::set_selected_value * @covers ::get_selected_value * @covers ::set_allow_empty * @covers ::get_allow_empty * @covers ::export_for_template */ public function test_set_allow_empty(): void { $choice = new choicelist('Choose an option'); $choice->add_option('option1', 'Option 1'); $choice->add_option('option2', 'Option 2'); $choice->set_allow_empty(true); $this->assertTrue($choice->get_allow_empty()); $this->assertNull($choice->get_selected_value()); $choice->set_allow_empty(false); $this->assertFalse($choice->get_allow_empty()); $this->assertEquals('option1', $choice->get_selected_value()); // Validate the null selected value is not changed when allow empty is set to true. $choice->set_allow_empty(true); $this->assertTrue($choice->get_allow_empty()); $this->assertNull($choice->get_selected_value()); $choice->set_selected_value('option2'); $choice->set_allow_empty(false); $this->assertFalse($choice->get_allow_empty()); $this->assertEquals('option2', $choice->get_selected_value()); $choice->set_allow_empty(true); $this->assertTrue($choice->get_allow_empty()); $this->assertEquals('option2', $choice->get_selected_value()); } /** * Test for a choice with option selected. * * @covers ::get_selectable_options */ public function test_get_selectable_options(): void { $choice = new choicelist('Choose an option'); $choice->add_option('option1', 'Option 1'); $choice->add_option('option2', 'Option 2'); $choice->add_option('option3', 'Option 3', ['disabled' => true]); $choice->add_option('option4', 'Option 4', ['disabled' => true]); $choice->add_option('option5', 'Option 5'); $selectable = $choice->get_selectable_options(); $this->assertCount(3, $selectable); $this->assertEquals('option1', $selectable[0]->value); $this->assertEquals('option2', $selectable[1]->value); $this->assertEquals('option5', $selectable[2]->value); $choice->set_selected_value('option2'); $selectable = $choice->get_selectable_options(); $this->assertCount(2, $selectable); $this->assertEquals('option1', $selectable[0]->value); $this->assertEquals('option5', $selectable[1]->value); } /** * Test for a choice with option selected. * * @covers ::get_option_extras */ public function test_get_option_extras(): void { $choice = new choicelist('Choose an option'); $choice->add_option('option1', 'Option 1'); $choice->add_option('option2', 'Option 2', ['extras' => ['data-attribute' => 'value2']]); $this->assertEquals([], $choice->get_option_extras('option1')); $this->assertEquals(['data-attribute' => 'value2'], $choice->get_option_extras('option2')); $this->assertEquals([], $choice->get_option_extras('inexistent')); } }