Proyectos de Subversion Moodle

Rev

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