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 assignfeedback_editpdf;
18
 
19
use mod_assign_test_generator;
20
 
21
defined('MOODLE_INTERNAL') || die();
22
 
23
global $CFG;
24
require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
25
 
26
/**
27
 * Unit tests for assignfeedback_editpdf\comments_quick_list
28
 *
29
 * @package    assignfeedback_editpdf
30
 * @category   test
31
 * @copyright  2013 Damyon Wiese
32
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 */
34
class feedback_test extends \advanced_testcase {
35
 
36
    // Use the generator helper.
37
    use mod_assign_test_generator;
38
 
39
    /**
40
     * Ensure that GS is available.
41
     */
42
    protected function require_ghostscript() {
43
        // Skip this test if ghostscript is not supported.
44
        $result = pdf::test_gs_path(false);
45
        if ($result->status !== pdf::GSPATH_OK) {
46
            $this->markTestSkipped('Ghostscript not setup');
47
        }
48
    }
49
 
50
    /**
51
     * Helper method to add a file to a submission.
52
     *
53
     * @param \stdClass $student Student submitting.
54
     * @param \assign   $assign Assignment being submitted.
55
     * @param bool     $textfile Use textfile fixture instead of pdf.
56
     */
57
    protected function add_file_submission($student, $assign, $textfile = false) {
58
        global $CFG;
59
 
60
        $this->setUser($student);
61
 
62
        // Create a file submission with the test pdf.
63
        $submission = $assign->get_user_submission($student->id, true);
64
 
65
        $fs = get_file_storage();
66
        $filerecord = (object) array(
67
            'contextid' => $assign->get_context()->id,
68
            'component' => 'assignsubmission_file',
69
            'filearea' => ASSIGNSUBMISSION_FILE_FILEAREA,
70
            'itemid' => $submission->id,
71
            'filepath' => '/',
72
            'filename' => $textfile ? 'submission.txt' : 'submission.pdf'
73
        );
74
        $sourcefile = $CFG->dirroot . '/mod/assign/feedback/editpdf/tests/fixtures/submission.' . ($textfile ? 'txt' : 'pdf');
75
        $fs->create_file_from_pathname($filerecord, $sourcefile);
76
 
77
        $data = new \stdClass();
78
        $plugin = $assign->get_submission_plugin_by_type('file');
79
        $plugin->save($submission, $data);
80
    }
81
 
11 efrain 82
    public function test_comments_quick_list(): void {
1 efrain 83
        $this->resetAfterTest();
84
        $course = $this->getDataGenerator()->create_course();
85
        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
86
 
87
        $this->setUser($teacher);
88
 
89
        $this->assertEmpty(comments_quick_list::get_comments());
90
 
91
        $comment = comments_quick_list::add_comment('test', 45, 'red');
92
        $comments = comments_quick_list::get_comments();
93
        $this->assertEquals(count($comments), 1);
94
        $first = reset($comments);
95
        $this->assertEquals($comment, $first);
96
 
97
        $commentbyid = comments_quick_list::get_comment($comment->id);
98
        $this->assertEquals($comment, $commentbyid);
99
 
100
        $this->assertTrue(comments_quick_list::remove_comment($comment->id));
101
 
102
        $comments = comments_quick_list::get_comments();
103
        $this->assertEmpty($comments);
104
    }
105
 
11 efrain 106
    public function test_page_editor(): void {
1 efrain 107
        $this->resetAfterTest();
108
        $course = $this->getDataGenerator()->create_course();
109
        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
110
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
111
        $assign = $this->create_instance($course, [
112
                'assignsubmission_onlinetext_enabled' => 1,
113
                'assignsubmission_file_enabled' => 1,
114
                'assignsubmission_file_maxfiles' => 1,
115
                'assignfeedback_editpdf_enabled' => 1,
116
                'assignsubmission_file_maxsizebytes' => 1000000,
117
            ]);
118
 
119
        // Add the standard submission.
120
        $this->add_file_submission($student, $assign);
121
 
122
        $this->setUser($teacher);
123
 
124
        $grade = $assign->get_user_grade($student->id, true);
125
 
126
        $notempty = page_editor::has_annotations_or_comments($grade->id, false);
127
        $this->assertFalse($notempty);
128
 
129
        $comment = new comment();
130
        $comment->rawtext = 'Comment text';
131
        $comment->width = 100;
132
        $comment->x = 100;
133
        $comment->y = 100;
134
        $comment->colour = 'red';
135
 
136
        $comment2 = new comment();
137
        $comment2->rawtext = 'Comment text 2';
138
        $comment2->width = 100;
139
        $comment2->x = 200;
140
        $comment2->y = 100;
141
        $comment2->colour = 'clear';
142
 
143
        page_editor::set_comments($grade->id, 0, array($comment, $comment2));
144
 
145
        $annotation = new annotation();
146
        $annotation->path = '';
147
        $annotation->x = 100;
148
        $annotation->y = 100;
149
        $annotation->endx = 200;
150
        $annotation->endy = 200;
151
        $annotation->type = 'line';
152
        $annotation->colour = 'red';
153
 
154
        $annotation2 = new annotation();
155
        $annotation2->path = '';
156
        $annotation2->x = 100;
157
        $annotation2->y = 100;
158
        $annotation2->endx = 200;
159
        $annotation2->endy = 200;
160
        $annotation2->type = 'rectangle';
161
        $annotation2->colour = 'yellow';
162
 
163
        page_editor::set_annotations($grade->id, 0, array($annotation, $annotation2));
164
 
165
        // Still empty because all edits are still drafts.
166
        $this->assertFalse(page_editor::has_annotations_or_comments($grade->id, false));
167
 
168
        $comments = page_editor::get_comments($grade->id, 0, false);
169
        $this->assertEmpty($comments);
170
 
171
        $comments = page_editor::get_comments($grade->id, 0, true);
172
        $this->assertEquals(count($comments), 2);
173
 
174
        $annotations = page_editor::get_annotations($grade->id, 0, false);
175
        $this->assertEmpty($annotations);
176
 
177
        $annotations = page_editor::get_annotations($grade->id, 0, true);
178
        $this->assertEquals(count($annotations), 2);
179
 
180
        $comment = reset($comments);
181
        $annotation = reset($annotations);
182
 
183
        page_editor::remove_comment($comment->id);
184
        page_editor::remove_annotation($annotation->id);
185
 
186
        $comments = page_editor::get_comments($grade->id, 0, true);
187
        $this->assertEquals(count($comments), 1);
188
 
189
        $annotations = page_editor::get_annotations($grade->id, 0, true);
190
        $this->assertEquals(count($annotations), 1);
191
 
192
        // Release the drafts.
193
        page_editor::release_drafts($grade->id);
194
 
195
        $notempty = page_editor::has_annotations_or_comments($grade->id, false);
196
        $this->assertTrue($notempty);
197
 
198
        // Unrelease the drafts.
199
        page_editor::unrelease_drafts($grade->id);
200
 
201
        $notempty = page_editor::has_annotations_or_comments($grade->id, false);
202
        $this->assertFalse($notempty);
203
    }
204
 
11 efrain 205
    public function test_document_services(): void {
1 efrain 206
        $this->require_ghostscript();
207
        $this->resetAfterTest();
208
        $course = $this->getDataGenerator()->create_course();
209
        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
210
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
211
        $assign = $this->create_instance($course, [
212
                'assignsubmission_onlinetext_enabled' => 1,
213
                'assignsubmission_file_enabled' => 1,
214
                'assignsubmission_file_maxfiles' => 1,
215
                'assignfeedback_editpdf_enabled' => 1,
216
                'assignsubmission_file_maxsizebytes' => 1000000,
217
            ]);
218
 
219
        // Add the standard submission.
220
        $this->add_file_submission($student, $assign);
221
 
222
        $this->setUser($teacher);
223
 
224
        $grade = $assign->get_user_grade($student->id, true);
225
 
226
        $contextid = $assign->get_context()->id;
227
        $component = 'assignfeedback_editpdf';
228
        $filearea = document_services::COMBINED_PDF_FILEAREA;
229
        $itemid = $grade->id;
230
        $filepath = '/';
231
        $filename = document_services::COMBINED_PDF_FILENAME;
232
        $fs = \get_file_storage();
233
 
234
        // Generate a blank combined pdf.
235
        $record = new \stdClass();
236
        $record->contextid = $contextid;
237
        $record->component = $component;
238
        $record->filearea = $filearea;
239
        $record->itemid = $itemid;
240
        $record->filepath = $filepath;
241
        $record->filename = $filename;
242
        $fs->create_file_from_string($record, base64_decode(document_services::BLANK_PDF_BASE64));
243
 
244
        // Verify that the blank combined pdf has the expected hash.
245
        $combinedpdf = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename);
246
        $this->assertEquals($combinedpdf->get_contenthash(), document_services::BLANK_PDF_HASH);
247
 
248
        // Generate page images and verify that the combined pdf has been replaced.
249
        document_services::get_page_images_for_attempt($assign, $student->id, -1);
250
        $combinedpdf = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename);
251
        $this->assertNotEquals($combinedpdf->get_contenthash(), document_services::BLANK_PDF_HASH);
252
 
253
        $notempty = page_editor::has_annotations_or_comments($grade->id, false);
254
        $this->assertFalse($notempty);
255
 
256
        $comment = new comment();
257
 
258
        // Use some different charset in the comment text.
259
        $comment->rawtext = 'Testing example: בקלות ואמנות';
260
        $comment->width = 100;
261
        $comment->x = 100;
262
        $comment->y = 100;
263
        $comment->colour = 'red';
264
 
265
        page_editor::set_comments($grade->id, 0, array($comment));
266
 
267
        $annotations = array();
268
 
269
        $annotation = new annotation();
270
        $annotation->path = '';
271
        $annotation->x = 100;
272
        $annotation->y = 100;
273
        $annotation->endx = 200;
274
        $annotation->endy = 200;
275
        $annotation->type = 'line';
276
        $annotation->colour = 'red';
277
        array_push($annotations, $annotation);
278
 
279
        $annotation = new annotation();
280
        $annotation->path = '';
281
        $annotation->x = 100;
282
        $annotation->y = 100;
283
        $annotation->endx = 200;
284
        $annotation->endy = 200;
285
        $annotation->type = 'rectangle';
286
        $annotation->colour = 'yellow';
287
        array_push($annotations, $annotation);
288
 
289
        $annotation = new annotation();
290
        $annotation->path = '';
291
        $annotation->x = 100;
292
        $annotation->y = 100;
293
        $annotation->endx = 200;
294
        $annotation->endy = 200;
295
        $annotation->type = 'oval';
296
        $annotation->colour = 'green';
297
        array_push($annotations, $annotation);
298
 
299
        $annotation = new annotation();
300
        $annotation->path = '';
301
        $annotation->x = 100;
302
        $annotation->y = 100;
303
        $annotation->endx = 200;
304
        $annotation->endy = 116;
305
        $annotation->type = 'highlight';
306
        $annotation->colour = 'blue';
307
        array_push($annotations, $annotation);
308
 
309
        $annotation = new annotation();
310
        $annotation->path = '100,100:105,105:110,100';
311
        $annotation->x = 100;
312
        $annotation->y = 100;
313
        $annotation->endx = 110;
314
        $annotation->endy = 105;
315
        $annotation->type = 'pen';
316
        $annotation->colour = 'black';
317
        array_push($annotations, $annotation);
318
        page_editor::set_annotations($grade->id, 0, $annotations);
319
 
320
        page_editor::release_drafts($grade->id);
321
 
322
        $notempty = page_editor::has_annotations_or_comments($grade->id, false);
323
 
324
        $this->assertTrue($notempty);
325
 
326
        $file = document_services::generate_feedback_document($assign->get_instance()->id, $grade->userid, $grade->attemptnumber);
327
        $this->assertNotEmpty($file);
328
 
329
        $file2 = document_services::get_feedback_document($assign->get_instance()->id, $grade->userid, $grade->attemptnumber);
330
 
331
        $this->assertEquals($file, $file2);
332
 
333
        document_services::delete_feedback_document($assign->get_instance()->id, $grade->userid, $grade->attemptnumber);
334
        $file3 = document_services::get_feedback_document($assign->get_instance()->id, $grade->userid, $grade->attemptnumber);
335
 
336
        $this->assertEmpty($file3);
337
    }
338
 
339
    /**
340
     * Test Convert submission ad-hoc task.
341
     *
342
     * @covers \assignfeedback_editpdf\task\convert_submission
343
     */
11 efrain 344
    public function test_conversion_task(): void {
1 efrain 345
        $this->require_ghostscript();
346
        $this->resetAfterTest();
347
        \core\cron::setup_user();
348
 
349
        $course = $this->getDataGenerator()->create_course();
350
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
351
        $assignopts = [
352
            'assignsubmission_file_enabled' => 1,
353
            'assignsubmission_file_maxfiles' => 1,
354
            'assignfeedback_editpdf_enabled' => 1,
355
            'assignsubmission_file_maxsizebytes' => 1000000,
356
        ];
357
        $assign = $this->create_instance($course, $assignopts);
358
 
359
        // Add the standard submission.
360
        $this->add_file_submission($student, $assign);
361
 
362
        // Run the conversion task.
363
        $task = \core\task\manager::get_next_adhoc_task(time());
364
        ob_start();
365
        $task->execute();
366
        \core\task\manager::adhoc_task_complete($task);
367
        $output = ob_get_clean();
368
 
369
        // Confirm, that submission has been converted and the task queue is now empty.
370
        $this->assertStringContainsString('Converting submission for user id ' . $student->id, $output);
371
        $this->assertStringContainsString('The document has been successfully converted', $output);
372
        $this->assertNull(\core\task\manager::get_next_adhoc_task(time()));
373
 
374
        // Trigger a re-queue by 'updating' a submission.
375
        $submission = $assign->get_user_submission($student->id, true);
376
        $plugin = $assign->get_submission_plugin_by_type('file');
377
        $plugin->save($submission, (new \stdClass));
378
 
379
        $task = \core\task\manager::get_next_adhoc_task(time());
380
        // Verify that queued a conversion task.
381
        $this->assertNotNull($task);
382
 
383
        ob_start();
384
        $task->execute();
385
        \core\task\manager::adhoc_task_complete($task);
386
        $output = ob_get_clean();
387
 
388
        // Confirm, that submission has been converted and the task queue is now empty.
389
        $this->assertStringContainsString('Converting submission for user id ' . $student->id, $output);
390
        $this->assertStringContainsString('The document has been successfully converted', $output);
391
        $this->assertNull(\core\task\manager::get_next_adhoc_task(time()));
392
    }
393
 
394
    /**
395
     * Test that modifying the annotated pdf form return true when modified
396
     * and false when not modified.
397
     */
11 efrain 398
    public function test_is_feedback_modified(): void {
1 efrain 399
        $this->require_ghostscript();
400
        $this->resetAfterTest();
401
        $course = $this->getDataGenerator()->create_course();
402
        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
403
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
404
        $assign = $this->create_instance($course, [
405
                'assignsubmission_onlinetext_enabled' => 1,
406
                'assignsubmission_file_enabled' => 1,
407
                'assignsubmission_file_maxfiles' => 1,
408
                'assignfeedback_editpdf_enabled' => 1,
409
                'assignsubmission_file_maxsizebytes' => 1000000,
410
            ]);
411
 
412
        // Add the standard submission.
413
        $this->add_file_submission($student, $assign);
414
 
415
        $this->setUser($teacher);
416
        $grade = $assign->get_user_grade($student->id, true);
417
 
418
        $notempty = page_editor::has_annotations_or_comments($grade->id, false);
419
        $this->assertFalse($notempty);
420
 
421
        $comment = new comment();
422
 
423
        $comment->rawtext = 'Comment text';
424
        $comment->width = 100;
425
        $comment->x = 100;
426
        $comment->y = 100;
427
        $comment->colour = 'red';
428
 
429
        page_editor::set_comments($grade->id, 0, array($comment));
430
 
431
        $annotations = array();
432
 
433
        $annotation = new annotation();
434
        $annotation->path = '';
435
        $annotation->x = 100;
436
        $annotation->y = 100;
437
        $annotation->endx = 200;
438
        $annotation->endy = 200;
439
        $annotation->type = 'line';
440
        $annotation->colour = 'red';
441
        array_push($annotations, $annotation);
442
 
443
        page_editor::set_annotations($grade->id, 0, $annotations);
444
 
445
        $plugin = $assign->get_feedback_plugin_by_type('editpdf');
446
        $data = new \stdClass();
447
        $data->editpdf_source_userid = $student->id;
448
        $this->assertTrue($plugin->is_feedback_modified($grade, $data));
449
        $plugin->save($grade, $data);
450
 
451
        $annotation = new annotation();
452
        $annotation->gradeid = $grade->id;
453
        $annotation->pageno = 0;
454
        $annotation->path = '';
455
        $annotation->x = 100;
456
        $annotation->y = 100;
457
        $annotation->endx = 200;
458
        $annotation->endy = 200;
459
        $annotation->type = 'rectangle';
460
        $annotation->colour = 'yellow';
461
 
462
        $yellowannotationid = page_editor::add_annotation($annotation);
463
 
464
        // Add a comment as well.
465
        $comment = new comment();
466
        $comment->gradeid = $grade->id;
467
        $comment->pageno = 0;
468
        $comment->rawtext = 'Second Comment text';
469
        $comment->width = 100;
470
        $comment->x = 100;
471
        $comment->y = 100;
472
        $comment->colour = 'red';
473
        page_editor::add_comment($comment);
474
 
475
        $this->assertTrue($plugin->is_feedback_modified($grade, $data));
476
        $plugin->save($grade, $data);
477
 
478
        // We should have two annotations.
479
        $this->assertCount(2, page_editor::get_annotations($grade->id, 0, false));
480
        // And two comments.
481
        $this->assertCount(2, page_editor::get_comments($grade->id, 0, false));
482
 
483
        // Add one annotation and delete another.
484
        $annotation = new annotation();
485
        $annotation->gradeid = $grade->id;
486
        $annotation->pageno = 0;
487
        $annotation->path = '100,100:105,105:110,100';
488
        $annotation->x = 100;
489
        $annotation->y = 100;
490
        $annotation->endx = 110;
491
        $annotation->endy = 105;
492
        $annotation->type = 'pen';
493
        $annotation->colour = 'black';
494
        page_editor::add_annotation($annotation);
495
 
496
        $annotations = page_editor::get_annotations($grade->id, 0, true);
497
        page_editor::remove_annotation($yellowannotationid);
498
        $this->assertTrue($plugin->is_feedback_modified($grade, $data));
499
        $plugin->save($grade, $data);
500
 
501
        // We should have two annotations.
502
        $this->assertCount(2, page_editor::get_annotations($grade->id, 0, false));
503
        // And two comments.
504
        $this->assertCount(2, page_editor::get_comments($grade->id, 0, false));
505
 
506
        // Add a comment and then remove it. Should not be considered as modified.
507
        $comment = new comment();
508
        $comment->gradeid = $grade->id;
509
        $comment->pageno = 0;
510
        $comment->rawtext = 'Third Comment text';
511
        $comment->width = 400;
512
        $comment->x = 57;
513
        $comment->y = 205;
514
        $comment->colour = 'black';
515
        $comment->id = page_editor::add_comment($comment);
516
 
517
        // We should now have three comments.
518
        $this->assertCount(3, page_editor::get_comments($grade->id, 0, true));
519
        // Now delete the newest record.
520
        page_editor::remove_comment($comment->id);
521
        // Back to two comments.
522
        $this->assertCount(2, page_editor::get_comments($grade->id, 0, true));
523
        // No modification.
524
        $this->assertFalse($plugin->is_feedback_modified($grade, $data));
525
    }
526
 
527
    /**
528
     * Test that overwriting a submission file deletes any associated conversions.
529
     *
530
     * @covers \core_files\conversion::get_conversions_for_file
531
     */
11 efrain 532
    public function test_submission_file_overridden(): void {
1 efrain 533
        $this->resetAfterTest();
534
        $course = $this->getDataGenerator()->create_course();
535
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
536
        $assign = $this->create_instance($course, [
537
            'assignsubmission_onlinetext_enabled' => 1,
538
            'assignsubmission_file_enabled' => 1,
539
            'assignsubmission_file_maxfiles' => 1,
540
            'assignfeedback_editpdf_enabled' => 1,
541
            'assignsubmission_file_maxsizebytes' => 1000000,
542
        ]);
543
 
544
        $this->add_file_submission($student, $assign, true);
545
        $submission = $assign->get_user_submission($student->id, true);
546
 
547
        $fs = get_file_storage();
548
        $sourcefile = $fs->get_file(
549
            $assign->get_context()->id,
550
            'assignsubmission_file',
551
            ASSIGNSUBMISSION_FILE_FILEAREA,
552
            $submission->id,
553
            '/',
554
            'submission.txt'
555
        );
556
 
557
        $conversion = new \core_files\conversion(0, (object)[
558
            'sourcefileid' => $sourcefile->get_id(),
559
            'targetformat' => 'pdf'
560
        ]);
561
        $conversion->create();
562
 
563
        $conversions = \core_files\conversion::get_conversions_for_file($sourcefile, 'pdf');
564
        $this->assertCount(1, $conversions);
565
 
566
        $filerecord = (object)[
567
            'contextid' => $assign->get_context()->id,
568
            'component' => 'core',
569
            'filearea'  => 'unittest',
570
            'itemid'    => $submission->id,
571
            'filepath'  => '/',
572
            'filename'  => 'submission.txt'
573
        ];
574
 
575
        $fs = get_file_storage();
576
        $newfile = $fs->create_file_from_string($filerecord, 'something totally different');
577
        $sourcefile->replace_file_with($newfile);
578
 
579
        $conversions = \core_files\conversion::get_conversions_for_file($sourcefile, 'pdf');
580
        $this->assertCount(0, $conversions);
581
    }
582
 
583
    /**
584
     * Tests that when the plugin is not enabled for an assignment it does not create conversion tasks.
585
     *
586
     * @covers \assignfeedback_editpdf\event\observer
587
     */
11 efrain 588
    public function test_submission_not_enabled(): void {
1 efrain 589
        $this->require_ghostscript();
590
        $this->resetAfterTest();
591
        \core\cron::setup_user();
592
 
593
        $course = $this->getDataGenerator()->create_course();
594
        $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
595
        $assignopts = [
596
            'assignsubmission_file_enabled' => 1,
597
            'assignsubmission_file_maxfiles' => 1,
598
            'assignfeedback_editpdf_enabled' => 0,
599
            'assignsubmission_file_maxsizebytes' => 1000000,
600
        ];
601
        $assign = $this->create_instance($course, $assignopts);
602
 
603
        // Add the standard submission.
604
        $this->add_file_submission($student, $assign);
605
 
606
        $task = \core\task\manager::get_next_adhoc_task(time());
607
 
608
        // No task was created.
609
        $this->assertNull($task);
610
    }
611
}