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
declare(strict_types=1);
18
 
19
namespace core_reportbuilder\local\helpers;
20
 
21
use advanced_testcase;
22
use invalid_parameter_exception;
23
use core_cohort\reportbuilder\audience\cohortmember;
24
use core_reportbuilder_generator;
25
use core_reportbuilder\local\models\schedule as model;
26
use core_reportbuilder\reportbuilder\audience\manual;
27
use core_user\reportbuilder\datasource\users;
28
 
29
/**
30
 * Unit tests for the schedule helper class
31
 *
32
 * @package     core_reportbuilder
33
 * @covers      \core_reportbuilder\local\helpers\schedule
34
 * @copyright   2021 Paul Holden <paulh@moodle.com>
35
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36
 */
37
class schedule_test extends advanced_testcase {
38
 
39
    /**
40
     * Test create schedule
41
     */
42
    public function test_create_schedule(): void {
43
        $this->resetAfterTest();
44
        $this->setAdminUser();
45
 
46
        /** @var core_reportbuilder_generator $generator */
47
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
48
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
49
 
50
        $timescheduled = time() + DAYSECS;
51
        $schedule = schedule::create_schedule((object) [
52
            'name' => 'My schedule',
53
            'reportid' => $report->get('id'),
54
            'format' => 'csv',
55
            'subject' => 'Hello',
56
            'message' => 'Hola',
57
            'timescheduled' => $timescheduled,
58
        ]);
59
 
60
        $this->assertEquals('My schedule', $schedule->get('name'));
61
        $this->assertEquals($report->get('id'), $schedule->get('reportid'));
62
        $this->assertEquals('csv', $schedule->get('format'));
63
        $this->assertEquals('Hello', $schedule->get('subject'));
64
        $this->assertEquals('Hola', $schedule->get('message'));
65
        $this->assertEquals($timescheduled, $schedule->get('timescheduled'));
66
        $this->assertEquals($timescheduled, $schedule->get('timenextsend'));
67
    }
68
 
69
    /**
70
     * Test update schedule
71
     */
72
    public function test_update_schedule(): void {
73
        $this->resetAfterTest();
74
        $this->setAdminUser();
75
 
76
        /** @var core_reportbuilder_generator $generator */
77
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
78
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
79
        $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);
80
 
81
        // Update some record properties.
82
        $record = $schedule->to_record();
83
        $record->name = 'My updated schedule';
84
        $record->timescheduled = 1861340400; // 25/12/2028 07:00 UTC.
85
 
86
        $schedule = schedule::update_schedule($record);
87
        $this->assertEquals($record->name, $schedule->get('name'));
88
        $this->assertEquals($record->timescheduled, $schedule->get('timescheduled'));
89
    }
90
 
91
    /**
92
     * Test update invalid schedule
93
     */
94
    public function test_update_schedule_invalid(): void {
95
        $this->resetAfterTest();
96
        $this->setAdminUser();
97
 
98
        /** @var core_reportbuilder_generator $generator */
99
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
100
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
101
 
102
        $this->expectException(invalid_parameter_exception::class);
103
        $this->expectExceptionMessage('Invalid schedule');
104
        schedule::update_schedule((object) ['id' => 42, 'reportid' => $report->get('id')]);
105
    }
106
 
107
    /**
108
     * Test toggle schedule
109
     */
110
    public function test_toggle_schedule(): void {
111
        $this->resetAfterTest();
112
        $this->setAdminUser();
113
 
114
        /** @var core_reportbuilder_generator $generator */
115
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
116
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
117
        $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);
118
 
119
        // Disable the schedule.
120
        schedule::toggle_schedule($report->get('id'), $schedule->get('id'), false);
121
        $schedule = $schedule->read();
122
        $this->assertFalse($schedule->get('enabled'));
123
 
124
        // Enable the schedule.
125
        schedule::toggle_schedule($report->get('id'), $schedule->get('id'), true);
126
        $schedule = $schedule->read();
127
        $this->assertTrue($schedule->get('enabled'));
128
    }
129
 
130
    /**
131
     * Test toggle invalid schedule
132
     */
133
    public function test_toggle_schedule_invalid(): void {
134
        $this->resetAfterTest();
135
        $this->setAdminUser();
136
 
137
        /** @var core_reportbuilder_generator $generator */
138
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
139
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
140
 
141
        $this->expectException(invalid_parameter_exception::class);
142
        $this->expectExceptionMessage('Invalid schedule');
143
        schedule::toggle_schedule($report->get('id'), 42, true);
144
    }
145
 
146
    /**
147
     * Test delete schedule
148
     */
149
    public function test_delete_schedule(): void {
150
        $this->resetAfterTest();
151
        $this->setAdminUser();
152
 
153
        /** @var core_reportbuilder_generator $generator */
154
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
155
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
156
        $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);
157
 
158
        $scheduleid = $schedule->get('id');
159
 
160
        schedule::delete_schedule($report->get('id'), $scheduleid);
161
        $this->assertFalse($schedule::record_exists($scheduleid));
162
    }
163
 
164
    /**
165
     * Test delete invalid schedule
166
     */
167
    public function test_delete_schedule_invalid(): void {
168
        $this->resetAfterTest();
169
        $this->setAdminUser();
170
 
171
        /** @var core_reportbuilder_generator $generator */
172
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
173
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
174
 
175
        $this->expectException(invalid_parameter_exception::class);
176
        $this->expectExceptionMessage('Invalid schedule');
177
        schedule::delete_schedule($report->get('id'), 42);
178
    }
179
 
180
    /**
181
     * Test getting schedule report users (those in matching audience)
182
     */
183
    public function test_get_schedule_report_users(): void {
184
        $this->resetAfterTest();
185
 
186
        /** @var core_reportbuilder_generator $generator */
187
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
188
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
189
 
190
        // Create cohort, with some members.
191
        $cohort = $this->getDataGenerator()->create_cohort();
192
        $cohortuserone = $this->getDataGenerator()->create_user(['firstname' => 'Zoe', 'lastname' => 'Zebra']);
193
        cohort_add_member($cohort->id, $cohortuserone->id);
194
        $cohortusertwo = $this->getDataGenerator()->create_user(['firstname' => 'Henrietta', 'lastname' => 'Hamster']);
195
        cohort_add_member($cohort->id, $cohortusertwo->id);
196
 
197
        // Create a third user, to be added manually.
198
        $manualuserone = $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Badger']);
199
 
200
        $audiencecohort = $generator->create_audience([
201
            'reportid' => $report->get('id'),
202
            'classname' => cohortmember::class,
203
            'configdata' => ['cohorts' => [$cohort->id]],
204
        ]);
205
 
206
        $audiencemanual = $generator->create_audience([
207
            'reportid' => $report->get('id'),
208
            'classname' => manual::class,
209
            'configdata' => ['users' => [$manualuserone->id]],
210
        ]);
211
 
212
        // Now create our schedule.
213
        $schedule = $generator->create_schedule([
214
            'reportid' => $report->get('id'),
215
            'name' => 'My schedule',
216
            'audiences' => json_encode([
217
                $audiencecohort->get_persistent()->get('id'),
218
                $audiencemanual->get_persistent()->get('id'),
219
            ]),
220
        ]);
221
 
222
        $users = schedule::get_schedule_report_users($schedule);
223
        $this->assertEquals([
224
            'Bob',
225
            'Henrietta',
226
            'Zoe',
227
        ], array_column($users, 'firstname'));
228
 
229
        // Now delete one of our users, ensure they are no longer returned.
230
        delete_user($manualuserone);
231
 
232
        $users = schedule::get_schedule_report_users($schedule);
233
        $this->assertEquals([
234
            'Henrietta',
235
            'Zoe',
236
        ], array_column($users, 'firstname'));
237
    }
238
 
239
    /**
240
     * Test getting schedule report row count
241
     */
242
    public function test_get_schedule_report_count(): void {
243
        $this->resetAfterTest();
244
 
245
        /** @var core_reportbuilder_generator $generator */
246
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
247
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
248
        $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule']);
249
 
250
        // There is only one row in the report (the only user on the site).
251
        $count = schedule::get_schedule_report_count($schedule);
252
        $this->assertEquals(1, $count);
253
    }
254
 
255
    /**
256
     * Data provider for {@see test_get_schedule_report_file}
257
     *
258
     * @return string[]
259
     */
260
    public function get_schedule_report_file_format(): array {
261
        return [
262
            ['csv'],
263
            ['excel'],
264
            ['html'],
265
            ['json'],
266
            ['ods'],
267
            ['pdf'],
268
        ];
269
    }
270
 
271
    /**
272
     * Test getting schedule report exported file, in each supported format
273
     *
274
     * @param string $format
275
     *
276
     * @dataProvider get_schedule_report_file_format
277
     */
278
    public function test_get_schedule_report_file(string $format): void {
279
        $this->resetAfterTest();
280
        $this->setAdminUser();
281
 
282
        /** @var core_reportbuilder_generator $generator */
283
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
284
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
285
        $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule', 'format' => $format]);
286
 
287
        // There is only one row in the report (the only user on the site).
288
        $file = schedule::get_schedule_report_file($schedule);
289
        $this->assertGreaterThan(64, $file->get_filesize());
290
    }
291
 
292
    /**
293
     * Data provider for {@see test_should_send_schedule}
294
     *
295
     * @return array[]
296
     */
297
    public function should_send_schedule_provider(): array {
298
        $time = time();
299
 
300
        // We just need large offsets for dates in the past/future.
301
        $yesterday = $time - DAYSECS;
302
        $tomorrow = $time + DAYSECS;
303
 
304
        return [
305
            'Disabled' => [[
306
                'enabled' => false,
307
            ], false],
308
            'Time scheduled in the past' => [[
309
                'recurrence' => model::RECURRENCE_NONE,
310
                'timescheduled' => $yesterday,
311
            ], true],
312
            'Time scheduled in the past, already sent prior to schedule' => [[
313
                'recurrence' => model::RECURRENCE_NONE,
314
                'timescheduled' => $yesterday,
315
                'timelastsent' => $yesterday - HOURSECS,
316
            ], true],
317
            'Time scheduled in the past, already sent on schedule' => [[
318
                'recurrence' => model::RECURRENCE_NONE,
319
                'timescheduled' => $yesterday,
320
                'timelastsent' => $yesterday,
321
            ], false],
322
            'Time scheduled in the future' => [[
323
                'recurrence' => model::RECURRENCE_NONE,
324
                'timescheduled' => $tomorrow,
325
            ], false],
326
            'Time scheduled in the future, already sent prior to schedule' => [[
327
                'recurrence' => model::RECURRENCE_NONE,
328
                'timelastsent' => $yesterday,
329
                'timescheduled' => $tomorrow,
330
            ], false],
331
            'Next send in the past' => [[
332
                'recurrence' => model::RECURRENCE_DAILY,
333
                'timescheduled' => $yesterday,
334
                'timenextsend' => $yesterday,
335
            ], true],
336
            'Next send in the future' => [[
337
                'recurrence' => model::RECURRENCE_DAILY,
338
                'timescheduled' => $yesterday,
339
                'timenextsend' => $tomorrow,
340
            ], false],
341
        ];
342
    }
343
 
344
    /**
345
     * Test for whether a schedule should be sent
346
     *
347
     * @param array $properties
348
     * @param bool $expected
349
     *
350
     * @dataProvider should_send_schedule_provider
351
     */
352
    public function test_should_send_schedule(array $properties, bool $expected): void {
353
        $this->resetAfterTest();
354
 
355
        /** @var core_reportbuilder_generator $generator */
356
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
357
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
358
 
359
        $schedule = $generator->create_schedule(['reportid' => $report->get('id'), 'name' => 'My schedule'] + $properties);
360
 
361
        // If "Time next send" is specified, then override calculated value.
362
        if (array_key_exists('timenextsend', $properties)) {
363
            $schedule->set('timenextsend', $properties['timenextsend']);
364
        }
365
 
366
        $this->assertEquals($expected, schedule::should_send_schedule($schedule));
367
    }
368
 
369
    /**
370
     * Data provider for {@see test_calculate_next_send_time}
371
     *
372
     * @return array[]
373
     */
374
    public function calculate_next_send_time_provider(): array {
375
        $timescheduled = 1635865200; // Tue Nov 02 2021 15:00:00 GMT+0000.
376
        $timenow = 1639846800; // Sat Dec 18 2021 17:00:00 GMT+0000.
377
 
378
        return [
379
            'No recurrence' => [model::RECURRENCE_NONE, $timescheduled, $timenow, $timescheduled],
380
            'Recurrence, time scheduled in future' => [model::RECURRENCE_DAILY, $timenow + DAYSECS, $timenow, $timenow + DAYSECS],
381
            // Sun Dec 19 2021 15:00:00 GMT+0000.
382
            'Daily recurrence' => [model::RECURRENCE_DAILY, $timescheduled, $timenow, 1639926000],
383
            // Mon Dec 20 2021 15:00:00 GMT+0000.
384
            'Weekday recurrence' => [model::RECURRENCE_WEEKDAYS, $timescheduled, $timenow, 1640012400],
385
            // Tue Dec 21 2021 15:00:00 GMT+0000.
386
            'Weekly recurrence' => [model::RECURRENCE_WEEKLY, $timescheduled, $timenow, 1640098800],
387
            // Sun Jan 02 2022 15:00:00 GMT+0000.
388
            'Monthy recurrence' => [model::RECURRENCE_MONTHLY, $timescheduled, $timenow, 1641135600],
389
            // Wed Nov 02 2022 15:00:00 GMT+0000.
390
            'Annual recurrence' => [model::RECURRENCE_ANNUALLY, $timescheduled, $timenow, 1667401200],
391
         ];
392
    }
393
 
394
    /**
395
     * Test for calculating next schedule send time
396
     *
397
     * @param int $recurrence
398
     * @param int $timescheduled
399
     * @param int $timenow
400
     * @param int $expected
401
     *
402
     * @dataProvider calculate_next_send_time_provider
403
     */
404
    public function test_calculate_next_send_time(int $recurrence, int $timescheduled, int $timenow, int $expected): void {
405
        $this->resetAfterTest();
406
 
407
        /** @var core_reportbuilder_generator $generator */
408
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
409
        $report = $generator->create_report(['name' => 'My report', 'source' => users::class]);
410
 
411
        $schedule = $generator->create_schedule([
412
            'reportid' => $report->get('id'),
413
            'name' => 'My schedule',
414
            'recurrence' => $recurrence,
415
            'timescheduled' => $timescheduled,
416
            'timenow' => $timenow,
417
        ]);
418
 
419
        $this->assertEquals($expected, schedule::calculate_next_send_time($schedule, $timenow));
420
    }
421
}