diff --git a/lib.php b/lib.php index efc09a2..24466f1 100644 --- a/lib.php +++ b/lib.php @@ -191,13 +191,10 @@ function kialo_update_visibility_depending_on_accepted_terms(): void { * @param stdClass $grades grade object * @return int Returns GRADE_UPDATE_OK, GRADE_UPDATE_FAILED, GRADE_UPDATE_MULTIPLE or GRADE_UPDATE_ITEM_LOCKED */ -function kialo_grade_item_update(stdClass $kialo, $grades = null): int { +function kialo_grade_item_update(stdClass $kialo, ?stdClass $grades = null): int { $params = [ 'itemname' => $kialo->name, 'idnumber' => $kialo->cmidnumber ?? '', - 'itemtype' => 'mod', - 'itemmodule' => 'kialo', - 'itemnumber' => 0, ]; if ($kialo->grade > 0) { @@ -241,9 +238,7 @@ function kialo_update_grades(stdClass $kialo, int $userid = 0, bool $nullifnone global $CFG, $DB; require_once($CFG->libdir.'/gradelib.php'); - if (empty($kialo->assessed) || !$kialo->assessed) { - kialo_grade_item_update($kialo); - } else if ($grades = kialo_get_user_grades($kialo, $userid)) { + if ($userid > 0 && $grades = kialo_get_user_grades($kialo, $userid)) { kialo_grade_item_update($kialo, $grades); } else if ($userid && $nullifnone) { $grade = new stdClass(); diff --git a/tests/classes/kialo_config_test.php b/tests/classes/kialo_config_test.php index 698e352..51018c8 100644 --- a/tests/classes/kialo_config_test.php +++ b/tests/classes/kialo_config_test.php @@ -86,6 +86,7 @@ public function test_get_platform(): void { $this->assertEquals("https://www.example.com/moodle/mod/kialo", $platform->getAudience()); $this->assertEquals("https://www.example.com/moodle/mod/kialo/lti_auth.php", $platform->getOidcAuthenticationUrl()); + $this->assertEquals("https://www.example.com/moodle/mod/kialo/lti_token.php", $platform->getOAuth2AccessTokenUrl()); $this->assertEquals("kialo-moodle-plugin", $platform->getIdentifier()); $this->assertEquals("Kialo Moodle Plugin", $platform->getName()); } @@ -125,4 +126,19 @@ public function test_registration(): void { $this->assertEquals("https://www.kialo-edu.com/lti/jwks.json", $registration->getToolJwksUrl()); $this->assertEquals("https://www.example.com/moodle/mod/kialo/lti_jwks.php", $registration->getPlatformJwksUrl()); } + + /** + * Tests the registration repository. + * @covers \mod_kialo\kialo_config::get_instance::get_registration_repository + */ + public function test_registration_repository(): void { + $repo = kialo_config::get_instance()->get_registration_repository("DEPLID1234"); + $this->assertNotNull($repo); + + $this->assertNull($repo->find("NONEXISTENT")); + + $registration = $repo->find("kialo-moodle-registration"); + $this->assertNotNull($registration); + $this->assertEquals("kialo-moodle-registration", $registration->getIdentifier()); + } } diff --git a/tests/classes/kialo_view_test.php b/tests/classes/kialo_view_test.php index cec8a2c..264da6e 100644 --- a/tests/classes/kialo_view_test.php +++ b/tests/classes/kialo_view_test.php @@ -25,6 +25,7 @@ namespace mod_kialo; +use GuzzleHttp\Psr7\Response; use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -224,4 +225,38 @@ public function test_group_info_grouping(): void { $this->assertEquals("grouping-{$grouping->id}", $groupinfo->groupid); $this->assertEquals($grouping->name, $groupinfo->groupname); } + + /** + * Tests writing an HTTP response. + * + * @return void + * @covers \mod_kialo\kialo_view::write_response + */ + public function test_write_response(): void { + $headers = [ + 'Content-Type' => 'application/json', + 'X-Test-Header' => 'test', + ]; + $json = json_encode(['message' => 'Hello, world!']); + $response = new Response(200, $headers, $json); + + ob_start(); + kialo_view::write_response($response); + $output = ob_get_clean(); + + $this->assertStringContainsString('HTTP/1.1 200 OK', $output); + $this->assertStringContainsString('Content-Type: application/json', $output); + $this->assertStringContainsString('X-Test-Header: test', $output); + $this->assertStringContainsString($json, $output); + } +} + +/** + * Mocks the header function, simpling printing to stdout so it can be asserted. + * + * @param string $str + * @return void + */ +function header(string $str): void { + echo $str . '\n'; } diff --git a/tests/classes/moodle_cache_test.php b/tests/classes/moodle_cache_test.php index 1e0aeda..632456b 100644 --- a/tests/classes/moodle_cache_test.php +++ b/tests/classes/moodle_cache_test.php @@ -53,6 +53,17 @@ protected function setUp(): void { $this->cache = moodle_cache::nonce_cache(); } + /** + * Tests that the nonce cache is created correctly. + * + * @return void + * @covers \mod_kialo\moodle_cache::nonce_cache + */ + public function test_access_token_cache(): void { + $this->cache = moodle_cache::access_token_cache(); + $this->assertInstanceOf(moodle_cache::class, $this->cache); + } + /** * Tests that setting and getting of individual cache items works. * diff --git a/tests/lib_test.php b/tests/lib_test.php index 448314d..abb5345 100644 --- a/tests/lib_test.php +++ b/tests/lib_test.php @@ -71,14 +71,24 @@ public function test_kialo_supports(): void { * Check add instance * * @covers ::kialo_add_instance + * @var $DB \DB */ public function test_kialo_add_instance(): void { + global $DB; $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course(); $id = kialo_add_instance((object) ["name" => "Test", "course" => $course->id, "grade" => 100]); $this->assertNotNull($id); + + // By default, the activity is created with a maximum grade of 100 points. + $instance = $DB->get_record('kialo', ['id' => $id], '*', MUST_EXIST); + $this->assertEquals(100, $instance->grade); + + // A line item should be created in the gradebook. + $gradeitem = $DB->get_record('grade_items', ['iteminstance' => $id, 'itemmodule' => 'kialo'], '*', MUST_EXIST); + $this->assertEquals(100, $gradeitem->grademax); } /** @@ -216,4 +226,106 @@ public function test_disable_module_when_terms_have_not_been_accepted(): void { $this->assertNotContains('kialo', \core_plugin_manager::instance()->get_enabled_plugins('mod')); } + + /** + * Check the kialo_grade_item_update function. + * + * @covers ::kialo_grade_item_update + * @var $DB \DB + */ + public function test_kialo_grade_item_update_no_scale(): void { + global $DB; + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $kialo = $this->getDataGenerator()->create_module('kialo', ['course' => $course]); + + $this->assertEquals(GRADE_UPDATE_OK, kialo_grade_item_update($kialo)); + + // Line item should have been updated/created accordingly. + $gradeitem = $DB->get_record('grade_items', ['iteminstance' => $kialo->id, 'itemmodule' => 'kialo'], '*', MUST_EXIST); + $this->assertEquals(100, $gradeitem->grademax); + $this->assertEquals(0, $gradeitem->grademin); + $this->assertEquals(GRADE_TYPE_VALUE, $gradeitem->gradetype); + } + + /** + * Check the kialo_grade_item_update function when using scales instead of regular points. + * + * @covers ::kialo_grade_item_update + * @var $DB \DB + */ + public function test_kialo_grade_item_update_scale(): void { + global $DB; + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $kialo = $this->getDataGenerator()->create_module('kialo', ['course' => $course]); + $kialo->grade = -1; + + $this->assertEquals(GRADE_UPDATE_OK, kialo_grade_item_update($kialo)); + + // Line item should have been updated/created accordingly. + $gradeitem = $DB->get_record('grade_items', ['iteminstance' => $kialo->id, 'itemmodule' => 'kialo'], '*', MUST_EXIST); + $this->assertEquals(1, $gradeitem->scaleid); // The value of `-grade` is the scale ID. + $this->assertEquals(GRADE_TYPE_SCALE, $gradeitem->gradetype); + } + + /** + * Check that updating and reading grades works. + * + * @covers ::kialo_grade_item_update + * @covers ::kialo_get_user_grades + * @var $DB \DB + */ + public function test_kialo_get_and_set_user_grades(): void { + global $DB; + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $user = $this->getDataGenerator()->create_user(); + $kialo = $this->getDataGenerator()->create_module('kialo', ['course' => $course]); + + // Initially there should be no grade. + $grades = kialo_get_user_grades($kialo, $user->id); + $this->assertEmpty($grades->errors); + $this->assertCount(1, $grades->items); + + $gradeitem = $grades->items[0]; + $this->assertEquals(0, $gradeitem->grademin); + $this->assertEquals(100, $gradeitem->grademax); + $this->assertEquals('mod', $gradeitem->itemtype); + $this->assertEquals('kialo', $gradeitem->itemmodule); + $this->assertEquals(0, $gradeitem->itemnumber); + $this->assertEquals(0, $gradeitem->scaleid); + + $this->assertCount(1, $gradeitem->grades); + $grade = current($gradeitem->grades); + $this->assertNull($grade->grade); + $this->assertNull($grade->feedback); + $this->assertNull($grade->datesubmitted); + + // Set a grade. + $grade = new \stdClass(); + $grade->userid = $user->id; + $grade->rawgrade = 50; + $grade->feedback = 'Good job!'; + $grade->datesubmitted = time(); + kialo_grade_item_update($kialo, $grade); + + // The grade should be set now. + $grades = kialo_get_user_grades($kialo, $user->id); + $this->assertEmpty($grades->errors); + $this->assertCount(1, $grades->items); + + $gradeitem = $grades->items[0]; + $this->assertCount(1, $gradeitem->grades); + $grade = current($gradeitem->grades); + $this->assertEquals(50, $grade->grade); + $this->assertEquals('Good job!', $grade->feedback); + $this->assertNotNull($grade->datesubmitted); + + // I don't know why these warnings appear. The test itself works as expected, and the plugin code itself, as well. + $this->expectOutputRegex('/(The instance of this module does not exist)+/'); + } }