Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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
/**
18
 * Tests for class core_course_category methods invoking hooks.
19
 *
20
 * @package    core_course
21
 * @category   test
22
 * @copyright  2020 Ruslan Kabalin
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
namespace core_course;
27
 
28
defined('MOODLE_INTERNAL') || die();
29
 
30
global $CFG;
31
require_once($CFG->dirroot . '/course/tests/fixtures/mock_hooks.php');
32
 
33
use PHPUnit\Framework\MockObject\MockObject;
34
use core_course\test\mock_hooks;
35
 
36
/**
37
 * Functional test for class core_course_category methods invoking hooks.
38
 */
39
class category_hooks_test extends \advanced_testcase {
40
 
41
    protected function setUp(): void {
42
        $this->resetAfterTest();
43
        $this->setAdminUser();
44
    }
45
 
46
    /**
47
     * Provides mocked category configured for named callback function.
48
     *
49
     * get_plugins_callback_function will return callable prefixed with `tool_unittest_`,
50
     * the actual callbacks are defined in mock_hooks.php fixture file.
51
     *
52
     * @param core_course_category $category Category to mock
53
     * @param string $callback Callback function used in method we test.
54
     * @return MockObject
55
     */
56
    public function get_mock_category(\core_course_category $category, string $callback = ''): MockObject {
57
        // Setup mock object for \core_course_category.
58
        // Disable original constructor, since we can't use it directly since it is private.
59
        $mockcategory = $this->getMockBuilder(\core_course_category::class)
60
            ->onlyMethods(['get_plugins_callback_function'])
61
            ->disableOriginalConstructor()
62
            ->getMock();
63
 
64
        // Define get_plugins_callback_function use and return value.
65
        if (!empty($callback)) {
66
            $mockcategory->method('get_plugins_callback_function')
67
                ->with($this->equalTo($callback))
68
                ->willReturn(['tool_unittest_' . $callback]);
69
        }
70
 
71
        // Modify constructor visibility and invoke mock object with real object.
72
        // This is used to overcome private constructor.
73
        $reflected = new \ReflectionClass(\core_course_category::class);
74
        $constructor = $reflected->getConstructor();
75
        $constructor->invoke($mockcategory, $category->get_db_record());
76
 
77
        return $mockcategory;
78
    }
79
 
80
    public function test_can_course_category_delete_hook() {
81
        $category1 = \core_course_category::create(array('name' => 'Cat1'));
82
        $category2 = \core_course_category::create(array('name' => 'Cat2', 'parent' => $category1->id));
83
        $category3 = \core_course_category::create(array('name' => 'Cat3'));
84
 
85
        $mockcategory2 = $this->get_mock_category($category2, 'can_course_category_delete');
86
 
87
        // Add course to mocked clone of category2.
88
        $course1 = $this->getDataGenerator()->create_course(array('category' => $mockcategory2->id));
89
 
90
        // Now configure fixture to return false for the callback.
91
        mock_hooks::set_can_course_category_delete_return(false);
92
        $this->assertFalse($mockcategory2->can_delete_full($category3->id));
93
 
94
        // Now configure fixture to return true for the callback.
95
        mock_hooks::set_can_course_category_delete_return(true);
96
        $this->assertTrue($mockcategory2->can_delete_full($category3->id));
97
 
98
        // Verify passed arguments.
99
        $arguments = mock_hooks::get_calling_arguments();
100
        $this->assertCount(1, $arguments);
101
 
102
        // Argument 1 is the same core_course_category instance.
103
        $argument = array_shift($arguments);
104
        $this->assertSame($mockcategory2, $argument);
105
    }
106
 
107
    public function test_can_course_category_delete_move_hook() {
108
        $category1 = \core_course_category::create(array('name' => 'Cat1'));
109
        $category2 = \core_course_category::create(array('name' => 'Cat2', 'parent' => $category1->id));
110
        $category3 = \core_course_category::create(array('name' => 'Cat3'));
111
 
112
        $mockcategory2 = $this->get_mock_category($category2, 'can_course_category_delete_move');
113
 
114
        // Add course to mocked clone of category2.
115
        $course1 = $this->getDataGenerator()->create_course(array('category' => $mockcategory2->id));
116
 
117
        // Now configure fixture to return false for the callback.
118
        mock_hooks::set_can_course_category_delete_move_return(false);
119
        $this->assertFalse($mockcategory2->can_move_content_to($category3->id));
120
 
121
        // Now configure fixture to return true for the callback.
122
        mock_hooks::set_can_course_category_delete_move_return(true);
123
        $this->assertTrue($mockcategory2->can_move_content_to($category3->id));
124
 
125
        // Verify passed arguments.
126
        $arguments = mock_hooks::get_calling_arguments();
127
        $this->assertCount(2, $arguments);
128
 
129
        // Argument 1 is the same core_course_category instance.
130
        $argument = array_shift($arguments);
131
        $this->assertSame($mockcategory2, $argument);
132
 
133
        // Argument 2 is referring to category 3.
134
        $argument = array_shift($arguments);
135
        $this->assertInstanceOf(\core_course_category::class, $argument);
136
        $this->assertEquals($category3->id, $argument->id);
137
    }
138
 
139
    public function test_pre_course_category_delete_hook() {
140
        $category1 = \core_course_category::create(array('name' => 'Cat1'));
141
        $category2 = \core_course_category::create(array('name' => 'Cat2', 'parent' => $category1->id));
142
 
143
        $mockcategory2 = $this->get_mock_category($category2, 'pre_course_category_delete');
144
        $mockcategory2->delete_full();
145
 
146
        // Verify passed arguments.
147
        $arguments = mock_hooks::get_calling_arguments();
148
        $this->assertCount(1, $arguments);
149
 
150
        // Argument 1 is the category object.
151
        $argument = array_shift($arguments);
152
        $this->assertEquals($mockcategory2->get_db_record(), $argument);
153
    }
154
 
155
    public function test_pre_course_category_delete_move_hook() {
156
        $category1 = \core_course_category::create(array('name' => 'Cat1'));
157
        $category2 = \core_course_category::create(array('name' => 'Cat2', 'parent' => $category1->id));
158
        $category3 = \core_course_category::create(array('name' => 'Cat3'));
159
 
160
        $mockcategory2 = $this->get_mock_category($category2, 'pre_course_category_delete_move');
161
 
162
        // Add course to mocked clone of category2.
163
        $course1 = $this->getDataGenerator()->create_course(array('category' => $mockcategory2->id));
164
 
165
        $mockcategory2->delete_move($category3->id);
166
 
167
        // Verify passed arguments.
168
        $arguments = mock_hooks::get_calling_arguments();
169
        $this->assertCount(2, $arguments);
170
 
171
        // Argument 1 is the same core_course_category instance.
172
        $argument = array_shift($arguments);
173
        $this->assertSame($mockcategory2, $argument);
174
 
175
        // Argument 2 is referring to category 3.
176
        $argument = array_shift($arguments);
177
        $this->assertInstanceOf(\core_course_category::class, $argument);
178
        $this->assertEquals($category3->id, $argument->id);
179
    }
180
 
181
    public function test_get_course_category_contents_hook() {
182
        $category1 = \core_course_category::create(array('name' => 'Cat1'));
183
        $category2 = \core_course_category::create(array('name' => 'Cat2', 'parent' => $category1->id));
184
 
185
        $mockcategory2 = $this->get_mock_category($category2);
186
 
187
        // Define get_plugins_callback_function use in the mock, it is called twice for different callback in the form.
188
        $mockcategory2->expects($this->exactly(2))
189
            ->method('get_plugins_callback_function')
190
            ->withConsecutive(
191
                [$this->equalTo('can_course_category_delete')],
192
                [$this->equalTo('get_course_category_contents')]
193
            )
194
            ->willReturn(
195
                ['tool_unittest_can_course_category_delete'],
196
                ['tool_unittest_get_course_category_contents']
197
            );
198
 
199
        // Now configure fixture to return string for the callback.
200
        $content = 'Bunch of test artefacts';
201
        mock_hooks::set_get_course_category_contents_return($content);
202
 
203
        $mform = new \core_course_deletecategory_form(null, $mockcategory2);
204
        $this->expectOutputRegex("/<li>$content<\/li>/");
205
        $mform->display();
206
 
207
        // Verify passed arguments.
208
        $arguments = mock_hooks::get_calling_arguments();
209
        $this->assertCount(1, $arguments);
210
 
211
        // Argument 1 is the same core_course_category instance.
212
        $argument = array_shift($arguments);
213
        $this->assertSame($mockcategory2, $argument);
214
    }
215
}