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