MDL-22078 course: End date tests
[moodle.git] / course / format / weeks / tests / format_weeks_test.php
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/>.
17 /**
18  * format_weeks related unit tests
19  *
20  * @package    format_weeks
21  * @copyright  2015 Marina Glancy
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
27 global $CFG;
28 require_once($CFG->dirroot . '/course/lib.php');
30 /**
31  * format_weeks related unit tests
32  *
33  * @package    format_weeks
34  * @copyright  2015 Marina Glancy
35  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class format_weeks_testcase extends advanced_testcase {
39     public function test_update_course_numsections() {
40         global $DB;
41         $this->resetAfterTest(true);
43         $generator = $this->getDataGenerator();
45         $course = $generator->create_course(array('numsections' => 10, 'format' => 'weeks'),
46             array('createsections' => true));
47         $generator->create_module('assign', array('course' => $course, 'section' => 7));
49         $this->setAdminUser();
51         $this->assertEquals(11, $DB->count_records('course_sections', array('course' => $course->id)));
53         // Change the numsections to 8, last two sections did not have any activities, they should be deleted.
54         update_course((object)array('id' => $course->id, 'numsections' => 8));
55         $this->assertEquals(9, $DB->count_records('course_sections', array('course' => $course->id)));
56         $this->assertEquals(9, count(get_fast_modinfo($course)->get_section_info_all()));
58         // Change the numsections to 5, section 8 should be deleted but section 7 should remain as it has activities.
59         update_course((object)array('id' => $course->id, 'numsections' => 6));
60         $this->assertEquals(8, $DB->count_records('course_sections', array('course' => $course->id)));
61         $this->assertEquals(8, count(get_fast_modinfo($course)->get_section_info_all()));
62         $this->assertEquals(6, course_get_format($course)->get_course()->numsections);
63     }
65     /**
66      * Tests for format_weeks::get_section_name method with default section names.
67      */
68     public function test_get_section_name() {
69         global $DB;
70         $this->resetAfterTest(true);
72         // Generate a course with 5 sections.
73         $generator = $this->getDataGenerator();
74         $numsections = 5;
75         $course = $generator->create_course(array('numsections' => $numsections, 'format' => 'weeks'),
76             array('createsections' => true));
78         // Get section names for course.
79         $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
81         // Test get_section_name with default section names.
82         $courseformat = course_get_format($course);
83         foreach ($coursesections as $section) {
84             // Assert that with unmodified section names, get_section_name returns the same result as get_default_section_name.
85             $this->assertEquals($courseformat->get_default_section_name($section), $courseformat->get_section_name($section));
86         }
87     }
89     /**
90      * Tests for format_weeks::get_section_name method with modified section names.
91      */
92     public function test_get_section_name_customised() {
93         global $DB;
94         $this->resetAfterTest(true);
96         // Generate a course with 5 sections.
97         $generator = $this->getDataGenerator();
98         $numsections = 5;
99         $course = $generator->create_course(array('numsections' => $numsections, 'format' => 'weeks'),
100             array('createsections' => true));
102         // Get section names for course.
103         $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
105         // Modify section names.
106         $customname = "Custom Section";
107         foreach ($coursesections as $section) {
108             $section->name = "$customname $section->section";
109             $DB->update_record('course_sections', $section);
110         }
112         // Requery updated section names then test get_section_name.
113         $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
114         $courseformat = course_get_format($course);
115         foreach ($coursesections as $section) {
116             // Assert that with modified section names, get_section_name returns the modified section name.
117             $this->assertEquals($section->name, $courseformat->get_section_name($section));
118         }
119     }
121     /**
122      * Tests for format_weeks::get_default_section_name.
123      */
124     public function test_get_default_section_name() {
125         global $DB;
126         $this->resetAfterTest(true);
128         // Generate a course with 5 sections.
129         $generator = $this->getDataGenerator();
130         $numsections = 5;
131         $course = $generator->create_course(array('numsections' => $numsections, 'format' => 'weeks'),
132             array('createsections' => true));
134         // Get section names for course.
135         $coursesections = $DB->get_records('course_sections', array('course' => $course->id));
137         // Test get_default_section_name with default section names.
138         $courseformat = course_get_format($course);
139         foreach ($coursesections as $section) {
140             if ($section->section == 0) {
141                 $sectionname = get_string('section0name', 'format_weeks');
142                 $this->assertEquals($sectionname, $courseformat->get_default_section_name($section));
143             } else {
144                 $dates = $courseformat->get_section_dates($section);
145                 $dates->end = ($dates->end - 86400);
146                 $dateformat = get_string('strftimedateshort');
147                 $weekday = userdate($dates->start, $dateformat);
148                 $endweekday = userdate($dates->end, $dateformat);
149                 $sectionname = $weekday.' - '.$endweekday;
151                 $this->assertEquals($sectionname, $courseformat->get_default_section_name($section));
152             }
153         }
154     }
156     /**
157      * Test web service updating section name
158      */
159     public function test_update_inplace_editable() {
160         global $CFG, $DB, $PAGE;
161         require_once($CFG->dirroot . '/lib/external/externallib.php');
163         $this->resetAfterTest();
164         $user = $this->getDataGenerator()->create_user();
165         $this->setUser($user);
166         $course = $this->getDataGenerator()->create_course(array('numsections' => 5, 'format' => 'weeks'),
167             array('createsections' => true));
168         $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2));
170         // Call webservice without necessary permissions.
171         try {
172             core_external::update_inplace_editable('format_weeks', 'sectionname', $section->id, 'New section name');
173             $this->fail('Exception expected');
174         } catch (moodle_exception $e) {
175             $this->assertEquals('Course or activity not accessible. (Not enrolled)',
176                     $e->getMessage());
177         }
179         // Change to teacher and make sure that section name can be updated using web service update_inplace_editable().
180         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
181         $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
183         $res = core_external::update_inplace_editable('format_weeks', 'sectionname', $section->id, 'New section name');
184         $res = external_api::clean_returnvalue(core_external::update_inplace_editable_returns(), $res);
185         $this->assertEquals('New section name', $res['value']);
186         $this->assertEquals('New section name', $DB->get_field('course_sections', 'name', array('id' => $section->id)));
187     }
189     /**
190      * Test callback updating section name
191      */
192     public function test_inplace_editable() {
193         global $CFG, $DB, $PAGE;
195         $this->resetAfterTest();
196         $user = $this->getDataGenerator()->create_user();
197         $course = $this->getDataGenerator()->create_course(array('numsections' => 5, 'format' => 'weeks'),
198             array('createsections' => true));
199         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
200         $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id);
201         $this->setUser($user);
203         $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2));
205         // Call callback format_weeks_inplace_editable() directly.
206         $tmpl = component_callback('format_weeks', 'inplace_editable', array('sectionname', $section->id, 'Rename me again'));
207         $this->assertInstanceOf('core\output\inplace_editable', $tmpl);
208         $res = $tmpl->export_for_template($PAGE->get_renderer('core'));
209         $this->assertEquals('Rename me again', $res['value']);
210         $this->assertEquals('Rename me again', $DB->get_field('course_sections', 'name', array('id' => $section->id)));
212         // Try updating using callback from mismatching course format.
213         try {
214             $tmpl = component_callback('format_topics', 'inplace_editable', array('sectionname', $section->id, 'New name'));
215             $this->fail('Exception expected');
216         } catch (moodle_exception $e) {
217             $this->assertEquals(1, preg_match('/^Can not find data record in database/', $e->getMessage()));
218         }
219     }
221     /**
222      * Test get_default_course_enddate.
223      *
224      * @return void
225      */
226     public function test_default_course_enddate() {
227         global $CFG, $DB;
229         $this->resetAfterTest(true);
231         require_once($CFG->dirroot . '/course/tests/fixtures/testable_course_edit_form.php');
233         $this->setTimezone('UTC');
235         $params = array('format' => 'weeks', 'numsections' => 5, 'startdate' => 1445644800);
236         $course = $this->getDataGenerator()->create_course($params);
237         $category = $DB->get_record('course_categories', array('id' => $course->category));
239         $args = [
240             'course' => $course,
241             'category' => $category,
242             'editoroptions' => [
243                 'context' => context_course::instance($course->id),
244                 'subdirs' => 0
245             ],
246             'returnto' => new moodle_url('/'),
247             'returnurl' => new moodle_url('/'),
248         ];
250         $courseform = new testable_course_edit_form(null, $args);
251         $courseform->definition_after_data();
253         // format_weeks::get_section_dates is adding 2h to avoid DST problems, we need to replicate it here.
254         $enddate = $params['startdate'] + (WEEKSECS * $params['numsections']) + 7200;
256         $weeksformat = course_get_format($course->id);
257         $this->assertEquals($enddate, $weeksformat->get_default_course_enddate($courseform->get_quick_form()));
258     }