See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401]
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 tour. 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 tour_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 \PHPUnit\Framework\MockObject\MockObject 60 */ 61 public function mock_database() { 62 global $DB; 63 64 $DB = $this->getMockBuilder(\moodle_database::class) 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 'name' => [ 79 'name', 80 ['Lorem'], 81 ], 82 'description' => [ 83 'description', 84 ['Lorem'], 85 ], 86 'pathmatch' => [ 87 'pathmatch', 88 ['Lorem'], 89 ], 90 'enabled' => [ 91 'enabled', 92 ['Lorem'], 93 ], 94 'sortorder' => [ 95 'sortorder', 96 [1], 97 ], 98 'config' => [ 99 'config', 100 ['key', 'value'], 101 ], 102 ]; 103 } 104 105 /** 106 * Test that setters mark things as dirty. 107 * 108 * @dataProvider dirty_value_provider 109 * @param string $name The name of the key being tested 110 * @param mixed $value The value being set 111 */ 112 public function test_dirty_values($name, $value) { 113 $tour = new \tool_usertours\tour(); 114 $method = 'set_' . $name; 115 call_user_func_array([$tour, $method], $value); 116 117 $rc = new \ReflectionClass(\tool_usertours\tour::class); 118 $rcp = $rc->getProperty('dirty'); 119 $rcp->setAccessible(true); 120 121 $this->assertTrue($rcp->getValue($tour)); 122 } 123 124 /** 125 * Data provider for the get_ tests. 126 * 127 * @return array 128 */ 129 public function getter_provider() { 130 return [ 131 'id' => [ 132 'id', 133 rand(1, 100), 134 ], 135 'name' => [ 136 'name', 137 'Lorem', 138 ], 139 'description' => [ 140 'description', 141 'Lorem', 142 ], 143 'pathmatch' => [ 144 'pathmatch', 145 'Lorem', 146 ], 147 'enabled' => [ 148 'enabled', 149 'Lorem', 150 ], 151 'sortorder' => [ 152 'sortorder', 153 rand(1, 100), 154 ], 155 'config' => [ 156 'config', 157 ['key', 'value'], 158 ], 159 ]; 160 } 161 162 /** 163 * Test that getters return the configured value. 164 * 165 * @dataProvider getter_provider 166 * @param string $key The name of the key being tested 167 * @param mixed $value The value being set 168 */ 169 public function test_getters($key, $value) { 170 $tour = new \tool_usertours\tour(); 171 172 $rc = new \ReflectionClass(tour::class); 173 174 $rcp = $rc->getProperty($key); 175 $rcp->setAccessible(true); 176 $rcp->setValue($tour, $value); 177 178 $getter = 'get_' . $key; 179 180 $this->assertEquals($value, $tour->$getter()); 181 } 182 183 /** 184 * Ensure that non-dirty tours are not persisted. 185 */ 186 public function test_persist_non_dirty() { 187 $tour = $this->getMockBuilder(tour::class) 188 ->onlyMethods(['to_record']) 189 ->getMock() 190 ; 191 192 $tour->expects($this->never()) 193 ->method('to_record') 194 ; 195 196 $this->assertSame($tour, $tour->persist()); 197 } 198 199 /** 200 * Ensure that new dirty tours are persisted. 201 */ 202 public function test_persist_dirty_new() { 203 // Mock the database. 204 $DB = $this->mock_database(); 205 206 $DB->expects($this->never()) 207 ->method('update_record') 208 ; 209 210 $id = rand(1, 100); 211 $DB->expects($this->once()) 212 ->method('insert_record') 213 ->willReturn($id) 214 ; 215 216 // Mock the tour. 217 $tour = $this->getMockBuilder(tour::class) 218 ->onlyMethods([ 219 'to_record', 220 'reload', 221 ]) 222 ->getMock() 223 ; 224 225 $tour->expects($this->once()) 226 ->method('to_record') 227 ; 228 229 $tour->expects($this->once()) 230 ->method('reload') 231 ; 232 233 $rc = new \ReflectionClass(tour::class); 234 235 $rcp = $rc->getProperty('dirty'); 236 $rcp->setAccessible(true); 237 $rcp->setValue($tour, true); 238 239 $this->assertSame($tour, $tour->persist()); 240 241 $rcp = $rc->getProperty('id'); 242 $rcp->setAccessible(true); 243 $this->assertEquals($id, $rcp->getValue($tour)); 244 } 245 246 /** 247 * Ensure that non-dirty, forced tours are persisted. 248 */ 249 public function test_persist_force_new() { 250 global $DB; 251 252 // Mock the database. 253 $DB = $this->mock_database(); 254 255 $DB->expects($this->never()) 256 ->method('update_record') 257 ; 258 259 $id = rand(1, 100); 260 $DB->expects($this->once()) 261 ->method('insert_record') 262 ->willReturn($id) 263 ; 264 265 // Mock the tour. 266 $tour = $this->getMockBuilder(tour::class) 267 ->onlyMethods([ 268 'to_record', 269 'reload', 270 ]) 271 ->getMock() 272 ; 273 274 $tour->expects($this->once()) 275 ->method('to_record') 276 ; 277 278 $tour->expects($this->once()) 279 ->method('reload') 280 ; 281 282 $this->assertSame($tour, $tour->persist(true)); 283 284 $rc = new \ReflectionClass(tour::class); 285 $rcp = $rc->getProperty('id'); 286 $rcp->setAccessible(true); 287 $this->assertEquals($id, $rcp->getValue($tour)); 288 } 289 290 /** 291 * Ensure that dirty tours are persisted. 292 */ 293 public function test_persist_dirty_existing() { 294 // Mock the database. 295 $DB = $this->mock_database(); 296 $DB->expects($this->once()) 297 ->method('update_record') 298 ->willReturn($this->returnSelf()) 299 ; 300 301 $DB->expects($this->never()) 302 ->method('insert_record') 303 ; 304 305 // Mock the tour. 306 $tour = $this->getMockBuilder(tour::class) 307 ->onlyMethods([ 308 'to_record', 309 'reload', 310 ]) 311 ->getMock() 312 ; 313 314 $tour->expects($this->once()) 315 ->method('to_record') 316 ; 317 318 $tour->expects($this->once()) 319 ->method('reload') 320 ; 321 322 $rc = new \ReflectionClass(tour::class); 323 324 $rcp = $rc->getProperty('id'); 325 $rcp->setAccessible(true); 326 $rcp->setValue($tour, 42); 327 328 $rcp = $rc->getProperty('dirty'); 329 $rcp->setAccessible(true); 330 $rcp->setValue($tour, true); 331 332 $this->assertSame($tour, $tour->persist()); 333 } 334 335 /** 336 * Ensure that non-dirty, forced tours are persisted. 337 */ 338 public function test_persist_force() { 339 global $DB; 340 341 // Mock the database. 342 $DB = $this->mock_database(); 343 344 $DB->expects($this->once()) 345 ->method('update_record') 346 ->willReturn($this->returnSelf()) 347 ; 348 349 $DB->expects($this->never()) 350 ->method('insert_record') 351 ; 352 353 // Mock the tour. 354 $tour = $this->getMockBuilder(tour::class) 355 ->onlyMethods([ 356 'to_record', 357 'reload', 358 ]) 359 ->getMock() 360 ; 361 362 $tour->expects($this->once()) 363 ->method('to_record') 364 ; 365 366 $tour->expects($this->once()) 367 ->method('reload') 368 ; 369 370 $rc = new \ReflectionClass(tour::class); 371 372 $rcp = $rc->getProperty('id'); 373 $rcp->setAccessible(true); 374 $rcp->setValue($tour, 42); 375 376 $rcp = $rc->getProperty('dirty'); 377 $rcp->setAccessible(true); 378 $rcp->setValue($tour, true); 379 380 $this->assertSame($tour, $tour->persist(true)); 381 } 382 383 /** 384 * Test setting config. 385 */ 386 public function test_set_config() { 387 $tour = new \tool_usertours\tour(); 388 389 $tour->set_config('key', 'value'); 390 $tour->set_config('another', [ 391 'foo' => 'bar', 392 ]); 393 394 $rc = new \ReflectionClass(tour::class); 395 $rcp = $rc->getProperty('config'); 396 $rcp->setAccessible(true); 397 $this->assertEquals((object) [ 398 'key' => 'value', 399 'another' => [ 400 'foo' => 'bar', 401 ], 402 ], $rcp->getValue($tour)); 403 } 404 405 /** 406 * Test get_config with no keys provided. 407 */ 408 public function test_get_config_no_keys() { 409 $tour = new \tool_usertours\tour(); 410 411 $rc = new \ReflectionClass(tour::class); 412 $rcp = $rc->getProperty('config'); 413 $rcp->setAccessible(true); 414 415 $allvalues = (object) [ 416 'some' => 'value', 417 'another' => 42, 418 'key' => [ 419 'somethingelse', 420 ], 421 ]; 422 423 $rcp->setValue($tour, $allvalues); 424 425 $this->assertEquals($allvalues, $tour->get_config()); 426 } 427 428 /** 429 * Data provider for get_config. 430 * 431 * @return array 432 */ 433 public function get_config_provider() { 434 $allvalues = (object) [ 435 'some' => 'value', 436 'another' => 42, 437 'key' => [ 438 'somethingelse', 439 ], 440 ]; 441 442 return [ 443 'No nitial config' => [ 444 null, 445 null, 446 null, 447 (object) [], 448 ], 449 'All values' => [ 450 $allvalues, 451 null, 452 null, 453 $allvalues, 454 ], 455 'Valid string value' => [ 456 $allvalues, 457 'some', 458 null, 459 'value', 460 ], 461 'Valid array value' => [ 462 $allvalues, 463 'key', 464 null, 465 ['somethingelse'], 466 ], 467 'Invalid value' => [ 468 $allvalues, 469 'notavalue', 470 null, 471 null, 472 ], 473 'Configuration value' => [ 474 $allvalues, 475 'placement', 476 null, 477 \tool_usertours\configuration::get_default_value('placement'), 478 ], 479 'Invalid value with default' => [ 480 $allvalues, 481 'notavalue', 482 'somedefault', 483 'somedefault', 484 ], 485 ]; 486 } 487 488 /** 489 * Test get_config with valid keys provided. 490 * 491 * @dataProvider get_config_provider 492 * @param object $values The config values 493 * @param string $key The key 494 * @param mixed $default The default value 495 * @param mixed $expected The expected value 496 */ 497 public function test_get_config_valid_keys($values, $key, $default, $expected) { 498 $tour = new \tool_usertours\tour(); 499 500 $rc = new \ReflectionClass(tour::class); 501 $rcp = $rc->getProperty('config'); 502 $rcp->setAccessible(true); 503 $rcp->setValue($tour, $values); 504 505 $this->assertEquals($expected, $tour->get_config($key, $default)); 506 } 507 508 /** 509 * Check that a tour which has never been persisted is removed correctly. 510 */ 511 public function test_remove_non_persisted() { 512 $tour = $this->getMockBuilder(tour::class) 513 ->onlyMethods([ 514 'get_steps', 515 ]) 516 ->getMock() 517 ; 518 519 $tour->expects($this->never()) 520 ->method('get_steps') 521 ; 522 523 // Mock the database. 524 $DB = $this->mock_database(); 525 $DB->expects($this->never()) 526 ->method('delete_records') 527 ; 528 529 $this->assertNull($tour->remove()); 530 } 531 532 /** 533 * Check that a tour which has been persisted is removed correctly. 534 */ 535 public function test_remove_persisted() { 536 $id = rand(1, 100); 537 538 $tour = $this->getMockBuilder(tour::class) 539 ->onlyMethods([ 540 'get_steps', 541 ]) 542 ->getMock() 543 ; 544 545 $rc = new \ReflectionClass(tour::class); 546 $rcp = $rc->getProperty('id'); 547 $rcp->setAccessible(true); 548 $rcp->setValue($tour, $id); 549 550 $step = $this->getMockBuilder(\tool_usertours\step::class) 551 ->onlyMethods([ 552 'remove', 553 ]) 554 ->getMock() 555 ; 556 557 $tour->expects($this->once()) 558 ->method('get_steps') 559 ->willReturn([$step]) 560 ; 561 562 // Mock the database. 563 $DB = $this->mock_database(); 564 565 $DB->expects($this->exactly(3)) 566 ->method('delete_records') 567 ->withConsecutive( 568 [$this->equalTo('tool_usertours_tours'), $this->equalTo(['id' => $id])], 569 [$this->equalTo('user_preferences'), $this->equalTo(['name' => tour::TOUR_LAST_COMPLETED_BY_USER . $id])], 570 [$this->equalTo('user_preferences'), $this->equalTo(['name' => tour::TOUR_REQUESTED_BY_USER . $id])] 571 ) 572 ->willReturn(null) 573 ; 574 575 $DB->expects($this->once()) 576 ->method('get_records') 577 ->with($this->equalTo('tool_usertours_tours'), $this->equalTo(null)) 578 ->willReturn([]) 579 ; 580 581 $this->assertNull($tour->remove()); 582 } 583 584 /** 585 * Teset that sortorder is reset according to sortorder with values from 0. 586 */ 587 public function test_reset_step_sortorder() { 588 $tour = new \tool_usertours\tour(); 589 590 $mockdata = []; 591 for ($i = 4; $i >= 0; $i--) { 592 $id = rand($i * 10, ($i * 10) + 9); 593 $mockdata[] = (object) ['id' => $id]; 594 $expectations[] = [$this->equalTo('tool_usertours_steps'), $this->equalTo('sortorder'), 4 - $i, ['id' => $id]]; 595 } 596 597 // Mock the database. 598 $DB = $this->mock_database(); 599 $DB->expects($this->once()) 600 ->method('get_records') 601 ->willReturn($mockdata) 602 ; 603 604 $setfield = $DB->expects($this->exactly(5)) 605 ->method('set_field') 606 ; 607 call_user_func_array([$setfield, 'withConsecutive'], $expectations); 608 609 $tour->reset_step_sortorder(); 610 } 611 612 /** 613 * Test that a disabled tour should never be shown to users. 614 */ 615 public function test_should_show_for_user_disabled() { 616 $tour = new \tool_usertours\tour(); 617 $tour->set_enabled(false); 618 619 $this->assertFalse($tour->should_show_for_user()); 620 } 621 622 /** 623 * Provider for should_show_for_user. 624 * 625 * @return array 626 */ 627 public function should_show_for_user_provider() { 628 $time = time(); 629 return [ 630 'Not seen by user at all' => [ 631 null, 632 null, 633 null, 634 true, 635 ], 636 'Completed by user before majorupdatetime' => [ 637 $time - DAYSECS, 638 null, 639 $time, 640 true, 641 ], 642 'Completed by user since majorupdatetime' => [ 643 $time, 644 null, 645 $time - DAYSECS, 646 false, 647 ], 648 'Requested by user before current completion' => [ 649 $time, 650 $time - DAYSECS, 651 null, 652 false, 653 ], 654 'Requested by user since completion' => [ 655 $time - DAYSECS, 656 $time, 657 null, 658 true, 659 ], 660 ]; 661 } 662 663 /** 664 * Test that a disabled tour should never be shown to users. 665 * 666 * @dataProvider should_show_for_user_provider 667 * @param mixed $completiondate The user's completion date for this tour 668 * @param mixed $requesteddate The user's last requested date for this tour 669 * @param mixed $updateddate The date this tour was last updated 670 * @param string $expectation The expected tour key 671 */ 672 public function test_should_show_for_user($completiondate, $requesteddate, $updateddate, $expectation) { 673 // Uses user preferences so we must be in a user context. 674 $this->resetAfterTest(); 675 $this->setAdminUser(); 676 677 $tour = $this->getMockBuilder(tour::class) 678 ->onlyMethods([ 679 'get_id', 680 'get_config', 681 'is_enabled', 682 ]) 683 ->getMock() 684 ; 685 686 $tour->method('is_enabled') 687 ->willReturn(true) 688 ; 689 690 $id = rand(1, 100); 691 $tour->method('get_id') 692 ->willReturn($id) 693 ; 694 695 if ($completiondate !== null) { 696 set_user_preference(\tool_usertours\tour::TOUR_LAST_COMPLETED_BY_USER . $id, $completiondate); 697 } 698 699 if ($requesteddate !== null) { 700 set_user_preference(\tool_usertours\tour::TOUR_REQUESTED_BY_USER . $id, $requesteddate); 701 } 702 703 if ($updateddate !== null) { 704 $tour->expects($this->once()) 705 ->method('get_config') 706 ->willReturn($updateddate) 707 ; 708 } 709 710 $this->assertEquals($expectation, $tour->should_show_for_user()); 711 } 712 713 /** 714 * Provider for get_tour_key. 715 * 716 * @return array 717 */ 718 public function get_tour_key_provider() { 719 $id = rand(1, 100); 720 $time = time(); 721 722 return [ 723 'No initial values' => [ 724 $id, 725 [null, $time], 726 $this->greaterThanOrEqual($time), 727 true, 728 null, 729 sprintf('tool_usertours_\d_%d_%s', $id, $time), 730 ], 731 732 'Initial tour time, no user pref' => [ 733 $id, 734 [$time], 735 null, 736 false, 737 null, 738 sprintf('tool_usertours_\d_%d_%s', $id, $time), 739 ], 740 'Initial tour time, with user reset lower' => [ 741 $id, 742 [$time], 743 null, 744 false, 745 $time - DAYSECS, 746 sprintf('tool_usertours_\d_%d_%s', $id, $time), 747 ], 748 'Initial tour time, with user reset higher' => [ 749 $id, 750 [$time], 751 null, 752 false, 753 $time + DAYSECS, 754 sprintf('tool_usertours_\d_%d_%s', $id, $time + DAYSECS), 755 ], 756 ]; 757 } 758 759 /** 760 * Test that get_tour_key provides the anticipated unique keys. 761 * 762 * @dataProvider get_tour_key_provider 763 * @param int $id The tour ID 764 * @param array $getconfig The mocked values for get_config calls 765 * @param array $setconfig The mocked values for set_config calls 766 * @param bool $willpersist Whether a persist is expected 767 * @param mixed $userpref The value to set for the user preference 768 * @param string $expectation The expected tour key 769 */ 770 public function test_get_tour_key($id, $getconfig, $setconfig, $willpersist, $userpref, $expectation) { 771 // Uses user preferences so we must be in a user context. 772 $this->resetAfterTest(); 773 $this->setAdminUser(); 774 775 $tour = $this->getMockBuilder(tour::class) 776 ->onlyMethods([ 777 'get_config', 778 'set_config', 779 'get_id', 780 'persist', 781 ]) 782 ->getMock() 783 ; 784 785 if ($getconfig) { 786 $tour->expects($this->exactly(count($getconfig))) 787 ->method('get_config') 788 ->will(call_user_func_array([$this, 'onConsecutiveCalls'], $getconfig)) 789 ; 790 } 791 792 if ($setconfig) { 793 $tour->expects($this->once()) 794 ->method('set_config') 795 ->with($this->equalTo('majorupdatetime'), $setconfig) 796 ->will($this->returnSelf()) 797 ; 798 } else { 799 $tour->expects($this->never()) 800 ->method('set_config') 801 ; 802 } 803 804 if ($willpersist) { 805 $tour->expects($this->once()) 806 ->method('persist') 807 ; 808 } else { 809 $tour->expects($this->never()) 810 ->method('persist') 811 ; 812 } 813 814 $tour->expects($this->any()) 815 ->method('get_id') 816 ->willReturn($id) 817 ; 818 819 if ($userpref !== null) { 820 set_user_preference(\tool_usertours\tour::TOUR_REQUESTED_BY_USER . $id, $userpref); 821 } 822 823 $this->assertMatchesRegularExpression( 824 '/' . $expectation . '/', 825 $tour->get_tour_key() 826 ); 827 } 828 829 /** 830 * Ensure that the request_user_reset function sets an appropriate value for the tour. 831 */ 832 public function test_requested_user_reset() { 833 $tour = $this->getMockBuilder(tour::class) 834 ->onlyMethods([ 835 'get_id', 836 ]) 837 ->getMock() 838 ; 839 840 $id = rand(1, 100); 841 $time = time(); 842 843 $tour->expects($this->once()) 844 ->method('get_id') 845 ->willReturn($id) 846 ; 847 848 $tour->request_user_reset(); 849 850 $this->assertGreaterThanOrEqual($time, get_user_preferences(\tool_usertours\tour::TOUR_REQUESTED_BY_USER . $id)); 851 } 852 853 /** 854 * Ensure that the request_user_reset function sets an appropriate value for the tour. 855 */ 856 public function test_mark_user_completed() { 857 $tour = $this->getMockBuilder(tour::class) 858 ->onlyMethods([ 859 'get_id', 860 ]) 861 ->getMock() 862 ; 863 864 $id = rand(1, 100); 865 $time = time(); 866 867 $tour->expects($this->once()) 868 ->method('get_id') 869 ->willReturn($id) 870 ; 871 872 $tour->mark_user_completed(); 873 874 $this->assertGreaterThanOrEqual($time, get_user_preferences(\tool_usertours\tour::TOUR_LAST_COMPLETED_BY_USER . $id)); 875 } 876 877 /** 878 * Provider for the is_first_tour and is_last_tour tests. 879 * 880 * @return array 881 */ 882 public function sortorder_first_last_provider() { 883 $topcount = rand(10, 100); 884 return [ 885 'Only tour => first + last' => [ 886 0, 887 true, 888 1, 889 true, 890 ], 891 'First tour of many' => [ 892 0, 893 true, 894 $topcount, 895 false, 896 ], 897 'Last tour of many' => [ 898 $topcount - 1, 899 false, 900 $topcount, 901 true, 902 ], 903 'Middle tour of many' => [ 904 5, 905 false, 906 $topcount, 907 false, 908 ], 909 ]; 910 } 911 912 /** 913 * Test the is_first_tour() function. 914 * 915 * @dataProvider sortorder_first_last_provider 916 * @param int $sortorder The new sort order 917 * @param bool $isfirst Whether this is the first tour 918 * @param int $total The number of tours 919 * @param bool $islast Whether this is the last tour 920 */ 921 public function test_is_first_tour($sortorder, $isfirst, $total, $islast) { 922 $tour = new \tool_usertours\tour(); 923 924 $rc = new \ReflectionClass(tour::class); 925 $rcp = $rc->getProperty('sortorder'); 926 $rcp->setAccessible(true); 927 $rcp->setValue($tour, $sortorder); 928 929 $this->assertEquals($isfirst, $tour->is_first_tour()); 930 } 931 932 /** 933 * Test the is_last_tour() function. 934 * 935 * @dataProvider sortorder_first_last_provider 936 * @param int $sortorder The new sort order 937 * @param bool $isfirst Whether this is the first tour 938 * @param int $total The number of tours 939 * @param bool $islast Whether this is the last tour 940 */ 941 public function test_is_last_tour_calculated($sortorder, $isfirst, $total, $islast) { 942 $tour = new \tool_usertours\tour(); 943 944 $rc = new \ReflectionClass(tour::class); 945 $rcp = $rc->getProperty('sortorder'); 946 $rcp->setAccessible(true); 947 $rcp->setValue($tour, $sortorder); 948 949 // The total will be calculated. 950 $DB = $this->mock_database(); 951 $DB->expects($this->once()) 952 ->method('count_records') 953 ->willReturn($total) 954 ; 955 $this->assertEquals($islast, $tour->is_last_tour()); 956 } 957 958 /** 959 * Test the is_last_tour() function. 960 * 961 * @dataProvider sortorder_first_last_provider 962 * @param int $sortorder The new sort order 963 * @param bool $isfirst Whether this is the first tour 964 * @param int $total The number of tours 965 * @param bool $islast Whether this is the last tour 966 */ 967 public function test_is_last_tour_provided($sortorder, $isfirst, $total, $islast) { 968 $tour = new \tool_usertours\tour(); 969 970 $rc = new \ReflectionClass(tour::class); 971 $rcp = $rc->getProperty('sortorder'); 972 $rcp->setAccessible(true); 973 $rcp->setValue($tour, $sortorder); 974 975 // The total is provided. 976 // No DB calls expected. 977 $DB = $this->mock_database(); 978 $DB->expects($this->never()) 979 ->method('count_records') 980 ->willReturn(0) 981 ; 982 $this->assertEquals($islast, $tour->is_last_tour($total)); 983 } 984 985 /** 986 * Data provider for the get_filter_values tests. 987 * 988 * @return array 989 */ 990 public function get_filter_values_provider() { 991 $cheese = ['cheddar', 'boursin', 'mozzarella']; 992 $horses = ['coolie', 'dakota', 'leo', 'twiggy']; 993 return [ 994 'No config' => [ 995 [], 996 'cheese', 997 [], 998 ], 999 'Some config for another filter' => [ 1000 [ 1001 'horses' => $horses, 1002 ], 1003 'cheese', 1004 [], 1005 ], 1006 'Some config for this filter' => [ 1007 [ 1008 'horses' => $horses, 1009 ], 1010 'horses', 1011 $horses, 1012 ], 1013 'Some config for several filters' => [ 1014 [ 1015 'horses' => $horses, 1016 'cheese' => $cheese 1017 ], 1018 'horses', 1019 $horses, 1020 ], 1021 ]; 1022 } 1023 1024 /** 1025 * Tests for the get_filter_values function. 1026 * 1027 * @dataProvider get_filter_values_provider 1028 * @param array $fullconfig The config value being tested 1029 * @param string $filtername The name of the filter being tested 1030 * @param array $expectedvalues The expected result 1031 */ 1032 public function test_get_filter_values($fullconfig, $filtername, $expectedvalues) { 1033 $tour = $this->getMockBuilder(tour::class) 1034 ->onlyMethods(['get_config']) 1035 ->getMock(); 1036 1037 $tour->expects($this->once()) 1038 ->method('get_config') 1039 ->will($this->returnValue($fullconfig)); 1040 1041 $this->assertEquals($expectedvalues, $tour->get_filter_values($filtername)); 1042 } 1043 1044 /** 1045 * Data provider for set_filter_values tests. 1046 * 1047 * @return array 1048 */ 1049 public function set_filter_values_provider() { 1050 $cheese = ['cheddar', 'boursin', 'mozzarella']; 1051 $horses = ['coolie', 'dakota', 'leo', 'twiggy']; 1052 1053 return [ 1054 'No initial value' => [ 1055 [], 1056 'cheese', 1057 $cheese, 1058 ['cheese' => $cheese], 1059 ], 1060 'Existing filter merged' => [ 1061 ['horses' => $horses], 1062 'cheese', 1063 $cheese, 1064 ['horses' => $horses, 'cheese' => $cheese], 1065 ], 1066 'Existing filter updated' => [ 1067 ['cheese' => $cheese], 1068 'cheese', 1069 ['cheddar'], 1070 ['cheese' => ['cheddar']], 1071 ], 1072 'Existing filter updated with merge' => [ 1073 ['horses' => $horses, 'cheese' => $cheese], 1074 'cheese', 1075 ['cheddar'], 1076 ['horses' => $horses, 'cheese' => ['cheddar']], 1077 ], 1078 ]; 1079 } 1080 1081 /** 1082 * Base tests for set_filter_values. 1083 * 1084 * @dataProvider set_filter_values_provider 1085 * @param array $currentvalues The current value 1086 * @param string $filtername The name of the filter to add to 1087 * @param array $newvalues The new values to store 1088 * @param array $expectedvalues The combined values 1089 */ 1090 public function test_set_filter_values_merge($currentvalues, $filtername, $newvalues, $expectedvalues) { 1091 $tour = $this->getMockBuilder(tour::class) 1092 ->onlyMethods(['get_config', 'set_config']) 1093 ->getMock(); 1094 1095 $tour->expects($this->once()) 1096 ->method('get_config') 1097 ->will($this->returnValue($currentvalues)); 1098 1099 $tour->expects($this->once()) 1100 ->method('set_config') 1101 ->with( 1102 $this->equalTo('filtervalues'), 1103 $this->equalTo($expectedvalues) 1104 ); 1105 1106 $tour->set_filter_values($filtername, $newvalues); 1107 } 1108 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body