Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
  • Differences Between: [Versions 310 and 311] [Versions 37 and 311] [Versions 38 and 311] [Versions 39 and 311]

       1  <?php
       2  // This file is part of Moodle - http://moodle.org/
       3  //
       4  // Moodle is free software: you can redistribute it and/or modify
       5  // it under the terms of the GNU General Public License as published by
       6  // the Free Software Foundation, either version 3 of the License, or
       7  // (at your option) any later version.
       8  //
       9  // Moodle is distributed in the hope that it will be useful,
      10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12  // GNU General Public License for more details.
      13  //
      14  // You should have received a copy of the GNU General Public License
      15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
      16  
      17  /**
      18   * Unit tests for lib/outputcomponents.php.
      19   *
      20   * @package   core
      21   * @category  phpunit
      22   * @copyright 2011 David Mudrak <david@moodle.com>
      23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      24   */
      25  
      26  defined('MOODLE_INTERNAL') || die();
      27  
      28  global $CFG;
      29  require_once($CFG->libdir . '/outputcomponents.php');
      30  
      31  /**
      32   * Unit tests for the user_picture class.
      33   */
      34  class core_outputcomponents_testcase extends advanced_testcase {
      35  
      36      /**
      37       * Tests user_picture::fields.
      38       *
      39       * @deprecated since Moodle 3.11 MDL-45242
      40       */
      41      public function test_fields_aliasing() {
      42          $fields = user_picture::fields();
      43          $fields = array_map('trim', explode(',', $fields));
      44          $this->assertTrue(in_array('id', $fields));
      45  
      46          $aliased = array();
      47          foreach ($fields as $field) {
      48              if ($field === 'id') {
      49                  $aliased['id'] = 'aliasedid';
      50              } else {
      51                  $aliased[$field] = 'prefix'.$field;
      52              }
      53          }
      54  
      55          $returned = user_picture::fields('', array('custom1', 'id'), 'aliasedid', 'prefix');
      56          $returned = array_map('trim', explode(',', $returned));
      57          $this->assertEquals(count($returned), count($fields) + 1); // Only one extra field added.
      58  
      59          foreach ($fields as $field) {
      60              if ($field === 'id') {
      61                  $expected = "id AS aliasedid";
      62              } else {
      63                  $expected = "$field AS prefix$field";
      64              }
      65              $this->assertContains($expected, $returned, "Expected pattern '$expected' not returned");
      66          }
      67          $this->assertContains("custom1 AS prefixcustom1", $returned, "Expected pattern 'custom1 AS prefixcustom1' not returned");
      68  
      69          // Deprecation warnings for user_picture::fields.
      70          $this->assertDebuggingCalledCount(2);
      71      }
      72  
      73      /**
      74       * Tests user_picture::unalias.
      75       */
      76      public function test_fields_unaliasing() {
      77          $fields = implode(',', \core_user\fields::get_picture_fields());
      78          $fields = array_map('trim', explode(',', $fields));
      79  
      80          $fakerecord = new stdClass();
      81          $fakerecord->aliasedid = 42;
      82          foreach ($fields as $field) {
      83              if ($field !== 'id') {
      84                  $fakerecord->{'prefix'.$field} = "Value of $field";
      85              }
      86          }
      87          $fakerecord->prefixcustom1 = 'Value of custom1';
      88  
      89          $returned = user_picture::unalias($fakerecord, array('custom1'), 'aliasedid', 'prefix');
      90  
      91          $this->assertEquals(42, $returned->id);
      92          foreach ($fields as $field) {
      93              if ($field !== 'id') {
      94                  $this->assertSame("Value of $field", $returned->{$field});
      95              }
      96          }
      97          $this->assertSame('Value of custom1', $returned->custom1);
      98      }
      99  
     100      /**
     101       * Tests user_picture::unalias with null values.
     102       */
     103      public function test_fields_unaliasing_null() {
     104          $fields = implode(',', \core_user\fields::get_picture_fields());
     105          $fields = array_map('trim', explode(',', $fields));
     106  
     107          $fakerecord = new stdClass();
     108          $fakerecord->aliasedid = 42;
     109          foreach ($fields as $field) {
     110              if ($field !== 'id') {
     111                  $fakerecord->{'prefix'.$field} = "Value of $field";
     112              }
     113          }
     114          $fakerecord->prefixcustom1 = 'Value of custom1';
     115          $fakerecord->prefiximagealt = null;
     116  
     117          $returned = user_picture::unalias($fakerecord, array('custom1'), 'aliasedid', 'prefix');
     118  
     119          $this->assertEquals(42, $returned->id);
     120          $this->assertNull($returned->imagealt);
     121          foreach ($fields as $field) {
     122              if ($field !== 'id' and $field !== 'imagealt') {
     123                  $this->assertSame("Value of $field", $returned->{$field});
     124              }
     125          }
     126          $this->assertSame('Value of custom1', $returned->custom1);
     127      }
     128  
     129      public function test_get_url() {
     130          global $DB, $CFG, $USER;
     131  
     132          $this->resetAfterTest();
     133  
     134          // Force SVG on so that we have predictable URL's.
     135          $CFG->svgicons = true;
     136  
     137          // Verify new install contains expected defaults.
     138          $this->assertSame(theme_config::DEFAULT_THEME, $CFG->theme);
     139          $this->assertEquals(1, $CFG->slasharguments);
     140          $this->assertEquals(1, $CFG->themerev);
     141          $this->assertEquals(0, $CFG->themedesignermode);
     142          $this->assertSame('https://www.example.com/moodle', $CFG->wwwroot);
     143          $this->assertEquals(0, $CFG->enablegravatar);
     144          $this->assertSame('mm', $CFG->gravatardefaulturl);
     145  
     146          // Create some users.
     147          $page = new moodle_page();
     148          $page->set_url('/user/profile.php');
     149          $page->set_context(context_system::instance());
     150          $renderer = $page->get_renderer('core');
     151  
     152          $user1 = $this->getDataGenerator()->create_user(array('picture'=>11, 'email'=>'user1@example.com'));
     153          $context1 = context_user::instance($user1->id);
     154          $user2 = $this->getDataGenerator()->create_user(array('picture'=>0, 'email'=>'user2@example.com'));
     155          $context2 = context_user::instance($user2->id);
     156  
     157          // User 3 is deleted.
     158          $user3 = $this->getDataGenerator()->create_user(array('picture'=>1, 'deleted'=>1, 'email'=>'user3@example.com'));
     159          $this->assertNotEmpty(context_user::instance($user3->id));
     160          $this->assertEquals(0, $user3->picture);
     161          $this->assertNotEquals('user3@example.com', $user3->email);
     162  
     163          // User 4 is incorrectly deleted with its context deleted as well (testing legacy code).
     164          $user4 = $this->getDataGenerator()->create_user(['picture' => 1, 'deleted' => 1, 'email' => 'user4@example.com']);
     165          context_helper::delete_instance(CONTEXT_USER, $user4->id);
     166          $this->assertEquals(0, $user4->picture);
     167          $this->assertNotEquals('user4@example.com', $user4->email);
     168  
     169          // Try legacy picture == 1.
     170          $user1->picture = 1;
     171          $up1 = new user_picture($user1);
     172          $this->assertSame($CFG->wwwroot.'/pluginfile.php/'.$context1->id.'/user/icon/boost/f2?rev=1', $up1->get_url($page, $renderer)->out(false));
     173          $user1->picture = 11;
     174  
     175          // Try valid user with picture when user context is not cached - 1 query expected.
     176          context_helper::reset_caches();
     177          $reads = $DB->perf_get_reads();
     178          $up1 = new user_picture($user1);
     179          $this->assertEquals($reads, $DB->perf_get_reads());
     180          $this->assertSame($CFG->wwwroot.'/pluginfile.php/'.$context1->id.'/user/icon/boost/f2?rev=11', $up1->get_url($page, $renderer)->out(false));
     181          $this->assertEquals($reads+1, $DB->perf_get_reads());
     182  
     183          // Try valid user with contextid hint - no queries expected.
     184          $user1->contextid = $context1->id;
     185          context_helper::reset_caches();
     186          $reads = $DB->perf_get_reads();
     187          $up1 = new user_picture($user1);
     188          $this->assertEquals($reads, $DB->perf_get_reads());
     189          $this->assertSame($CFG->wwwroot.'/pluginfile.php/'.$context1->id.'/user/icon/boost/f2?rev=11', $up1->get_url($page, $renderer)->out(false));
     190          $this->assertEquals($reads, $DB->perf_get_reads());
     191  
     192          // Try valid user without image - no queries expected.
     193          context_helper::reset_caches();
     194          $reads = $DB->perf_get_reads();
     195          $up2 = new user_picture($user2);
     196          $this->assertEquals($reads, $DB->perf_get_reads());
     197          $this->assertSame($CFG->wwwroot.'/theme/image.php/boost/core/1/u/f2', $up2->get_url($page, $renderer)->out(false));
     198          $this->assertEquals($reads, $DB->perf_get_reads());
     199  
     200          // Try guessing of deleted users - no queries expected.
     201          unset($user3->deleted);
     202          context_helper::reset_caches();
     203          $reads = $DB->perf_get_reads();
     204          $up3 = new user_picture($user3);
     205          $this->assertEquals($reads, $DB->perf_get_reads());
     206          $this->assertSame($CFG->wwwroot.'/theme/image.php/boost/core/1/u/f2', $up3->get_url($page, $renderer)->out(false));
     207          $this->assertEquals($reads, $DB->perf_get_reads());
     208  
     209          // Try incorrectly deleted users (with valid email and picture flag, but user context removed) - some DB reads expected.
     210          unset($user4->deleted);
     211          $user4->email = 'user4@example.com';
     212          $user4->picture = 1;
     213          $reads = $DB->perf_get_reads();
     214          $up4 = new user_picture($user4);
     215          $this->assertEquals($reads, $DB->perf_get_reads());
     216          $this->assertSame($CFG->wwwroot.'/theme/image.php/boost/core/1/u/f2', $up4->get_url($page, $renderer)->out(false));
     217          $this->assertGreaterThan($reads, $DB->perf_get_reads());
     218  
     219          // Test gravatar.
     220          set_config('enablegravatar', 1);
     221  
     222          // Deleted user can not have gravatar.
     223          $user3->email = 'deleted';
     224          $user3->picture = 0;
     225          $up3 = new user_picture($user3);
     226          $this->assertSame($CFG->wwwroot.'/theme/image.php/boost/core/1/u/f2', $up3->get_url($page, $renderer)->out(false));
     227          $user4->email = 'deleted';
     228          $user4->picture = 0;
     229          $up4 = new user_picture($user4);
     230          $this->assertSame($CFG->wwwroot.'/theme/image.php/boost/core/1/u/f2', $up4->get_url($page, $renderer)->out(false));
     231  
     232          // Http version.
     233          $CFG->wwwroot = str_replace('https:', 'http:', $CFG->wwwroot);
     234  
     235          // Verify defaults to misteryman (mm).
     236          $up2 = new user_picture($user2);
     237          $this->assertSame('http://www.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?s=35&d=mm', $up2->get_url($page, $renderer)->out(false));
     238  
     239          // Without gravatardefaulturl, verify we pick own file.
     240          set_config('gravatardefaulturl', '');
     241          $up2 = new user_picture($user2);
     242          $this->assertSame('http://www.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?s=35&d=http%3A%2F%2Fwww.example.com%2Fmoodle%2Fpix%2Fu%2Ff2.png', $up2->get_url($page, $renderer)->out(false));
     243          // Uploaded image takes precedence before gravatar.
     244          $up1 = new user_picture($user1);
     245          $this->assertSame($CFG->wwwroot.'/pluginfile.php/'.$context1->id.'/user/icon/boost/f2?rev=11', $up1->get_url($page, $renderer)->out(false));
     246  
     247          // Uploaded image with token-based access for current user.
     248          $up1 = new user_picture($user1);
     249          $up1->includetoken = true;
     250          $token = get_user_key('core_files', $USER->id);
     251          $this->assertSame($CFG->wwwroot.'/tokenpluginfile.php/'.$token.'/'.$context1->id.'/user/icon/boost/f2?rev=11', $up1->get_url($page, $renderer)->out(false));
     252  
     253          // Uploaded image with token-based access for other user.
     254          $up1 = new user_picture($user1);
     255          $up1->includetoken = $user2->id;
     256          $token = get_user_key('core_files', $user2->id);
     257          $this->assertSame($CFG->wwwroot.'/tokenpluginfile.php/'.$token.'/'.$context1->id.'/user/icon/boost/f2?rev=11', $up1->get_url($page, $renderer)->out(false));
     258  
     259          // Https version.
     260          $CFG->wwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
     261  
     262          $up1 = new user_picture($user1);
     263          $this->assertSame($CFG->wwwroot.'/pluginfile.php/'.$context1->id.'/user/icon/boost/f2?rev=11', $up1->get_url($page, $renderer)->out(false));
     264  
     265          $up2 = new user_picture($user2);
     266          $this->assertSame('https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?s=35&d=https%3A%2F%2Fwww.example.com%2Fmoodle%2Fpix%2Fu%2Ff2.png', $up2->get_url($page, $renderer)->out(false));
     267  
     268          $up3 = new user_picture($user3);
     269          $this->assertSame($CFG->wwwroot.'/theme/image.php/boost/core/1/u/f2', $up3->get_url($page, $renderer)->out(false));
     270  
     271          $up4 = new user_picture($user4);
     272          $this->assertSame($CFG->wwwroot.'/theme/image.php/boost/core/1/u/f2', $up4->get_url($page, $renderer)->out(false));
     273  
     274          // TODO MDL-44792 Rewrite those tests to use a fixture.
     275          // Now test gravatar with one theme having own images (afterburner).
     276          // $this->assertFileExists("$CFG->dirroot/theme/afterburner/config.php");
     277          // set_config('theme', 'afterburner');
     278          // $page = new moodle_page();
     279          // $page->set_url('/user/profile.php');
     280          // $page->set_context(context_system::instance());
     281          // $renderer = $page->get_renderer('core');
     282  
     283          // $up2 = new user_picture($user2);
     284          // $this->assertEquals('http://www.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?s=35&d=http%3A%2F%2Fwww.example.com%2Fmoodle%2Ftheme%2Fafterburner%2Fpix_core%2Fu%2Ff2.png', $up2->get_url($page, $renderer)->out(false));
     285  
     286          // $up2 = new user_picture($user2);
     287          // $this->assertSame('https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?s=35&d=https%3A%2F%2Fwww.example.com%2Fmoodle%2Ftheme%2Fafterburner%2Fpix_core%2Fu%2Ff2.png', $up2->get_url($page, $renderer)->out(false));
     288          // End of gravatar tests.
     289  
     290          // Test themed images.
     291          // set_config('enablegravatar', 0);
     292          // $this->assertFileExists("$CFG->dirroot/theme/formal_white/config.php"); // Use any other theme.
     293          // set_config('theme', 'formal_white');
     294          // $page = new moodle_page();
     295          // $page->set_url('/user/profile.php');
     296          // $page->set_context(context_system::instance());
     297          // $renderer = $page->get_renderer('core');
     298  
     299          // $up1 = new user_picture($user1);
     300          // $this->assertSame($CFG->wwwroot.'/pluginfile.php/'.$context1->id.'/user/icon/formal_white/f2?rev=11', $up1->get_url($page, $renderer)->out(false));
     301  
     302          // $up2 = new user_picture($user2);
     303          // $this->assertSame($CFG->wwwroot.'/theme/image.php/formal_white/core/1/u/f2', $up2->get_url($page, $renderer)->out(false));
     304  
     305          // Test non-slashargument images.
     306          set_config('theme', 'classic');
     307          $CFG->wwwroot = str_replace('https:', 'http:', $CFG->wwwroot);
     308          $CFG->slasharguments = 0;
     309          $page = new moodle_page();
     310          $page->set_url('/user/profile.php');
     311          $page->set_context(context_system::instance());
     312          $renderer = $page->get_renderer('core');
     313  
     314          $up3 = new user_picture($user3);
     315          $this->assertSame($CFG->wwwroot.'/theme/image.php?theme=classic&component=core&rev=1&image=u%2Ff2', $up3->get_url($page, $renderer)->out(false));
     316      }
     317  
     318      public function test_empty_menu() {
     319          $emptymenu = new custom_menu();
     320          $this->assertInstanceOf('custom_menu', $emptymenu);
     321          $this->assertFalse($emptymenu->has_children());
     322      }
     323  
     324      public function test_basic_syntax() {
     325          $definition = <<<EOF
     326  Moodle community|http://moodle.org
     327  -Moodle free support|http://moodle.org/support
     328  -Moodle development|http://moodle.org/development
     329  --Moodle Tracker|http://tracker.moodle.org
     330  --Moodle Docs|http://docs.moodle.org
     331  -Moodle News|http://moodle.org/news
     332  Moodle company||Moodle trust pty
     333  -Hosting|http://moodle.com/hosting|Commercial hosting
     334  -Support|http://moodle.com/support|Commercial support
     335  EOF;
     336  
     337          $menu = new custom_menu($definition);
     338          $this->assertInstanceOf('custom_menu', $menu);
     339          $this->assertTrue($menu->has_children());
     340          $firstlevel = $menu->get_children();
     341          $this->assertTrue(is_array($firstlevel));
     342          $this->assertCount(2, $firstlevel);
     343  
     344          $item = array_shift($firstlevel);
     345          $this->assertInstanceOf('custom_menu_item', $item);
     346          $this->assertTrue($item->has_children());
     347          $this->assertCount(3, $item->get_children());
     348          $this->assertEquals('Moodle community', $item->get_text());
     349          $itemurl = $item->get_url();
     350          $this->assertTrue($itemurl instanceof moodle_url);
     351          $this->assertEquals('http://moodle.org', $itemurl->out());
     352          $this->assertNull($item->get_title()); // Implicit title.
     353  
     354          /** @var custom_menu_item $item */
     355          $item = array_shift($firstlevel);
     356          $this->assertTrue($item->has_children());
     357          $this->assertCount(2, $item->get_children());
     358          $this->assertSame('Moodle company', $item->get_text());
     359          $this->assertNull($item->get_url());
     360          $this->assertSame('Moodle trust pty', $item->get_title());
     361  
     362          $children = $item->get_children();
     363          $subitem = array_shift($children);
     364          $this->assertFalse($subitem->has_children());
     365          $this->assertSame('Hosting', $subitem->get_text());
     366          $this->assertSame('Commercial hosting', $subitem->get_title());
     367      }
     368  
     369      public function test_custommenu_mulitlang() {
     370          $definition = <<<EOF
     371  Start|http://school.info
     372  Info
     373  -English|http://school.info/en|Information in English|en
     374  --Nested under English
     375  --I will be lost|||de
     376  -Deutsch|http://school.info/de|Informationen in deutscher Sprache|de,de_du,de_kids
     377  --Nested under Deutsch
     378  --I will be lost|||en
     379  kontaktieren Sie uns|contactus.php||de
     380  Contact us|contactus.php||en
     381  EOF;
     382          $definitionen = <<<EOF
     383  Start|http://school.info
     384  Info
     385  -English|http://school.info/en|Information in English|en
     386  --Nested under English
     387  Contact us|contactus.php||en
     388  EOF;
     389          $definitionde = <<<EOF
     390  Start|http://school.info
     391  Info
     392  -Deutsch|http://school.info/de|Informationen in deutscher Sprache|de,de_du,de_kids
     393  --Nested under Deutsch
     394  kontaktieren Sie uns|contactus.php||de
     395  EOF;
     396  
     397          $definitiondedu = <<<EOF
     398  Start|http://school.info
     399  Info
     400  -Deutsch|http://school.info/de|Informationen in deutscher Sprache|de,de_du,de_kids
     401  --Nested under Deutsch
     402  EOF;
     403  
     404          $parsed = $this->custommenu_out(new custom_menu($definition));
     405          $parseden = $this->custommenu_out(new custom_menu($definition, 'en'));
     406          $parsedde = $this->custommenu_out(new custom_menu($definition, 'de'));
     407          $parseddedu = $this->custommenu_out(new custom_menu($definition, 'de_du'));
     408  
     409          $actualen = $this->custommenu_out(new custom_menu($definitionen, 'en'));
     410          $actualde = $this->custommenu_out(new custom_menu($definitionde, 'de'));
     411          $actualdedu = $this->custommenu_out(new custom_menu($definitiondedu, 'de_du'));
     412  
     413          $this->assertSame($actualen, $parseden, 'The parsed English menu does not match the expected English menu');
     414          $this->assertSame($actualde, $parsedde, 'The parsed German menu does not match the expected German menu');
     415          $this->assertSame($actualdedu, $parseddedu, 'The parsed German [Du] menu does not match the expected German [Du] menu');
     416  
     417          $this->assertNotSame($parsed, $parsedde, 'The menu without language is the same as the German menu. They should differ!');
     418          $this->assertNotSame($parsed, $parseden, 'The menu without language is the same as the English menu. They should differ!');
     419          $this->assertNotSame($parsed, $parseddedu, 'The menu without language is the same as the German [Du] menu. They should differ!');
     420          $this->assertNotSame($parseden, $parsedde, 'The English menu is the same as the German menu. They should differ!');
     421          $this->assertNotSame($parseden, $parseddedu, 'The English menu is the same as the German [Du] menu. They should differ!');
     422          $this->assertNotSame($parseddedu, $parsedde, 'The German [Du] menu is the same as the German menu. They should differ!');
     423      }
     424  
     425      /**
     426       * Support function that takes a custom_menu_item and converts it to a string.
     427       *
     428       * @param custom_menu_item $item
     429       * @param int $depth
     430       * @return string
     431       */
     432      protected function custommenu_out(custom_menu_item $item, $depth = 0) {
     433          $str = str_repeat('-', $depth);
     434          $str .= $item->get_text();
     435          $str .= '|' . $item->get_url();
     436          $str .= '|' . $item->get_title();
     437          if ($item->has_children()) {
     438              $str .= '|' . count($item->get_children());
     439              foreach ($item->get_children() as $child) {
     440                  $str .= "\n" . $this->custommenu_out($child, $depth + 1);
     441              }
     442          }
     443          return $str;
     444      }
     445  
     446      public function test_prepare() {
     447          $expecteda = array('<span class="current-page">1</span>',
     448                             '<a href="index.php?page=1">2</a>',
     449                             '<a href="index.php?page=2">3</a>',
     450                             '<a href="index.php?page=3">4</a>',
     451                             '<a href="index.php?page=4">5</a>',
     452                             '<a href="index.php?page=5">6</a>',
     453                             '<a href="index.php?page=6">7</a>',
     454                             '<a href="index.php?page=7">8</a>',
     455                             );
     456          $expectedb = array('<a href="page?page=3">4</a>',
     457                             '<a href="page?page=4">5</a>',
     458                             '<span class="current-page">6</span>',
     459                             '<a href="page?page=6">7</a>',
     460                             '<a href="page?page=7">8</a>',
     461                             );
     462  
     463          $mpage = new moodle_page();
     464          $rbase = new renderer_base($mpage, "/");
     465          $pbara = new paging_bar(40, 0, 5, 'index.php');
     466          $pbara->prepare($rbase, $mpage, "/");
     467          $pbarb = new paging_bar(100, 5, 5, 'page');
     468          $pbarb->maxdisplay = 5;
     469          $pbarb->prepare($rbase, $mpage, "/");
     470  
     471          $this->assertEquals($expecteda, $pbara->pagelinks);
     472          $this->assertEquals($expectedb, $pbarb->pagelinks);
     473      }
     474  
     475      public function test_pix_icon() {
     476          $this->resetAfterTest();
     477  
     478          $page = new moodle_page();
     479  
     480          set_config('theme', 'boost');
     481          // Need to reset after changing theme.
     482          $page->reset_theme_and_output();
     483          $renderer = $page->get_renderer('core');
     484  
     485          $reason = 'An icon with no alt text is hidden from screenreaders.';
     486          $this->assertStringContainsString('aria-hidden="true"', $renderer->pix_icon('t/print', ''), $reason);
     487  
     488          $reason = 'An icon with alt text is not hidden from screenreaders.';
     489          $this->assertStringNotContainsString('aria-hidden="true"', $renderer->pix_icon('t/print', 'Print'), $reason);
     490  
     491          // Test another theme with a different icon system.
     492          set_config('theme', 'classic');
     493          // Need to reset after changing theme.
     494          $page->reset_theme_and_output();
     495          $renderer = $page->get_renderer('core');
     496  
     497          $reason = 'An icon with no alt text is hidden from screenreaders.';
     498          $this->assertStringContainsString('aria-hidden="true"', $renderer->pix_icon('t/print', ''), $reason);
     499  
     500          $reason = 'An icon with alt text is not hidden from screenreaders.';
     501          $this->assertStringNotContainsString('aria-hidden="true"', $renderer->pix_icon('t/print', 'Print'), $reason);
     502      }
     503  
     504      /**
     505       * Test for checking the template context data for the single_select element.
     506       */
     507      public function test_single_select() {
     508          global $PAGE;
     509  
     510          $fakename = 'fakename';
     511          $fakeclass = 'fakeclass';
     512          $faketitle = 'faketitle';
     513          $fakedisabled = true;
     514          $fakefor = 'fakefor';
     515  
     516          $someid = 'someid';
     517          $realname = 'realname';
     518          $realclass = 'realclass';
     519          $realtitle = 'realtitle';
     520          $realdisabled = false;
     521          $reallabel = 'Some cool label';
     522          $labelclass = 'somelabelclass';
     523          $labelstyle = 'font-weight: bold';
     524  
     525          $dataaction = 'actiondata';
     526          $dataother = 'otherdata';
     527  
     528          $attributes = [
     529              'id' => $someid,
     530              'class' => $fakeclass,
     531              'title' => $faketitle,
     532              'disabled' => $fakedisabled,
     533              'name' => $fakename,
     534              'data-action' => $dataaction,
     535              'data-other' => $dataother,
     536          ];
     537          $labelattributes = [
     538              'for' => $fakefor,
     539              'class' => $labelclass,
     540              'style' => $labelstyle
     541          ];
     542  
     543          $options = [ "Option A", "Option B", "Option C" ];
     544          $nothing = ['' => 'choosedots'];
     545  
     546          $url = new moodle_url('/');
     547  
     548          $singleselect = new single_select($url, $realname, $options, null, $nothing, 'someformid');
     549          $singleselect->class = $realclass;
     550          $singleselect->tooltip = $realtitle;
     551          $singleselect->disabled = $realdisabled;
     552          $singleselect->attributes = $attributes;
     553          $singleselect->label = $reallabel;
     554          $singleselect->labelattributes = $labelattributes;
     555  
     556          $renderer = $PAGE->get_renderer('core');
     557          $data = $singleselect->export_for_template($renderer);
     558  
     559          $this->assertEquals($realtitle, $data->title);
     560          $this->assertEquals($singleselect->class, $data->classes);
     561          $this->assertEquals($realname, $data->name);
     562          $this->assertEquals($reallabel, $data->label);
     563          $this->assertEquals($realdisabled, $data->disabled);
     564          $this->assertEquals($someid, $data->id);
     565  
     566          // Validate attributes array.
     567          // The following should not be included: id, class, name, disabled.
     568          $this->assertFalse(in_array(['name' => 'id', 'value' => $someid], $data->attributes));
     569          $this->assertFalse(in_array(['name' => 'class', 'value' => $fakeclass], $data->attributes));
     570          $this->assertFalse(in_array(['name' => 'name', 'value' => $fakeclass], $data->attributes));
     571          $this->assertFalse(in_array(['name' => 'disabled', 'value' => $fakedisabled], $data->attributes));
     572          // The rest should be fine.
     573          $this->assertTrue(in_array(['name' => 'data-action', 'value' => $dataaction], $data->attributes));
     574          $this->assertTrue(in_array(['name' => 'data-other', 'value' => $dataother], $data->attributes));
     575  
     576          // Validate label attributes.
     577          // The for attribute should not be included.
     578          $this->assertFalse(in_array(['name' => 'for', 'value' => $someid], $data->labelattributes));
     579          // The rest should be fine.
     580          $this->assertTrue(in_array(['name' => 'class', 'value' => $labelclass], $data->labelattributes));
     581          $this->assertTrue(in_array(['name' => 'style', 'value' => $labelstyle], $data->labelattributes));
     582      }
     583  
     584      /**
     585       * Test for checking the template context data for the url_select element.
     586       */
     587      public function test_url_select() {
     588          global $PAGE;
     589  
     590          $fakename = 'fakename';
     591          $fakeclass = 'fakeclass';
     592          $faketitle = 'faketitle';
     593          $fakedisabled = true;
     594          $fakefor = 'fakefor';
     595  
     596          $someid = 'someid';
     597          $realclass = 'realclass';
     598          $realtitle = 'realtitle';
     599          $realdisabled = false;
     600          $reallabel = 'Some cool label';
     601          $labelclass = 'somelabelclass';
     602          $labelstyle = 'font-weight: bold';
     603  
     604          $dataaction = 'actiondata';
     605          $dataother = 'otherdata';
     606  
     607          $attributes = [
     608              'id' => $someid,
     609              'class' => $fakeclass,
     610              'title' => $faketitle,
     611              'disabled' => $fakedisabled,
     612              'name' => $fakename,
     613              'data-action' => $dataaction,
     614              'data-other' => $dataother,
     615          ];
     616          $labelattributes = [
     617              'for' => $fakefor,
     618              'class' => $labelclass,
     619              'style' => $labelstyle
     620          ];
     621  
     622          $url1 = new moodle_url("/#a");
     623          $url2 = new moodle_url("/#b");
     624          $url3 = new moodle_url("/#c");
     625  
     626          $urls = [
     627              $url1->out() => 'A',
     628              $url2->out() => 'B',
     629              $url3->out() => 'C',
     630          ];
     631          $nothing = ['' => 'choosedots'];
     632  
     633          $urlselect = new url_select($urls, null, $nothing, 'someformid');
     634          $urlselect->class = $realclass;
     635          $urlselect->tooltip = $realtitle;
     636          $urlselect->disabled = $realdisabled;
     637          $urlselect->attributes = $attributes;
     638          $urlselect->label = $reallabel;
     639          $urlselect->labelattributes = $labelattributes;
     640  
     641          $renderer = $PAGE->get_renderer('core');
     642          $data = $urlselect->export_for_template($renderer);
     643  
     644          $this->assertEquals($realtitle, $data->title);
     645          $this->assertEquals($urlselect->class, $data->classes);
     646          $this->assertEquals($reallabel, $data->label);
     647          $this->assertEquals($realdisabled, $data->disabled);
     648          $this->assertEquals($someid, $data->id);
     649  
     650          // Validate attributes array.
     651          // The following should not be included: id, class, name, disabled.
     652          $this->assertFalse(in_array(['name' => 'id', 'value' => $someid], $data->attributes));
     653          $this->assertFalse(in_array(['name' => 'class', 'value' => $fakeclass], $data->attributes));
     654          $this->assertFalse(in_array(['name' => 'name', 'value' => $fakeclass], $data->attributes));
     655          $this->assertFalse(in_array(['name' => 'disabled', 'value' => $fakedisabled], $data->attributes));
     656          // The rest should be fine.
     657          $this->assertTrue(in_array(['name' => 'data-action', 'value' => $dataaction], $data->attributes));
     658          $this->assertTrue(in_array(['name' => 'data-other', 'value' => $dataother], $data->attributes));
     659  
     660          // Validate label attributes.
     661          // The for attribute should not be included.
     662          $this->assertFalse(in_array(['name' => 'for', 'value' => $someid], $data->labelattributes));
     663          // The rest should be fine.
     664          $this->assertTrue(in_array(['name' => 'class', 'value' => $labelclass], $data->labelattributes));
     665          $this->assertTrue(in_array(['name' => 'style', 'value' => $labelstyle], $data->labelattributes));
     666      }
     667  
     668      /**
     669       * Data provider for test_block_contents_is_fake().
     670       *
     671       * @return array
     672       */
     673      public function block_contents_is_fake_provider() {
     674          return [
     675              'Null' => [null, false],
     676              'Not set' => [false, false],
     677              'Fake' => ['_fake', true],
     678              'Real block' => ['activity_modules', false],
     679          ];
     680      }
     681  
     682      /**
     683       * Test block_contents is_fake() method.
     684       *
     685       * @dataProvider block_contents_is_fake_provider
     686       * @param mixed $value Value for the data-block attribute
     687       * @param boolean $expected The expected result
     688       */
     689      public function test_block_contents_is_fake($value, $expected) {
     690          $bc = new block_contents(array());
     691          if ($value !== false) {
     692              $bc->attributes['data-block'] = $value;
     693          }
     694          $this->assertEquals($expected, $bc->is_fake());
     695      }
     696  }