Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * @covers \tool_usertours\step
31
 */
32
class step_test extends \advanced_testcase {
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
        return $DB;
68
    }
69
 
70
    /**
71
     * Data provider for the dirty value tester.
72
     *
73
     * @return array
74
     */
75
    public static function dirty_value_provider(): array {
76
        return
77
            [
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(): void {
113
        $step = $this->getMockBuilder(\tool_usertours\step::class)
114
            ->onlyMethods(['reload_from_record'])
115
            ->getMock();
116
 
117
        $idretval = rand(1, 100);
118
        $DB = $this->mock_database();
119
        $DB->method('get_record')
120
            ->willReturn($idretval);
121
 
122
        $retval = rand(1, 100);
123
        $step->expects($this->once())
124
            ->method('reload_from_record')
125
            ->with($this->equalTo($idretval))
126
            ->wilLReturn($retval);
127
 
128
        $rc = new \ReflectionClass(\tool_usertours\step::class);
129
        $rcm = $rc->getMethod('fetch');
130
 
131
        $id = rand(1, 100);
132
        $this->assertEquals($retval, $rcm->invoke($step, 'fetch', $id));
133
    }
134
 
135
    /**
136
     * Test that setters mark things as dirty.
137
     *
138
     * @dataProvider dirty_value_provider
139
     * @param   string  $name       The key to update
140
     * @param   string  $value      The value to set
141
     */
142
    public function test_dirty_values($name, $value): void {
143
        $step = new \tool_usertours\step();
144
        $method = 'set_' . $name;
145
        call_user_func_array([$step, $method], $value);
146
 
147
        $rc = new \ReflectionClass(\tool_usertours\step::class);
148
        $rcp = $rc->getProperty('dirty');
149
 
150
        $this->assertTrue($rcp->getValue($step));
151
    }
152
 
153
    /**
154
     * Provider for is_first_step.
155
     *
156
     * @return array
157
     */
158
    public static function step_sortorder_provider(): array {
159
        return [
160
            [0, 5, true, false],
161
            [1, 5, false, false],
162
            [4, 5, false, true],
163
        ];
164
    }
165
 
166
    /**
167
     * Test is_first_step.
168
     *
169
     * @dataProvider step_sortorder_provider
170
     * @param   int     $sortorder      The sortorder to check
171
     * @param   int     $count          Unused in this function
172
     * @param   bool    $isfirst        Whether this is the first step
173
     * @param   bool    $islast         Whether this is the last step
174
     */
175
    public function test_is_first_step($sortorder, $count, $isfirst, $islast): void {
176
        $step = $this->getMockBuilder(\tool_usertours\step::class)
177
            ->onlyMethods(['get_sortorder'])
178
            ->getMock();
179
 
180
        $step->expects($this->once())
181
            ->method('get_sortorder')
182
            ->willReturn($sortorder);
183
 
184
        $this->assertEquals($isfirst, $step->is_first_step());
185
    }
186
 
187
    /**
188
     * Test is_last_step.
189
     *
190
     * @dataProvider step_sortorder_provider
191
     * @param   int     $sortorder      The sortorder to check
192
     * @param   int     $count          Total number of steps for this test
193
     * @param   bool    $isfirst        Whether this is the first step
194
     * @param   bool    $islast         Whether this is the last step
195
     */
196
    public function test_is_last_step($sortorder, $count, $isfirst, $islast): void {
197
        $step = $this->getMockBuilder(\tool_usertours\step::class)
198
            ->onlyMethods(['get_sortorder', 'get_tour'])
199
            ->getMock();
200
 
201
        $tour = $this->getMockBuilder(\tool_usertours\tour::class)
202
            ->onlyMethods(['count_steps'])
203
            ->getMock();
204
 
205
        $step->expects($this->once())
206
            ->method('get_tour')
207
            ->willReturn($tour);
208
 
209
        $tour->expects($this->once())
210
            ->method('count_steps')
211
            ->willReturn($count);
212
 
213
        $step->expects($this->once())
214
            ->method('get_sortorder')
215
            ->willReturn($sortorder);
216
 
217
        $this->assertEquals($islast, $step->is_last_step());
218
    }
219
 
220
    /**
221
     * Test get_config with no keys provided.
222
     */
223
    public function test_get_config_no_keys(): void {
224
        $step = new \tool_usertours\step();
225
 
226
        $rc = new \ReflectionClass(\tool_usertours\step::class);
227
        $rcp = $rc->getProperty('config');
228
 
229
        $allvalues = (object) [
230
            'some' => 'value',
231
            'another' => 42,
232
            'key' => [
233
                'somethingelse',
234
            ],
235
        ];
236
 
237
        $rcp->setValue($step, $allvalues);
238
 
239
        $this->assertEquals($allvalues, $step->get_config());
240
    }
241
 
242
    /**
243
     * Data provider for get_config.
244
     *
245
     * @return array
246
     */
247
    public static function get_config_provider(): array {
248
        $allvalues = (object) [
249
            'some' => 'value',
250
            'another' => 42,
251
            'key' => [
252
                'somethingelse',
253
            ],
254
        ];
255
 
256
        $tourconfig = rand(1, 100);
257
        $forcedconfig = rand(1, 100);
258
 
259
        return [
260
            'No initial config' => [
261
                null,
262
                null,
263
                null,
264
                $tourconfig,
265
                false,
266
                $forcedconfig,
267
                (object) [],
268
            ],
269
            'All values' => [
270
                $allvalues,
271
                null,
272
                null,
273
                $tourconfig,
274
                false,
275
                $forcedconfig,
276
                $allvalues,
277
            ],
278
            'Valid string value' => [
279
                $allvalues,
280
                'some',
281
                null,
282
                $tourconfig,
283
                false,
284
                $forcedconfig,
285
                'value',
286
            ],
287
            'Valid array value' => [
288
                $allvalues,
289
                'key',
290
                null,
291
                $tourconfig,
292
                false,
293
                $forcedconfig,
294
                ['somethingelse'],
295
            ],
296
            'Invalid value' => [
297
                $allvalues,
298
                'notavalue',
299
                null,
300
                $tourconfig,
301
                false,
302
                $forcedconfig,
303
                $tourconfig,
304
            ],
305
            'Configuration value' => [
306
                $allvalues,
307
                'placement',
308
                null,
309
                $tourconfig,
310
                false,
311
                $forcedconfig,
312
                $tourconfig,
313
            ],
314
            'Invalid value with default' => [
315
                $allvalues,
316
                'notavalue',
317
                'somedefault',
318
                $tourconfig,
319
                false,
320
                $forcedconfig,
321
                'somedefault',
322
            ],
323
            'Value forced at target' => [
324
                $allvalues,
325
                'somevalue',
326
                'somedefault',
327
                $tourconfig,
328
                true,
329
                $forcedconfig,
330
                $forcedconfig,
331
            ],
332
        ];
333
    }
334
 
335
    /**
336
     * Test get_config with valid keys provided.
337
     *
338
     * @dataProvider get_config_provider
339
     * @param   object  $values     The config values
340
     * @param   string  $key        The key
341
     * @param   mixed   $default    The default value
342
     * @param   mixed   $tourconfig The tour config
343
     * @param   bool    $isforced   Whether the setting is forced
344
     * @param   mixed   $forcedvalue    The example value
345
     * @param   mixed   $expected   The expected value
346
     */
347
    public function test_get_config_valid_keys($values, $key, $default, $tourconfig, $isforced, $forcedvalue, $expected): void {
348
        $step = $this->getMockBuilder(\tool_usertours\step::class)
349
            ->onlyMethods(['get_target', 'get_targettype', 'get_tour'])
350
            ->getMock();
351
 
352
        $rc = new \ReflectionClass(\tool_usertours\step::class);
353
        $rcp = $rc->getProperty('config');
354
        $rcp->setValue($step, $values);
355
 
356
        $target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
357
            ->disableOriginalConstructor()
358
            ->getMock();
359
 
360
        $target->expects($this->any())
361
            ->method('is_setting_forced')
362
            ->willReturn($isforced);
363
 
364
        $target->expects($this->any())
365
            ->method('get_forced_setting_value')
366
            ->with($this->equalTo($key))
367
            ->willReturn($forcedvalue);
368
 
369
        $step->expects($this->any())
370
            ->method('get_targettype')
371
            ->willReturn('type');
372
 
373
        $step->expects($this->any())
374
            ->method('get_target')
375
            ->willReturn($target);
376
 
377
        $tour = $this->getMockBuilder(\tool_usertours\tour::class)
378
            ->getMock();
379
 
380
        $tour->expects($this->any())
381
            ->method('get_config')
382
            ->willReturn($tourconfig);
383
 
384
        $step->expects($this->any())
385
            ->method('get_tour')
386
            ->willReturn($tour);
387
 
388
        $this->assertEquals($expected, $step->get_config($key, $default));
389
    }
390
 
391
    /**
392
     * Data provider for set_config.
393
     */
394
    public static function set_config_provider(): array {
395
        $allvalues = (object) [
396
            'some' => 'value',
397
            'another' => 42,
398
            'key' => [
399
                'somethingelse',
400
            ],
401
        ];
402
 
403
        $randvalue = rand(1, 100);
404
 
405
        $provider = [];
406
 
407
        $newvalues = $allvalues;
408
        $newvalues->some = 'unset';
409
        $provider['Unset an existing value'] = [
410
            $allvalues,
411
            'some',
412
            null,
413
            $newvalues,
414
        ];
415
 
416
        $newvalues = $allvalues;
417
        $newvalues->some = $randvalue;
418
        $provider['Set an existing value'] = [
419
            $allvalues,
420
            'some',
421
            $randvalue,
422
            $newvalues,
423
        ];
424
 
425
        $provider['Set a new value'] = [
426
            $allvalues,
427
            'newkey',
428
            $randvalue,
429
            (object) array_merge((array) $allvalues, ['newkey' => $randvalue]),
430
        ];
431
 
432
        return $provider;
433
    }
434
 
435
    /**
436
     * Test that set_config works in the anticipated fashion.
437
     *
438
     * @dataProvider set_config_provider
439
     * @param   mixed   $initialvalues  The inital value to set
440
     * @param   string  $key        The key to test
441
     * @param   mixed   $newvalue   The new value to set
442
     * @param   mixed   $expected   The expected value
443
     */
444
    public function test_set_config($initialvalues, $key, $newvalue, $expected): void {
445
        $step = new \tool_usertours\step();
446
 
447
        $rc = new \ReflectionClass(\tool_usertours\step::class);
448
        $rcp = $rc->getProperty('config');
449
        $rcp->setValue($step, $initialvalues);
450
 
451
        $target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
452
            ->disableOriginalConstructor()
453
            ->getMock();
454
 
455
        $target->expects($this->any())
456
            ->method('is_setting_forced')
457
            ->willReturn(false);
458
 
459
        $step->set_config($key, $newvalue);
460
 
461
        $this->assertEquals($expected, $rcp->getValue($step));
462
    }
463
 
464
    /**
465
     * Ensure that non-dirty tours are not persisted.
466
     */
467
    public function test_persist_non_dirty(): void {
468
        $step = $this->getMockBuilder(\tool_usertours\step::class)
469
            ->onlyMethods([
470
                'to_record',
471
                'reload',
472
            ])
473
            ->getMock();
474
 
475
        $step->expects($this->never())
476
            ->method('to_record');
477
 
478
        $step->expects($this->never())
479
            ->method('reload');
480
 
481
        $this->assertSame($step, $step->persist());
482
    }
483
 
484
    /**
485
     * Ensure that new dirty steps are persisted.
486
     */
487
    public function test_persist_dirty_new(): void {
488
        // Mock the database.
489
        $DB = $this->mock_database();
490
        $DB->expects($this->once())
491
            ->method('insert_record')
492
            ->willReturn(42);
493
 
494
        // Mock the tour.
495
        $step = $this->getMockBuilder(\tool_usertours\step::class)
496
            ->onlyMethods([
497
                'to_record',
498
                'calculate_sortorder',
499
                'reload',
500
            ])
501
            ->getMock();
502
 
503
        $step->expects($this->once())
504
            ->method('to_record')
505
            ->willReturn((object)['id' => 42]);
506
 
507
        $step->expects($this->once())
508
            ->method('calculate_sortorder');
509
 
510
        $step->expects($this->once())
511
            ->method('reload');
512
 
513
        $rc = new \ReflectionClass(\tool_usertours\step::class);
514
        $rcp = $rc->getProperty('dirty');
515
        $rcp->setValue($step, true);
516
 
517
        $tour = $this->createMock(\tool_usertours\tour::class);
518
        $rcp = $rc->getProperty('tour');
519
        $rcp->setValue($step, $tour);
520
 
521
        $this->assertSame($step, $step->persist());
522
    }
523
 
524
    /**
525
     * Ensure that new non-dirty, forced steps are persisted.
526
     */
527
    public function test_persist_force_new(): void {
528
        global $DB;
529
 
530
        // Mock the database.
531
        $DB = $this->mock_database();
532
        $DB->expects($this->once())
533
            ->method('insert_record')
534
            ->willReturn(42);
535
 
536
        // Mock the tour.
537
        $step = $this->getMockBuilder(\tool_usertours\step::class)
538
            ->onlyMethods([
539
                'to_record',
540
                'calculate_sortorder',
541
                'reload',
542
            ])
543
            ->getMock();
544
 
545
        $step->expects($this->once())
546
            ->method('to_record')
547
            ->willReturn((object)['id' => 42]);
548
 
549
        $step->expects($this->once())
550
            ->method('calculate_sortorder');
551
 
552
        $step->expects($this->once())
553
            ->method('reload');
554
 
555
        $tour = $this->createMock(\tool_usertours\tour::class);
556
        $rc = new \ReflectionClass(\tool_usertours\step::class);
557
        $rcp = $rc->getProperty('tour');
558
        $rcp->setValue($step, $tour);
559
 
560
        $this->assertSame($step, $step->persist(true));
561
    }
562
 
563
    /**
564
     * Ensure that existing dirty steps are persisted.
565
     */
566
    public function test_persist_dirty_existing(): void {
567
        // Mock the database.
568
        $DB = $this->mock_database();
569
        $DB->expects($this->once())
570
            ->method('update_record');
571
 
572
        // Mock the tour.
573
        $step = $this->getMockBuilder(\tool_usertours\step::class)
574
            ->onlyMethods([
575
                'to_record',
576
                'calculate_sortorder',
577
                'reload',
578
            ])
579
            ->getMock();
580
 
581
        $step->expects($this->once())
582
            ->method('to_record')
583
            ->willReturn((object)['id' => 42]);
584
 
585
        $step->expects($this->never())
586
            ->method('calculate_sortorder');
587
 
588
        $step->expects($this->once())
589
            ->method('reload');
590
 
591
        $rc = new \ReflectionClass(\tool_usertours\step::class);
592
        $rcp = $rc->getProperty('id');
593
        $rcp->setValue($step, 42);
594
 
595
        $rcp = $rc->getProperty('dirty');
596
        $rcp->setValue($step, true);
597
 
598
        $tour = $this->createMock(\tool_usertours\tour::class);
599
        $rcp = $rc->getProperty('tour');
600
        $rcp->setValue($step, $tour);
601
 
602
        $this->assertSame($step, $step->persist());
603
    }
604
 
605
    /**
606
     * Ensure that existing non-dirty, forced steps are persisted.
607
     */
608
    public function test_persist_force_existing(): void {
609
        global $DB;
610
 
611
        // Mock the database.
612
        $DB = $this->mock_database();
613
        $DB->expects($this->once())
614
            ->method('update_record');
615
 
616
        // Mock the tour.
617
        $step = $this->getMockBuilder(\tool_usertours\step::class)
618
            ->onlyMethods([
619
                'to_record',
620
                'calculate_sortorder',
621
                'reload',
622
            ])
623
            ->getMock();
624
 
625
        $step->expects($this->once())
626
            ->method('to_record')
627
            ->willReturn((object) ['id' => 42]);
628
 
629
        $step->expects($this->never())
630
            ->method('calculate_sortorder');
631
 
632
        $step->expects($this->once())
633
            ->method('reload');
634
 
635
        $rc = new \ReflectionClass(\tool_usertours\step::class);
636
        $rcp = $rc->getProperty('id');
637
        $rcp->setValue($step, 42);
638
 
639
        $tour = $this->createMock(\tool_usertours\tour::class);
640
        $rcp = $rc->getProperty('tour');
641
        $rcp->setValue($step, $tour);
642
 
643
        $this->assertSame($step, $step->persist(true));
644
    }
645
 
646
    /**
647
     * Check that a tour which has never been persisted is removed correctly.
648
     */
649
    public function test_remove_non_persisted(): void {
650
        $step = $this->getMockBuilder(\tool_usertours\step::class)
651
            ->onlyMethods([])
652
            ->getMock();
653
 
654
        // Mock the database.
655
        $DB = $this->mock_database();
656
        $DB->expects($this->never())
657
            ->method('delete_records');
658
 
659
        $this->assertNull($step->remove());
660
    }
661
 
662
    /**
663
     * Check that a tour which has been persisted is removed correctly.
664
     */
665
    public function test_remove_persisted(): void {
666
        $id = rand(1, 100);
667
 
668
        $tour = $this->getMockBuilder(\tool_usertours\tour::class)
669
            ->onlyMethods([
670
                'reset_step_sortorder',
671
            ])
672
            ->getMock();
673
 
674
        $tour->expects($this->once())
675
            ->method('reset_step_sortorder');
676
 
677
        $step = $this->getMockBuilder(\tool_usertours\step::class)
678
            ->onlyMethods([
679
                'get_tour',
680
            ])
681
            ->getMock();
682
 
683
        $step->expects($this->once())
684
            ->method('get_tour')
685
            ->willReturn($tour);
686
 
687
        // Mock the database.
688
        $DB = $this->mock_database();
689
        $DB->expects($this->once())
690
            ->method('delete_records')
691
            ->with($this->equalTo('tool_usertours_steps'), $this->equalTo(['id' => $id]));
692
 
693
        $rc = new \ReflectionClass(\tool_usertours\step::class);
694
        $rcp = $rc->getProperty('id');
695
        $rcp->setValue($step, $id);
696
 
697
        $this->assertEquals($id, $step->get_id());
698
        $this->assertNull($step->remove());
699
    }
700
 
701
    /**
702
     * Data provider for the get_ tests.
703
     *
704
     * @return array
705
     */
706
    public static function getter_provider(): array {
707
        return [
708
            'id' => [
709
                'id',
710
                rand(1, 100),
711
            ],
712
            'tourid' => [
713
                'tourid',
714
                rand(1, 100),
715
            ],
716
            'title' => [
717
                'title',
718
                'Lorem',
719
            ],
720
            'content' => [
721
                'content',
722
                'Lorem',
723
            ],
724
            'targettype' => [
725
                'targettype',
726
                'Lorem',
727
            ],
728
            'targetvalue' => [
729
                'targetvalue',
730
                'Lorem',
731
            ],
732
            'sortorder' => [
733
                'sortorder',
734
                rand(1, 100),
735
            ],
736
        ];
737
    }
738
 
739
    /**
740
     * Test that getters return the configured value.
741
     *
742
     * @dataProvider getter_provider
743
     * @param   string  $key        The key to test
744
     * @param   mixed   $value      The expected value
745
     */
746
    public function test_getters($key, $value): void {
747
        $step = new \tool_usertours\step();
748
 
749
        $rc = new \ReflectionClass(\tool_usertours\step::class);
750
 
751
        $rcp = $rc->getProperty($key);
752
        $rcp->setValue($step, $value);
753
 
754
        $getter = 'get_' . $key;
755
 
756
        $this->assertEquals($value, $step->$getter());
757
    }
758
 
759
    /**
760
     * Ensure that the get_step_image_from_input function replace PIXICON placeholder with the correct images correctly.
761
     */
762
    public function test_get_step_image_from_input(): void {
763
        // Test step content with single image.
764
        $stepcontent = '@@PIXICON::tour/tour_mycourses::tool_usertours@@<br>Test';
765
        $stepcontent = \tool_usertours\step::get_step_image_from_input($stepcontent);
766
 
767
        // If the format is correct, PIXICON placeholder will be replaced with the img tag.
768
        $this->assertStringStartsWith('<img', $stepcontent);
769
        $this->assertStringEndsWith('Test', $stepcontent);
770
        $this->assertStringNotContainsString('PIXICON', $stepcontent);
771
 
772
        // Test step content with multiple images.
773
        $stepcontent =
774
            '@@PIXICON::tour/tour_mycourses::tool_usertours@@<br>Test<br>@@PIXICON::tour/tour_myhomepage::tool_usertours@@';
775
        $stepcontent = \tool_usertours\step::get_step_image_from_input($stepcontent);
776
        // If the format is correct, PIXICON placeholder will be replaced with the img tag.
777
        $this->assertStringStartsWith('<img', $stepcontent);
778
        // We should have 2 img tags here.
779
        $this->assertEquals(2, substr_count($stepcontent, '<img'));
780
        $this->assertStringNotContainsString('PIXICON', $stepcontent);
781
 
782
        // Test step content with incorrect format.
783
        $stepcontent = '@@PIXICON::tour/tour_mycourses<br>Test';
784
        $stepcontent = \tool_usertours\step::get_step_image_from_input($stepcontent);
785
 
786
        // If the format is not correct, PIXICON placeholder will not be replaced with the img tag.
787
        $this->assertStringStartsNotWith('<img', $stepcontent);
788
        $this->assertStringStartsWith('@@PIXICON', $stepcontent);
789
        $this->assertStringEndsWith('Test', $stepcontent);
790
        $this->assertStringContainsString('PIXICON', $stepcontent);
791
    }
792
}