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 ltiservice_gradebookservices;
18
 
19
use ltiservice_gradebookservices\local\service\gradebookservices;
20
 
21
/**
22
 * Unit tests for lti gradebookservices.
23
 *
24
 * @package    ltiservice_gradebookservices
25
 * @category   test
26
 * @copyright  2020 Claude Vervoort <claude.vervoort@cengage.com>
27
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28
 * @coversDefaultClass \mod_lti\service\gradebookservices\local\gradebookservices
29
 */
30
class gradebookservices_test extends \advanced_testcase {
31
    /**
32
     * Load the necessary libs for the tests.
33
     */
34
    public static function setUpBeforeClass(): void {
35
        global $CFG;
36
        require_once($CFG->dirroot . '/mod/lti/locallib.php');
37
    }
38
 
39
    /**
40
     * @covers ::instance_added
41
     *
42
     * Test saving a graded LTI with resource and tag info (as a result of
43
     * content item selection) creates a gradebookservices record
44
     * that can be retrieved using the gradebook service API.
45
     */
11 efrain 46
    public function test_lti_add_coupled_lineitem(): void {
1 efrain 47
        $this->resetAfterTest();
48
        $this->setAdminUser();
49
 
50
        // Create a tool type, associated with that proxy.
51
 
52
        $typeid = $this->create_type();
53
        $course = $this->getDataGenerator()->create_course();
54
        $resourceid = 'test-resource-id';
55
        $tag = 'tag';
56
        $subreviewurl = 'https://subreview.example.com';
57
        $subreviewparams = 'a=2';
58
 
59
        $ltiinstance = $this->create_graded_lti($typeid, $course, $resourceid, $tag, $subreviewurl, $subreviewparams);
60
 
61
        $this->assertNotNull($ltiinstance);
62
 
63
        $gbs = gradebookservices::find_ltiservice_gradebookservice_for_lti($ltiinstance->id);
64
 
65
        $this->assertNotNull($gbs);
66
        $this->assertEquals($resourceid, $gbs->resourceid);
67
        $this->assertEquals($tag, $gbs->tag);
68
        $this->assertEquals($subreviewurl, $gbs->subreviewurl);
69
        $this->assertEquals($subreviewparams, $gbs->subreviewparams);
70
        $this->assert_lineitems($course, $typeid, $ltiinstance->name,
71
            $ltiinstance, $resourceid, $tag, $subreviewurl, $subreviewparams);
72
    }
73
 
74
    /**
75
     * @covers ::instance_added
76
     *
77
     * Test saving a graded LTI with resource and tag info (as a result of
78
     * content item selection) creates a gradebookservices record
79
     * that can be retrieved using the gradebook service API.
80
     */
11 efrain 81
    public function test_lti_add_coupled_lineitem_default_subreview(): void {
1 efrain 82
        $this->resetAfterTest();
83
        $this->setAdminUser();
84
 
85
        // Create a tool type, associated with that proxy.
86
 
87
        $typeid = $this->create_type();
88
        $course = $this->getDataGenerator()->create_course();
89
        $resourceid = 'test-resource-id';
90
        $tag = 'tag';
91
 
92
        $ltiinstance = $this->create_graded_lti($typeid, $course, $resourceid, $tag, 'DEFAULT');
93
 
94
        $this->assertNotNull($ltiinstance);
95
 
96
        $gbs = gradebookservices::find_ltiservice_gradebookservice_for_lti($ltiinstance->id);
97
 
98
        $this->assertNotNull($gbs);
99
        $this->assertEquals('DEFAULT', $gbs->subreviewurl);
100
        $this->assert_lineitems($course, $typeid, $ltiinstance->name, $ltiinstance, $resourceid, $tag, 'DEFAULT');
101
    }
102
 
103
    /**
104
     * @covers ::add_standalone_lineitem
105
     *
106
     * Test saving a standalone LTI lineitem with resource and tag info
107
     * that can be retrieved using the gradebook service API.
108
     */
11 efrain 109
    public function test_lti_add_standalone_lineitem(): void {
1 efrain 110
        $this->resetAfterTest();
111
        $this->setAdminUser();
112
 
113
        $course = $this->getDataGenerator()->create_course();
114
        $resourceid = "test-resource-standalone";
115
        $tag = "test-tag-standalone";
116
        $typeid = $this->create_type();
117
 
118
        $this->create_standalone_lineitem($course->id, $typeid, $resourceid, $tag);
119
 
120
        $this->assert_lineitems($course, $typeid, "manualtest", null, $resourceid, $tag);
121
    }
122
 
123
    /**
124
     * @covers ::find_ltiservice_gradebookservice_for_lti
125
     *
126
     * Test line item URL is populated for coupled line item only
127
     * if there is not another line item bound to the lti instance,
128
     * since in that case there would be no rule to define which of
129
     * the line items should be actually passed.
130
     */
11 efrain 131
    public function test_get_launch_parameters_coupled(): void {
1 efrain 132
        $this->resetAfterTest();
133
        $this->setAdminUser();
134
 
135
        // Create a tool type, associated with that proxy.
136
 
137
        $typeid = $this->create_type();
138
        $course = $this->getDataGenerator()->create_course();
139
 
140
        $ltiinstance = $this->create_graded_lti($typeid, $course, 'resource-id', 'tag', 'https://subreview.url', 'sub=review');
141
 
142
        $this->assertNotNull($ltiinstance);
143
 
144
        $gbservice = new gradebookservices();
145
        $params = $gbservice->get_launch_parameters('basic-lti-launch-request', $course->id, 111, $typeid, $ltiinstance->id);
146
        $this->assertEquals('$LineItem.url', $params['lineitem_url']);
147
        $this->assertEquals('$LineItem.url', $params['lineitem_url']);
148
 
149
        $this->create_standalone_lineitem($course->id, $typeid, 'resource-id', 'tag', $ltiinstance->id);
150
        $params = $gbservice->get_launch_parameters('basic-lti-launch-request', $course->id, 111, $typeid, $ltiinstance->id);
151
        $this->assertEquals('$LineItems.url', $params['lineitems_url']);
152
        // 2 line items for a single link, we cannot return a single line item url.
153
        $this->assertFalse(array_key_exists('$LineItem.url', $params));
154
    }
155
 
156
    /**
157
     * @covers ::override_endpoint
158
     *
159
     * Test Submission Review URL and custom parameter is applied when the
160
     * launch is submission review.
161
     */
11 efrain 162
    public function test_get_launch_parameters_coupled_subreview_override(): void {
1 efrain 163
        $this->resetAfterTest();
164
        $this->setAdminUser();
165
 
166
        // Create a tool type, associated with that proxy.
167
 
168
        $typeid = $this->create_type();
169
        $course = $this->getDataGenerator()->create_course();
170
 
171
        $ltiinstance = $this->create_graded_lti($typeid, $course, 'resource-id', 'tag',
172
            'https://example.com/subreview', 'action=review');
173
 
174
        $this->assertNotNull($ltiinstance);
175
 
176
        $gbservice = new gradebookservices();
177
        $overrides = $gbservice->override_endpoint('LtiSubmissionReviewRequest', 'https://example.com/lti',
178
            "color=blue", $course->id, $ltiinstance);
179
 
180
        $this->assertEquals('https://example.com/subreview', $overrides[0]);
181
        $this->assertEquals("color=blue\naction=review", $overrides[1]);
182
    }
183
 
184
    /**
185
     * @covers ::override_endpoint
186
     *
187
     * Test Submission Review URL and custom parameter is applied when the
188
     * launch is submission review.
189
     */
11 efrain 190
    public function test_get_launch_parameters_coupled_subreview_override_default(): void {
1 efrain 191
        $this->resetAfterTest();
192
        $this->setAdminUser();
193
 
194
        // Create a tool type, associated with that proxy.
195
 
196
        $typeid = $this->create_type();
197
        $course = $this->getDataGenerator()->create_course();
198
 
199
        $ltiinstance = $this->create_graded_lti($typeid, $course, 'resource-id', 'tag',
200
            'DEFAULT', '');
201
 
202
        $this->assertNotNull($ltiinstance);
203
 
204
        $gbservice = new gradebookservices();
205
        $overrides = $gbservice->override_endpoint('LtiSubmissionReviewRequest', 'https://example.com/lti',
206
            "color=blue", $course->id, $ltiinstance);
207
 
208
        $this->assertEquals('https://example.com/lti', $overrides[0]);
209
        $this->assertEquals("color=blue", $overrides[1]);
210
    }
211
 
212
    /**
213
     * @covers ::get_launch_parameters
214
     *
215
     * Test line item URL is populated for not coupled line item only
216
     * if there is a single line item attached to that lti instance.
217
     */
11 efrain 218
    public function test_get_launch_parameters_decoupled(): void {
1 efrain 219
        $this->resetAfterTest();
220
        $this->setAdminUser();
221
 
222
        // Create a tool type, associated with that proxy.
223
 
224
        $typeid = $this->create_type();
225
 
226
        $course = $this->getDataGenerator()->create_course();
227
 
228
        $ltiinstance = $this->create_notgraded_lti($typeid, $course);
229
 
230
        $this->assertNotNull($ltiinstance);
231
 
232
        $gbservice = new gradebookservices();
233
        $params = $gbservice->get_launch_parameters('basic-lti-launch-request', $course->id, 111, $typeid, $ltiinstance->id);
234
        $this->assertEquals('$LineItems.url', $params['lineitems_url']);
235
        $this->assertFalse(array_key_exists('$LineItem.url', $params));
236
 
237
        $this->create_standalone_lineitem($course->id, $typeid, 'resource-id', 'tag', $ltiinstance->id);
238
        $params = $gbservice->get_launch_parameters('basic-lti-launch-request', $course->id, 111, $typeid, $ltiinstance->id);
239
        $this->assertEquals('$LineItems.url', $params['lineitems_url']);
240
        $this->assertEquals('$LineItem.url', $params['lineitem_url']);
241
 
242
        // 2 line items for a single link, we cannot return a single line item url.
243
        $this->create_standalone_lineitem($course->id, $typeid, 'resource-id', 'tag-2', $ltiinstance->id);
244
        $this->assertFalse(array_key_exists('$LineItem.url', $params));
245
    }
246
 
247
    /**
248
     * @covers ::is_user_gradable_in_course
249
     *
250
     * Test if a user can be graded in a course.
251
     */
11 efrain 252
    public function test_is_user_gradable_in_course(): void {
1 efrain 253
        $this->resetAfterTest();
254
 
255
        $generator = $this->getDataGenerator();
256
        $course = $generator->create_course();
257
        $user1 = $generator->create_user();
258
        $user2 = $generator->create_user();
259
        $generator->enrol_user($user1->id, $course->id, 'student');
260
        $generator->enrol_user($user2->id, $course->id, 'editingteacher');
261
 
262
        $this->assertTrue(gradebookservices::is_user_gradable_in_course($course->id, $user1->id));
263
        $this->assertFalse(gradebookservices::is_user_gradable_in_course($course->id, $user2->id));
264
    }
265
 
266
    /**
267
     * Asserts a matching gradebookservices record exist with the matching tag and resourceid.
268
     *
269
     * @param object $course current course
270
     * @param int $typeid Type id of the tool
271
     * @param string $label Label of the line item
272
     * @param object|null $ltiinstance lti instance related to that line item
273
     * @param string|null $resourceid resourceid the line item should have
274
     * @param string|null $tag tag the line item should have
275
     * @param string|null $subreviewurl submission review url
276
     * @param string|null $subreviewparams submission review custom params
277
     */
278
    private function assert_lineitems(object $course, int $typeid,
279
            string $label, ?object $ltiinstance, ?string $resourceid, ?string $tag,
280
            ?string $subreviewurl = null, ?string $subreviewparams = null): void {
281
        $gbservice = new gradebookservices();
282
        $gradeitems = $gbservice->get_lineitems($course->id, null, null, null, null, null, $typeid);
283
 
284
        // The 1st item in the array is the items count.
285
        $this->assertEquals(1, $gradeitems[0]);
286
        $lineitem = gradebookservices::item_for_json($gradeitems[1][0], '', $typeid);
287
        $this->assertEquals(10, $lineitem->scoreMaximum);
288
        $this->assertEquals($resourceid, $lineitem->resourceId);
289
        $this->assertEquals($tag, $lineitem->tag);
290
        $this->assertEquals($label, $lineitem->label);
291
        $this->assertEquals(!empty($subreviewurl), isset($lineitem->submissionReview));
292
        if ($subreviewurl) {
293
            if ($subreviewurl == 'DEFAULT') {
294
                $this->assertFalse(isset($lineitem->submissionReview->url));
295
            } else {
296
                $this->assertEquals($subreviewurl, $lineitem->submissionReview->url);
297
            }
298
            if ($subreviewparams) {
299
                $custom = $lineitem->submissionReview->custom;
300
                $this->assertEquals($subreviewparams, join("\n", array_map(fn($k) => $k.'='.$custom[$k], array_keys($custom))));
301
            } else {
302
                $this->assertFalse(isset($lineitem->submissionReview->custom));
303
            }
304
        }
305
 
306
        $gradeitems = $gbservice->get_lineitems($course->id, $resourceid, null, null, null, null, $typeid);
307
        $this->assertEquals(1, $gradeitems[0]);
308
 
309
        if (isset($ltiinstance)) {
310
            $gradeitems = $gbservice->get_lineitems($course->id, null, $ltiinstance->id, null, null, null, $typeid);
311
            $this->assertEquals(1, $gradeitems[0]);
312
            $gradeitems = $gbservice->get_lineitems($course->id, null, $ltiinstance->id + 1, null, null, null, $typeid);
313
            $this->assertEquals(0, $gradeitems[0]);
314
        }
315
 
316
        $gradeitems = $gbservice->get_lineitems($course->id, null, null, $tag, null, null, $typeid);
317
        $this->assertEquals(1, $gradeitems[0]);
318
 
319
        $gradeitems = $gbservice->get_lineitems($course->id, 'an unknown resource id', null, null, null, null, $typeid);
320
        $this->assertEquals(0, $gradeitems[0]);
321
 
322
        $gradeitems = $gbservice->get_lineitems($course->id, null, null, 'an unknown tag', null, null, $typeid);
323
        $this->assertEquals(0, $gradeitems[0]);
324
    }
325
 
326
    /**
327
     * Inserts a graded lti instance, which should create a grade_item and gradebookservices record.
328
     *
329
     * @param int $typeid Type ID of the LTI Tool.
330
     * @param object $course course where to add the lti instance.
331
     * @param string|null $resourceid resource id
332
     * @param string|null $tag tag
333
     * @param string|null $subreviewurl submission review url
334
     * @param string|null $subreviewparams submission review custom params
335
     *
336
     * @return object lti instance created
337
     */
338
    private function create_graded_lti(int $typeid, object $course, ?string $resourceid, ?string $tag,
339
            ?string $subreviewurl = null, ?string $subreviewparams = null): object {
340
 
341
        $lti = ['course' => $course->id,
342
            'typeid' => $typeid,
343
            'instructorchoiceacceptgrades' => LTI_SETTING_ALWAYS,
344
            'grade' => 10,
345
            'lineitemresourceid' => $resourceid,
346
            'lineitemtag' => $tag,
347
            'lineitemsubreviewurl' => $subreviewurl,
348
            'lineitemsubreviewparams' => $subreviewparams];
349
 
350
        return $this->getDataGenerator()->create_module('lti', $lti, array());
351
    }
352
 
353
     /**
354
      * Inserts an lti instance that is not graded.
355
      *
356
      * @param int $typeid Type Id of the LTI Tool.
357
      * @param object $course course where to add the lti instance.
358
      *
359
      * @return object lti instance created
360
      */
361
    private function create_notgraded_lti(int $typeid, object $course): object {
362
 
363
        $lti = ['course' => $course->id,
364
            'typeid' => $typeid,
365
            'instructorchoiceacceptgrades' => LTI_SETTING_NEVER];
366
 
367
        return $this->getDataGenerator()->create_module('lti', $lti, array());
368
    }
369
 
370
    /**
371
     * Inserts a standalone lineitem (gradeitem, gradebookservices entries).
372
     *
373
     * @param int $courseid Id of the course where the standalone line item will be added.
374
     * @param int $typeid of the LTI Tool
375
     * @param string|null $resourceid resource id
376
     * @param string|null $tag tag
377
     * @param int|null $ltiinstanceid Id of the LTI instance the standalone line item will be related to.
378
     *
379
     */
380
    private function create_standalone_lineitem(int $courseid, int $typeid, ?string $resourceid,
381
            ?string $tag, int $ltiinstanceid = null): void {
382
        $gbservice = new gradebookservices();
383
        $gbservice->add_standalone_lineitem($courseid,
384
            "manualtest",
385
            10,
386
            "https://test.phpunit",
387
            $ltiinstanceid,
388
            $resourceid,
389
            $tag,
390
            $typeid,
391
            null /*toolproxyid*/);
392
    }
393
 
394
    /**
395
     * Creates a new LTI Tool Type.
396
     */
397
    private function create_type() {
398
        $type = new \stdClass();
399
        $type->state = LTI_TOOL_STATE_CONFIGURED;
400
        $type->name = "Test tool";
401
        $type->description = "Example description";
402
        $type->clientid = "Test client ID";
403
        $type->baseurl = $this->getExternalTestFileUrl('/test.html');
404
 
405
        $config = new \stdClass();
406
        $config->ltiservice_gradesynchronization = 2;
407
        return lti_add_type($type, $config);
408
    }
409
}