Merge branch 'dashboard-split-overview-block' of https://github.com/ryanwyllie/moodle

This commit is contained in:
Andrew Nicols 2018-09-27 14:08:55 +08:00
commit 20f9b981f9
137 changed files with 5871 additions and 2450 deletions

View file

@ -4227,4 +4227,494 @@ class core_course_courselib_testcase extends advanced_testcase {
assign_capability('moodle/backup:downloadfile', CAP_ALLOW, $teacherrole->id, $context);
$this->assertFalse(can_download_from_backup_filearea('testing', $context, $user));
}
/**
* Test cases for the course_classify_courses_for_timeline test.
*/
public function get_course_classify_courses_for_timeline_test_cases() {
$now = time();
$day = 86400;
return [
'no courses' => [
'coursesdata' => [],
'expected' => [
COURSE_TIMELINE_PAST => [],
COURSE_TIMELINE_FUTURE => [],
COURSE_TIMELINE_INPROGRESS => []
]
],
'only past' => [
'coursesdata' => [
[
'shortname' => 'past1',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'past2',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
]
],
'expected' => [
COURSE_TIMELINE_PAST => ['past1', 'past2'],
COURSE_TIMELINE_FUTURE => [],
COURSE_TIMELINE_INPROGRESS => []
]
],
'only in progress' => [
'coursesdata' => [
[
'shortname' => 'inprogress1',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'inprogress2',
'startdate' => $now - $day,
'enddate' => $now + $day
]
],
'expected' => [
COURSE_TIMELINE_PAST => [],
COURSE_TIMELINE_FUTURE => [],
COURSE_TIMELINE_INPROGRESS => ['inprogress1', 'inprogress2']
]
],
'only future' => [
'coursesdata' => [
[
'shortname' => 'future1',
'startdate' => $now + $day
],
[
'shortname' => 'future2',
'startdate' => $now + $day
]
],
'expected' => [
COURSE_TIMELINE_PAST => [],
COURSE_TIMELINE_FUTURE => ['future1', 'future2'],
COURSE_TIMELINE_INPROGRESS => []
]
],
'combination' => [
'coursesdata' => [
[
'shortname' => 'past1',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'past2',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'inprogress1',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'inprogress2',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'future1',
'startdate' => $now + $day
],
[
'shortname' => 'future2',
'startdate' => $now + $day
]
],
'expected' => [
COURSE_TIMELINE_PAST => ['past1', 'past2'],
COURSE_TIMELINE_FUTURE => ['future1', 'future2'],
COURSE_TIMELINE_INPROGRESS => ['inprogress1', 'inprogress2']
]
],
];
}
/**
* Test the course_classify_courses_for_timeline function.
*
* @dataProvider get_course_classify_courses_for_timeline_test_cases()
* @param array $coursesdata Courses to create
* @param array $expected Expected test results.
*/
public function test_course_classify_courses_for_timeline($coursesdata, $expected) {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$courses = array_map(function($coursedata) use ($generator) {
return $generator->create_course($coursedata);
}, $coursesdata);
sort($expected[COURSE_TIMELINE_PAST]);
sort($expected[COURSE_TIMELINE_FUTURE]);
sort($expected[COURSE_TIMELINE_INPROGRESS]);
$results = course_classify_courses_for_timeline($courses);
$actualpast = array_map(function($result) {
return $result->shortname;
}, $results[COURSE_TIMELINE_PAST]);
$actualfuture = array_map(function($result) {
return $result->shortname;
}, $results[COURSE_TIMELINE_FUTURE]);
$actualinprogress = array_map(function($result) {
return $result->shortname;
}, $results[COURSE_TIMELINE_INPROGRESS]);
sort($actualpast);
sort($actualfuture);
sort($actualinprogress);
$this->assertEquals($expected[COURSE_TIMELINE_PAST], $actualpast);
$this->assertEquals($expected[COURSE_TIMELINE_FUTURE], $actualfuture);
$this->assertEquals($expected[COURSE_TIMELINE_INPROGRESS], $actualinprogress);
}
/**
* Test cases for the course_get_enrolled_courses_for_logged_in_user tests.
*/
public function get_course_get_enrolled_courses_for_logged_in_user_test_cases() {
$buildexpectedresult = function($limit, $offset) {
$result = [];
for ($i = $offset; $i < $offset + $limit; $i++) {
$result[] = "testcourse{$i}";
}
return $result;
};
return [
'zero records' => [
'dbquerylimit' => 3,
'totalcourses' => 0,
'limit' => 0,
'offset' => 0,
'expecteddbqueries' => 1,
'expectedresult' => $buildexpectedresult(0, 0)
],
'less than query limit' => [
'dbquerylimit' => 3,
'totalcourses' => 2,
'limit' => 0,
'offset' => 0,
'expecteddbqueries' => 1,
'expectedresult' => $buildexpectedresult(2, 0)
],
'more than query limit' => [
'dbquerylimit' => 3,
'totalcourses' => 7,
'limit' => 0,
'offset' => 0,
'expecteddbqueries' => 3,
'expectedresult' => $buildexpectedresult(7, 0)
],
'limit less than query limit' => [
'dbquerylimit' => 3,
'totalcourses' => 7,
'limit' => 2,
'offset' => 0,
'expecteddbqueries' => 1,
'expectedresult' => $buildexpectedresult(2, 0)
],
'limit less than query limit with offset' => [
'dbquerylimit' => 3,
'totalcourses' => 7,
'limit' => 2,
'offset' => 2,
'expecteddbqueries' => 1,
'expectedresult' => $buildexpectedresult(2, 2)
],
'limit less than total' => [
'dbquerylimit' => 3,
'totalcourses' => 9,
'limit' => 6,
'offset' => 0,
'expecteddbqueries' => 2,
'expectedresult' => $buildexpectedresult(6, 0)
],
'less results than limit' => [
'dbquerylimit' => 4,
'totalcourses' => 9,
'limit' => 20,
'offset' => 0,
'expecteddbqueries' => 3,
'expectedresult' => $buildexpectedresult(9, 0)
],
'less results than limit exact divisible' => [
'dbquerylimit' => 3,
'totalcourses' => 9,
'limit' => 20,
'offset' => 0,
'expecteddbqueries' => 4,
'expectedresult' => $buildexpectedresult(9, 0)
],
'less results than limit with offset' => [
'dbquerylimit' => 3,
'totalcourses' => 9,
'limit' => 10,
'offset' => 5,
'expecteddbqueries' => 2,
'expectedresult' => $buildexpectedresult(4, 5)
],
];
}
/**
* Test the course_get_enrolled_courses_for_logged_in_user function.
*
* @dataProvider get_course_get_enrolled_courses_for_logged_in_user_test_cases()
* @param int $dbquerylimit Number of records to load per DB request
* @param int $totalcourses Number of courses to create
* @param int $limit Maximum number of results to get.
* @param int $offset Skip this number of results from the start of the result set.
* @param int $expecteddbqueries The number of DB queries expected during the test.
* @param array $expectedresult Expected test results.
*/
public function test_course_get_enrolled_courses_for_logged_in_user(
$dbquerylimit,
$totalcourses,
$limit,
$offset,
$expecteddbqueries,
$expectedresult
) {
global $DB;
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$student = $generator->create_user();
for ($i = 0; $i < $totalcourses; $i++) {
$shortname = "testcourse{$i}";
$course = $generator->create_course(['shortname' => $shortname]);
$generator->enrol_user($student->id, $course->id, 'student');
}
$this->setUser($student);
$initialquerycount = $DB->perf_get_queries();
$courses = course_get_enrolled_courses_for_logged_in_user($limit, $offset, 'shortname ASC', 'shortname', $dbquerylimit);
// Loop over the result set to force the lazy loading to kick in so that we can check the
// number of DB queries.
$actualresult = array_map(function($course) {
return $course->shortname;
}, iterator_to_array($courses, false));
sort($expectedresult);
$this->assertEquals($expectedresult, $actualresult);
$this->assertEquals($expecteddbqueries, $DB->perf_get_queries() - $initialquerycount);
}
/**
* Test cases for the course_filter_courses_by_timeline_classification tests.
*/
public function get_course_filter_courses_by_timeline_classification_test_cases() {
$now = time();
$day = 86400;
$coursedata = [
[
'shortname' => 'apast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'bpast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'cpast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'dpast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'epast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'ainprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'binprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'cinprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'dinprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'einprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'afuture',
'startdate' => $now + $day
],
[
'shortname' => 'bfuture',
'startdate' => $now + $day
],
[
'shortname' => 'cfuture',
'startdate' => $now + $day
],
[
'shortname' => 'dfuture',
'startdate' => $now + $day
],
[
'shortname' => 'efuture',
'startdate' => $now + $day
]
];
// Raw enrolled courses result set should be returned in this order:
// afuture, ainprogress, apast, bfuture, binprogress, bpast, cfuture, cinprogress, cpast,
// dfuture, dinprogress, dpast, efuture, einprogress, epast
//
// By classification the offset values for each record should be:
// COURSE_TIMELINE_FUTURE
// 0 (afuture), 3 (bfuture), 6 (cfuture), 9 (dfuture), 12 (efuture)
// COURSE_TIMELINE_INPROGRESS
// 1 (ainprogress), 4 (binprogress), 7 (cinprogress), 10 (dinprogress), 13 (einprogress)
// COURSE_TIMELINE_PAST
// 2 (apast), 5 (bpast), 8 (cpast), 11 (dpast), 14 (epast).
return [
'empty set' => [
'coursedata' => [],
'classification' => COURSE_TIMELINE_FUTURE,
'limit' => 2,
'offset' => 0,
'expectedcourses' => [],
'expectedprocessedcount' => 0
],
// COURSE_TIMELINE_FUTURE.
'future not limit no offset' => [
'coursedata' => $coursedata,
'classification' => COURSE_TIMELINE_FUTURE,
'limit' => 0,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
'expectedprocessedcount' => 15
],
'future no offset' => [
'coursedata' => $coursedata,
'classification' => COURSE_TIMELINE_FUTURE,
'limit' => 2,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture'],
'expectedprocessedcount' => 4
],
'future offset' => [
'coursedata' => $coursedata,
'classification' => COURSE_TIMELINE_FUTURE,
'limit' => 2,
'offset' => 2,
'expectedcourses' => ['bfuture', 'cfuture'],
'expectedprocessedcount' => 5
],
'future exact limit' => [
'coursedata' => $coursedata,
'classification' => COURSE_TIMELINE_FUTURE,
'limit' => 5,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
'expectedprocessedcount' => 13
],
'future limit less results' => [
'coursedata' => $coursedata,
'classification' => COURSE_TIMELINE_FUTURE,
'limit' => 10,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
'expectedprocessedcount' => 15
],
'future limit less results with offset' => [
'coursedata' => $coursedata,
'classification' => COURSE_TIMELINE_FUTURE,
'limit' => 10,
'offset' => 5,
'expectedcourses' => ['cfuture', 'dfuture', 'efuture'],
'expectedprocessedcount' => 10
],
];
}
/**
* Test the course_filter_courses_by_timeline_classification function.
*
* @dataProvider get_course_filter_courses_by_timeline_classification_test_cases()
* @param array $coursedata Course test data to create.
* @param string $classification Timeline classification.
* @param int $limit Maximum number of results to return.
* @param int $offset Results to skip at the start of the result set.
* @param string[] $expectedcourses Expected courses in results.
* @param int $expectedprocessedcount Expected number of course records to be processed.
*/
public function test_course_filter_courses_by_timeline_classification(
$coursedata,
$classification,
$limit,
$offset,
$expectedcourses,
$expectedprocessedcount
) {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$courses = array_map(function($coursedata) use ($generator) {
return $generator->create_course($coursedata);
}, $coursedata);
$student = $generator->create_user();
foreach ($courses as $course) {
$generator->enrol_user($student->id, $course->id, 'student');
}
$this->setUser($student);
$coursesgenerator = course_get_enrolled_courses_for_logged_in_user(0, $offset, 'shortname ASC', 'shortname');
list($result, $processedcount) = course_filter_courses_by_timeline_classification(
$coursesgenerator,
$classification,
$limit
);
$actual = array_map(function($course) {
return $course->shortname;
}, $result);
$this->assertEquals($expectedcourses, $actual);
$this->assertEquals($expectedprocessedcount, $processedcount);
}
}

View file

@ -2341,4 +2341,218 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
$this->assertCount(1, $result['warnings']);
$this->assertEquals(-2, $result['warnings'][0]['itemid']);
}
/**
* Test cases for the get_enrolled_courses_by_timeline_classification test.
*/
public function get_get_enrolled_courses_by_timeline_classification_test_cases() {
$now = time();
$day = 86400;
$coursedata = [
[
'shortname' => 'apast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'bpast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'cpast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'dpast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'epast',
'startdate' => $now - ($day * 2),
'enddate' => $now - $day
],
[
'shortname' => 'ainprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'binprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'cinprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'dinprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'einprogress',
'startdate' => $now - $day,
'enddate' => $now + $day
],
[
'shortname' => 'afuture',
'startdate' => $now + $day
],
[
'shortname' => 'bfuture',
'startdate' => $now + $day
],
[
'shortname' => 'cfuture',
'startdate' => $now + $day
],
[
'shortname' => 'dfuture',
'startdate' => $now + $day
],
[
'shortname' => 'efuture',
'startdate' => $now + $day
]
];
// Raw enrolled courses result set should be returned in this order:
// afuture, ainprogress, apast, bfuture, binprogress, bpast, cfuture, cinprogress, cpast,
// dfuture, dinprogress, dpast, efuture, einprogress, epast
//
// By classification the offset values for each record should be:
// COURSE_TIMELINE_FUTURE
// 0 (afuture), 3 (bfuture), 6 (cfuture), 9 (dfuture), 12 (efuture)
// COURSE_TIMELINE_INPROGRESS
// 1 (ainprogress), 4 (binprogress), 7 (cinprogress), 10 (dinprogress), 13 (einprogress)
// COURSE_TIMELINE_PAST
// 2 (apast), 5 (bpast), 8 (cpast), 11 (dpast), 14 (epast).
//
// NOTE: The offset applies to the unfiltered full set of courses before the classification
// filtering is done.
// E.g. In our example if an offset of 2 is given then it would mean the first
// two courses (afuture, ainprogress) are ignored.
return [
'empty set' => [
'coursedata' => [],
'classification' => 'future',
'limit' => 2,
'offset' => 0,
'expectedcourses' => [],
'expectednextoffset' => 0
],
// COURSE_TIMELINE_FUTURE.
'future not limit no offset' => [
'coursedata' => $coursedata,
'classification' => 'future',
'limit' => 0,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
'expectednextoffset' => 15
],
'future no offset' => [
'coursedata' => $coursedata,
'classification' => 'future',
'limit' => 2,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture'],
'expectednextoffset' => 4
],
'future offset' => [
'coursedata' => $coursedata,
'classification' => 'future',
'limit' => 2,
'offset' => 2,
'expectedcourses' => ['bfuture', 'cfuture'],
'expectednextoffset' => 7
],
'future exact limit' => [
'coursedata' => $coursedata,
'classification' => 'future',
'limit' => 5,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
'expectednextoffset' => 13
],
'future limit less results' => [
'coursedata' => $coursedata,
'classification' => 'future',
'limit' => 10,
'offset' => 0,
'expectedcourses' => ['afuture', 'bfuture', 'cfuture', 'dfuture', 'efuture'],
'expectednextoffset' => 15
],
'future limit less results with offset' => [
'coursedata' => $coursedata,
'classification' => 'future',
'limit' => 10,
'offset' => 5,
'expectedcourses' => ['cfuture', 'dfuture', 'efuture'],
'expectednextoffset' => 15
],
];
}
/**
* Test the get_enrolled_courses_by_timeline_classification function.
*
* @dataProvider get_get_enrolled_courses_by_timeline_classification_test_cases()
* @param array $coursedata Courses to create
* @param string $classification Timeline classification
* @param int $limit Maximum number of results
* @param int $offset Offset the unfiltered courses result set by this amount
* @param array $expectedcourses Expected courses in result
* @param int $expectednextoffset Expected next offset value in result
*/
public function test_get_enrolled_courses_by_timeline_classification(
$coursedata,
$classification,
$limit,
$offset,
$expectedcourses,
$expectednextoffset
) {
$this->resetAfterTest();
$generator = $this->getDataGenerator();
$courses = array_map(function($coursedata) use ($generator) {
return $generator->create_course($coursedata);
}, $coursedata);
$student = $generator->create_user();
foreach ($courses as $course) {
$generator->enrol_user($student->id, $course->id, 'student');
}
$this->setUser($student);
// NOTE: The offset applies to the unfiltered full set of courses before the classification
// filtering is done.
// E.g. In our example if an offset of 2 is given then it would mean the first
// two courses (afuture, ainprogress) are ignored.
$result = core_course_external::get_enrolled_courses_by_timeline_classification(
$classification,
$limit,
$offset,
'shortname ASC'
);
$result = external_api::clean_returnvalue(
core_course_external::get_enrolled_courses_by_timeline_classification_returns(),
$result
);
$actual = array_map(function($course) {
return $course['shortname'];
}, $result['courses']);
$this->assertEquals($expectedcourses, $actual);
$this->assertEquals($expectednextoffset, $result['nextoffset']);
}
}