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 311 and 400] [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  namespace tool_usertours;
      18  
      19  defined('MOODLE_INTERNAL') || die();
      20  
      21  global $CFG;
      22  require_once($CFG->libdir . '/formslib.php');
      23  
      24  /**
      25   * Tests for step.
      26   *
      27   * @package    tool_usertours
      28   * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
      29   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      30   */
      31  class step_test extends \advanced_testcase {
      32  
      33      /**
      34       * @var moodle_database
      35       */
      36      protected $db;
      37  
      38      /**
      39       * Setup to store the DB reference.
      40       */
      41      public function setUp(): void {
      42          global $DB;
      43  
      44          $this->db = $DB;
      45      }
      46  
      47      /**
      48       * Tear down to restore the original DB reference.
      49       */
      50      public function tearDown(): void {
      51          global $DB;
      52  
      53          $DB = $this->db;
      54      }
      55  
      56      /**
      57       * Helper to mock the database.
      58       *
      59       * @return moodle_database
      60       */
      61      public function mock_database() {
      62          global $DB;
      63  
      64          $DB = $this->getMockBuilder('moodle_database')
      65              ->getMock()
      66              ;
      67  
      68          return $DB;
      69      }
      70  
      71      /**
      72       * Data provider for the dirty value tester.
      73       *
      74       * @return array
      75       */
      76      public function dirty_value_provider() {
      77          return [
      78                  'tourid' => [
      79                          'tourid',
      80                          [1],
      81                      ],
      82                  'title' => [
      83                          'title',
      84                          ['Lorem'],
      85                      ],
      86                  'content' => [
      87                          'content',
      88                          ['Lorem'],
      89                      ],
      90                  'targettype' => [
      91                          'targettype',
      92                          ['Lorem'],
      93                      ],
      94                  'targetvalue' => [
      95                          'targetvalue',
      96                          ['Lorem'],
      97                      ],
      98                  'sortorder' => [
      99                          'sortorder',
     100                          [1],
     101                      ],
     102                  'config' => [
     103                          'config',
     104                          ['key', 'value'],
     105                      ],
     106              ];
     107      }
     108  
     109      /**
     110       * Test the fetch function.
     111       */
     112      public function test_fetch() {
     113          $step = $this->getMockBuilder(\tool_usertours\step::class)
     114              ->onlyMethods(['reload_from_record'])
     115              ->getMock()
     116              ;
     117  
     118          $idretval = rand(1, 100);
     119          $DB = $this->mock_database();
     120          $DB->method('get_record')
     121              ->willReturn($idretval)
     122              ;
     123  
     124          $retval = rand(1, 100);
     125          $step->expects($this->once())
     126              ->method('reload_from_record')
     127              ->with($this->equalTo($idretval))
     128              ->wilLReturn($retval)
     129              ;
     130  
     131          $rc = new \ReflectionClass(\tool_usertours\step::class);
     132          $rcm = $rc->getMethod('fetch');
     133          $rcm->setAccessible(true);
     134  
     135          $id = rand(1, 100);
     136          $this->assertEquals($retval, $rcm->invoke($step, 'fetch', $id));
     137      }
     138  
     139      /**
     140       * Test that setters mark things as dirty.
     141       *
     142       * @dataProvider dirty_value_provider
     143       * @param   string  $name       The key to update
     144       * @param   string  $value      The value to set
     145       */
     146      public function test_dirty_values($name, $value) {
     147          $step = new \tool_usertours\step();
     148          $method = 'set_' . $name;
     149          call_user_func_array([$step, $method], $value);
     150  
     151          $rc = new \ReflectionClass(\tool_usertours\step::class);
     152          $rcp = $rc->getProperty('dirty');
     153          $rcp->setAccessible(true);
     154  
     155          $this->assertTrue($rcp->getValue($step));
     156      }
     157  
     158      /**
     159       * Provider for is_first_step.
     160       *
     161       * @return array
     162       */
     163      public function step_sortorder_provider() {
     164          return [
     165                  [0, 5, true, false],
     166                  [1, 5, false, false],
     167                  [4, 5, false, true],
     168              ];
     169      }
     170  
     171      /**
     172       * Test is_first_step.
     173       *
     174       * @dataProvider step_sortorder_provider
     175       * @param   int     $sortorder      The sortorder to check
     176       * @param   int     $count          Unused in this function
     177       * @param   bool    $isfirst        Whether this is the first step
     178       * @param   bool    $islast         Whether this is the last step
     179       */
     180      public function test_is_first_step($sortorder, $count, $isfirst, $islast) {
     181          $step = $this->getMockBuilder(\tool_usertours\step::class)
     182              ->onlyMethods(['get_sortorder'])
     183              ->getMock();
     184  
     185          $step->expects($this->once())
     186              ->method('get_sortorder')
     187              ->willReturn($sortorder)
     188              ;
     189  
     190          $this->assertEquals($isfirst, $step->is_first_step());
     191      }
     192  
     193      /**
     194       * Test is_last_step.
     195       *
     196       * @dataProvider step_sortorder_provider
     197       * @param   int     $sortorder      The sortorder to check
     198       * @param   int     $count          Total number of steps for this test
     199       * @param   bool    $isfirst        Whether this is the first step
     200       * @param   bool    $islast         Whether this is the last step
     201       */
     202      public function test_is_last_step($sortorder, $count, $isfirst, $islast) {
     203          $step = $this->getMockBuilder(\tool_usertours\step::class)
     204              ->onlyMethods(['get_sortorder', 'get_tour'])
     205              ->getMock();
     206  
     207          $tour = $this->getMockBuilder(\tool_usertours\tour::class)
     208              ->onlyMethods(['count_steps'])
     209              ->getMock();
     210  
     211          $step->expects($this->once())
     212              ->method('get_tour')
     213              ->willReturn($tour)
     214              ;
     215  
     216          $tour->expects($this->once())
     217              ->method('count_steps')
     218              ->willReturn($count)
     219              ;
     220  
     221          $step->expects($this->once())
     222              ->method('get_sortorder')
     223              ->willReturn($sortorder)
     224              ;
     225  
     226          $this->assertEquals($islast, $step->is_last_step());
     227      }
     228  
     229      /**
     230       * Test get_config with no keys provided.
     231       */
     232      public function test_get_config_no_keys() {
     233          $step = new \tool_usertours\step();
     234  
     235          $rc = new \ReflectionClass(\tool_usertours\step::class);
     236          $rcp = $rc->getProperty('config');
     237          $rcp->setAccessible(true);
     238  
     239          $allvalues = (object) [
     240                  'some' => 'value',
     241                  'another' => 42,
     242                  'key' => [
     243                      'somethingelse',
     244                  ],
     245              ];
     246  
     247          $rcp->setValue($step, $allvalues);
     248  
     249          $this->assertEquals($allvalues, $step->get_config());
     250      }
     251  
     252      /**
     253       * Data provider for get_config.
     254       *
     255       * @return array
     256       */
     257      public function get_config_provider() {
     258          $allvalues = (object) [
     259                  'some' => 'value',
     260                  'another' => 42,
     261                  'key' => [
     262                      'somethingelse',
     263                  ],
     264              ];
     265  
     266          $tourconfig = rand(1, 100);
     267          $forcedconfig = rand(1, 100);
     268  
     269          return [
     270                  'No initial config' => [
     271                          null,
     272                          null,
     273                          null,
     274                          $tourconfig,
     275                          false,
     276                          $forcedconfig,
     277                          (object) [],
     278                      ],
     279                  'All values' => [
     280                          $allvalues,
     281                          null,
     282                          null,
     283                          $tourconfig,
     284                          false,
     285                          $forcedconfig,
     286                          $allvalues,
     287                      ],
     288                  'Valid string value' => [
     289                          $allvalues,
     290                          'some',
     291                          null,
     292                          $tourconfig,
     293                          false,
     294                          $forcedconfig,
     295                          'value',
     296                      ],
     297                  'Valid array value' => [
     298                          $allvalues,
     299                          'key',
     300                          null,
     301                          $tourconfig,
     302                          false,
     303                          $forcedconfig,
     304                          ['somethingelse'],
     305                      ],
     306                  'Invalid value' => [
     307                          $allvalues,
     308                          'notavalue',
     309                          null,
     310                          $tourconfig,
     311                          false,
     312                          $forcedconfig,
     313                          $tourconfig,
     314                      ],
     315                  'Configuration value' => [
     316                          $allvalues,
     317                          'placement',
     318                          null,
     319                          $tourconfig,
     320                          false,
     321                          $forcedconfig,
     322                          $tourconfig,
     323                      ],
     324                  'Invalid value with default' => [
     325                          $allvalues,
     326                          'notavalue',
     327                          'somedefault',
     328                          $tourconfig,
     329                          false,
     330                          $forcedconfig,
     331                          'somedefault',
     332                      ],
     333                  'Value forced at target' => [
     334                          $allvalues,
     335                          'somevalue',
     336                          'somedefault',
     337                          $tourconfig,
     338                          true,
     339                          $forcedconfig,
     340                          $forcedconfig,
     341                      ],
     342              ];
     343      }
     344  
     345      /**
     346       * Test get_config with valid keys provided.
     347       *
     348       * @dataProvider get_config_provider
     349       * @param   object  $values     The config values
     350       * @param   string  $key        The key
     351       * @param   mixed   $default    The default value
     352       * @param   mixed   $tourconfig The tour config
     353       * @param   bool    $isforced   Whether the setting is forced
     354       * @param   mixed   $forcedvalue    The example value
     355       * @param   mixed   $expected   The expected value
     356       */
     357      public function test_get_config_valid_keys($values, $key, $default, $tourconfig, $isforced, $forcedvalue, $expected) {
     358          $step = $this->getMockBuilder(\tool_usertours\step::class)
     359              ->onlyMethods(['get_target', 'get_targettype', 'get_tour'])
     360              ->getMock();
     361  
     362          $rc = new \ReflectionClass(\tool_usertours\step::class);
     363          $rcp = $rc->getProperty('config');
     364          $rcp->setAccessible(true);
     365          $rcp->setValue($step, $values);
     366  
     367          $target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
     368              ->disableOriginalConstructor()
     369              ->getMock()
     370              ;
     371  
     372          $target->expects($this->any())
     373              ->method('is_setting_forced')
     374              ->willReturn($isforced)
     375              ;
     376  
     377          $target->expects($this->any())
     378              ->method('get_forced_setting_value')
     379              ->with($this->equalTo($key))
     380              ->willReturn($forcedvalue)
     381              ;
     382  
     383          $step->expects($this->any())
     384              ->method('get_targettype')
     385              ->willReturn('type')
     386              ;
     387  
     388          $step->expects($this->any())
     389              ->method('get_target')
     390              ->willReturn($target)
     391              ;
     392  
     393          $tour = $this->getMockBuilder(\tool_usertours\tour::class)
     394              ->getMock()
     395              ;
     396  
     397          $tour->expects($this->any())
     398              ->method('get_config')
     399              ->willReturn($tourconfig)
     400              ;
     401  
     402          $step->expects($this->any())
     403              ->method('get_tour')
     404              ->willReturn($tour)
     405              ;
     406  
     407          $this->assertEquals($expected, $step->get_config($key, $default));
     408      }
     409  
     410      /**
     411       * Data provider for set_config.
     412       */
     413      public function set_config_provider() {
     414          $allvalues = (object) [
     415                  'some' => 'value',
     416                  'another' => 42,
     417                  'key' => [
     418                      'somethingelse',
     419                  ],
     420              ];
     421  
     422          $randvalue = rand(1, 100);
     423  
     424          $provider = [];
     425  
     426          $newvalues = $allvalues;
     427          $newvalues->some = 'unset';
     428          $provider['Unset an existing value'] = [
     429                  $allvalues,
     430                  'some',
     431                  null,
     432                  $newvalues,
     433              ];
     434  
     435          $newvalues = $allvalues;
     436          $newvalues->some = $randvalue;
     437          $provider['Set an existing value'] = [
     438                  $allvalues,
     439                  'some',
     440                  $randvalue,
     441                  $newvalues,
     442              ];
     443  
     444          $provider['Set a new value'] = [
     445                  $allvalues,
     446                  'newkey',
     447                  $randvalue,
     448                  (object) array_merge((array) $allvalues, ['newkey' => $randvalue]),
     449              ];
     450  
     451          return $provider;
     452      }
     453  
     454      /**
     455       * Test that set_config works in the anticipated fashion.
     456       *
     457       * @dataProvider set_config_provider
     458       * @param   mixed   $initialvalues  The inital value to set
     459       * @param   string  $key        The key to test
     460       * @param   mixed   $newvalue   The new value to set
     461       * @param   mixed   $expected   The expected value
     462       */
     463      public function test_set_config($initialvalues, $key, $newvalue, $expected) {
     464          $step = new \tool_usertours\step();
     465  
     466          $rc = new \ReflectionClass(\tool_usertours\step::class);
     467          $rcp = $rc->getProperty('config');
     468          $rcp->setAccessible(true);
     469          $rcp->setValue($step, $initialvalues);
     470  
     471          $target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
     472              ->disableOriginalConstructor()
     473              ->getMock()
     474              ;
     475  
     476          $target->expects($this->any())
     477              ->method('is_setting_forced')
     478              ->willReturn(false)
     479              ;
     480  
     481          $step->set_config($key, $newvalue);
     482  
     483          $this->assertEquals($expected, $rcp->getValue($step));
     484      }
     485  
     486      /**
     487       * Ensure that non-dirty tours are not persisted.
     488       */
     489      public function test_persist_non_dirty() {
     490          $step = $this->getMockBuilder(\tool_usertours\step::class)
     491              ->onlyMethods([
     492                      'to_record',
     493                      'reload',
     494                  ])
     495              ->getMock()
     496              ;
     497  
     498          $step->expects($this->never())
     499              ->method('to_record')
     500              ;
     501  
     502          $step->expects($this->never())
     503              ->method('reload')
     504              ;
     505  
     506          $this->assertSame($step, $step->persist());
     507      }
     508  
     509      /**
     510       * Ensure that new dirty steps are persisted.
     511       */
     512      public function test_persist_dirty_new() {
     513          // Mock the database.
     514          $DB = $this->mock_database();
     515          $DB->expects($this->once())
     516              ->method('insert_record')
     517              ->willReturn(42)
     518              ;
     519  
     520          // Mock the tour.
     521          $step = $this->getMockBuilder(\tool_usertours\step::class)
     522              ->onlyMethods([
     523                      'to_record',
     524                      'calculate_sortorder',
     525                      'reload',
     526                  ])
     527              ->getMock()
     528              ;
     529  
     530          $step->expects($this->once())
     531              ->method('to_record')
     532              ->willReturn((object)['id' => 42]);
     533              ;
     534  
     535          $step->expects($this->once())
     536              ->method('calculate_sortorder')
     537              ;
     538  
     539          $step->expects($this->once())
     540              ->method('reload')
     541              ;
     542  
     543          $rc = new \ReflectionClass(\tool_usertours\step::class);
     544          $rcp = $rc->getProperty('dirty');
     545          $rcp->setAccessible(true);
     546          $rcp->setValue($step, true);
     547  
     548          $tour = $this->createMock(\tool_usertours\tour::class);
     549          $rcp = $rc->getProperty('tour');
     550          $rcp->setAccessible(true);
     551          $rcp->setValue($step, $tour);
     552  
     553          $this->assertSame($step, $step->persist());
     554      }
     555  
     556      /**
     557       * Ensure that new non-dirty, forced steps are persisted.
     558       */
     559      public function test_persist_force_new() {
     560          global $DB;
     561  
     562          // Mock the database.
     563          $DB = $this->mock_database();
     564          $DB->expects($this->once())
     565              ->method('insert_record')
     566              ->willReturn(42)
     567              ;
     568  
     569          // Mock the tour.
     570          $step = $this->getMockBuilder(\tool_usertours\step::class)
     571              ->onlyMethods([
     572                      'to_record',
     573                      'calculate_sortorder',
     574                      'reload',
     575                  ])
     576              ->getMock()
     577              ;
     578  
     579          $step->expects($this->once())
     580              ->method('to_record')
     581              ->willReturn((object)['id' => 42]);
     582              ;
     583  
     584          $step->expects($this->once())
     585              ->method('calculate_sortorder')
     586              ;
     587  
     588          $step->expects($this->once())
     589              ->method('reload')
     590              ;
     591  
     592          $tour = $this->createMock(\tool_usertours\tour::class);
     593          $rc = new \ReflectionClass(\tool_usertours\step::class);
     594          $rcp = $rc->getProperty('tour');
     595          $rcp->setAccessible(true);
     596          $rcp->setValue($step, $tour);
     597  
     598          $this->assertSame($step, $step->persist(true));
     599      }
     600  
     601      /**
     602       * Ensure that existing dirty steps are persisted.
     603       */
     604      public function test_persist_dirty_existing() {
     605          // Mock the database.
     606          $DB = $this->mock_database();
     607          $DB->expects($this->once())
     608              ->method('update_record')
     609              ;
     610  
     611          // Mock the tour.
     612          $step = $this->getMockBuilder(\tool_usertours\step::class)
     613              ->onlyMethods([
     614                      'to_record',
     615                      'calculate_sortorder',
     616                      'reload',
     617                  ])
     618              ->getMock()
     619              ;
     620  
     621          $step->expects($this->once())
     622              ->method('to_record')
     623              ->willReturn((object)['id' => 42]);
     624              ;
     625  
     626          $step->expects($this->never())
     627              ->method('calculate_sortorder')
     628              ;
     629  
     630          $step->expects($this->once())
     631              ->method('reload')
     632              ;
     633  
     634          $rc = new \ReflectionClass(\tool_usertours\step::class);
     635          $rcp = $rc->getProperty('id');
     636          $rcp->setAccessible(true);
     637          $rcp->setValue($step, 42);
     638  
     639          $rcp = $rc->getProperty('dirty');
     640          $rcp->setAccessible(true);
     641          $rcp->setValue($step, true);
     642  
     643          $tour = $this->createMock(\tool_usertours\tour::class);
     644          $rcp = $rc->getProperty('tour');
     645          $rcp->setAccessible(true);
     646          $rcp->setValue($step, $tour);
     647  
     648          $this->assertSame($step, $step->persist());
     649      }
     650  
     651      /**
     652       * Ensure that existing non-dirty, forced steps are persisted.
     653       */
     654      public function test_persist_force_existing() {
     655          global $DB;
     656  
     657          // Mock the database.
     658          $DB = $this->mock_database();
     659          $DB->expects($this->once())
     660              ->method('update_record')
     661              ;
     662  
     663          // Mock the tour.
     664          $step = $this->getMockBuilder(\tool_usertours\step::class)
     665              ->onlyMethods([
     666                      'to_record',
     667                      'calculate_sortorder',
     668                      'reload',
     669                  ])
     670              ->getMock()
     671              ;
     672  
     673          $step->expects($this->once())
     674              ->method('to_record')
     675              ->willReturn((object)['id' => 42]);
     676              ;
     677  
     678          $step->expects($this->never())
     679              ->method('calculate_sortorder')
     680              ;
     681  
     682          $step->expects($this->once())
     683              ->method('reload')
     684              ;
     685  
     686          $rc = new \ReflectionClass(\tool_usertours\step::class);
     687          $rcp = $rc->getProperty('id');
     688          $rcp->setAccessible(true);
     689          $rcp->setValue($step, 42);
     690  
     691          $tour = $this->createMock(\tool_usertours\tour::class);
     692          $rcp = $rc->getProperty('tour');
     693          $rcp->setAccessible(true);
     694          $rcp->setValue($step, $tour);
     695  
     696          $this->assertSame($step, $step->persist(true));
     697      }
     698  
     699      /**
     700       * Check that a tour which has never been persisted is removed correctly.
     701       */
     702      public function test_remove_non_persisted() {
     703          $step = $this->getMockBuilder(\tool_usertours\step::class)
     704              ->onlyMethods([])
     705              ->getMock()
     706              ;
     707  
     708          // Mock the database.
     709          $DB = $this->mock_database();
     710          $DB->expects($this->never())
     711              ->method('delete_records')
     712              ;
     713  
     714          $this->assertNull($step->remove());
     715      }
     716  
     717      /**
     718       * Check that a tour which has been persisted is removed correctly.
     719       */
     720      public function test_remove_persisted() {
     721          $id = rand(1, 100);
     722  
     723          $tour = $this->getMockBuilder(\tool_usertours\tour::class)
     724              ->onlyMethods([
     725                      'reset_step_sortorder',
     726                  ])
     727              ->getMock()
     728              ;
     729  
     730          $tour->expects($this->once())
     731              ->method('reset_step_sortorder')
     732              ;
     733  
     734          $step = $this->getMockBuilder(\tool_usertours\step::class)
     735              ->onlyMethods([
     736                      'get_tour',
     737                  ])
     738              ->getMock()
     739              ;
     740  
     741          $step->expects($this->once())
     742              ->method('get_tour')
     743              ->willReturn($tour)
     744              ;
     745  
     746          // Mock the database.
     747          $DB = $this->mock_database();
     748          $DB->expects($this->once())
     749              ->method('delete_records')
     750              ->with($this->equalTo('tool_usertours_steps'), $this->equalTo(['id' => $id]))
     751              ;
     752  
     753          $rc = new \ReflectionClass(\tool_usertours\step::class);
     754          $rcp = $rc->getProperty('id');
     755          $rcp->setAccessible(true);
     756          $rcp->setValue($step, $id);
     757  
     758          $this->assertEquals($id, $step->get_id());
     759          $this->assertNull($step->remove());
     760      }
     761  
     762      /**
     763       * Data provider for the get_ tests.
     764       *
     765       * @return array
     766       */
     767      public function getter_provider() {
     768          return [
     769                  'id' => [
     770                          'id',
     771                          rand(1, 100),
     772                      ],
     773                  'tourid' => [
     774                          'tourid',
     775                          rand(1, 100),
     776                      ],
     777                  'title' => [
     778                          'title',
     779                          'Lorem',
     780                      ],
     781                  'content' => [
     782                          'content',
     783                          'Lorem',
     784                      ],
     785                  'targettype' => [
     786                          'targettype',
     787                          'Lorem',
     788                      ],
     789                  'targetvalue' => [
     790                          'targetvalue',
     791                          'Lorem',
     792                      ],
     793                  'sortorder' => [
     794                          'sortorder',
     795                          rand(1, 100),
     796                      ],
     797              ];
     798      }
     799  
     800      /**
     801       * Test that getters return the configured value.
     802       *
     803       * @dataProvider getter_provider
     804       * @param   string  $key        The key to test
     805       * @param   mixed   $value      The expected value
     806       */
     807      public function test_getters($key, $value) {
     808          $step = new \tool_usertours\step();
     809  
     810          $rc = new \ReflectionClass(\tool_usertours\step::class);
     811  
     812          $rcp = $rc->getProperty($key);
     813          $rcp->setAccessible(true);
     814          $rcp->setValue($step, $value);
     815  
     816          $getter = 'get_' . $key;
     817  
     818          $this->assertEquals($value, $step->$getter());
     819      }
     820  
     821      /**
     822       * Data Provider for get_string_from_input.
     823       *
     824       * @return array
     825       */
     826      public function get_string_from_input_provider() {
     827          return [
     828              'Text'  => [
     829                  'example',
     830                  'example',
     831              ],
     832              'Text which looks like a langstring' => [
     833                  'example,fakecomponent',
     834                  'example,fakecomponent',
     835              ],
     836              'Text which is a langstring' => [
     837                  'administration,core',
     838                  'Administration',
     839              ],
     840              'Text which is a langstring but uses "moodle" instead of "core"' => [
     841                  'administration,moodle',
     842                  'Administration',
     843              ],
     844              'Text which is a langstring, but with extra whitespace' => [
     845                  '  administration,moodle  ',
     846                  'Administration',
     847              ],
     848              'Looks like a langstring, but has incorrect space around comma' => [
     849                  'administration , moodle',
     850                  'administration , moodle',
     851              ],
     852          ];
     853      }
     854  
     855      /**
     856       * Ensure that the get_string_from_input function returns langstring strings correctly.
     857       *
     858       * @dataProvider get_string_from_input_provider
     859       * @param   string  $string     The string to test
     860       * @param   string  $expected   The expected result
     861       */
     862      public function test_get_string_from_input($string, $expected) {
     863          $this->assertEquals($expected, \tool_usertours\step::get_string_from_input($string));
     864      }
     865  }