Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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 mod_assign\external;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  global $CFG;
  22  
  23  require_once($CFG->dirroot . '/mod/assign/tests/externallib_advanced_testcase.php');
  24  
  25  /**
  26   * Test the start_submission external function.
  27   *
  28   * @package    mod_assign
  29   * @category   test
  30   * @covers     \mod_assign\external\start_submission
  31   * @author     Andrew Madden <andrewmadden@catalyst-au.net>
  32   * @copyright  2021 Catalyst IT
  33   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  class start_submission_test extends \mod_assign\externallib_advanced_testcase {
  36      /** @var \stdClass $course New course created to hold the assignments */
  37      protected $course = null;
  38  
  39      /**
  40       * Called before every test.
  41       */
  42      protected function setUp(): void {
  43          parent::setUp();
  44          $this->resetAfterTest();
  45          $this->course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
  46      }
  47  
  48      /**
  49       * Test start_submission if assignment doesn't exist matching id.
  50       */
  51      public function test_start_submission_with_invalid_assign_id() {
  52          $this->expectException(\dml_exception::class);
  53          start_submission::execute(123);
  54      }
  55  
  56      /**
  57       * Test start_submission if user is not able to access activity or course.
  58       */
  59      public function test_start_submission_when_user_has_no_capability_to_view_assignment() {
  60          $user = $this->getDataGenerator()->create_user();
  61          $this->setUser($user);
  62          $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
  63          $assign = $generator->create_instance(['course' => $this->course->id]);
  64  
  65          $this->expectException(\require_login_exception::class);
  66          start_submission::execute($assign->id);
  67      }
  68  
  69      /**
  70       * Test start_submission if assignment cut off date has elapsed.
  71       */
  72      public function test_start_submission_when_assignment_past_due_date() {
  73          $fiveminago = time() - 300;
  74          list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
  75                  false, ['cutoffdate' => $fiveminago]);
  76          $result = start_submission::execute($instance->id);
  77          $filteredwarnings = array_filter($result['warnings'], function($warning) {
  78              return $warning['warningcode'] === 'submissionnotopen';
  79          });
  80          $this->assertCount(1, $filteredwarnings);
  81          $this->assertEquals(0, $result['submissionid']);
  82          $warning = array_pop($filteredwarnings);
  83          $this->assertEquals($instance->id, $warning['itemid']);
  84          $this->assertEquals('This assignment is not open for submissions', $warning['item']);
  85      }
  86  
  87      /**
  88       * Test start_submission if time limit is disabled.
  89       */
  90      public function test_start_submission_when_time_limit_disabled() {
  91          list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status();
  92          $result = start_submission::execute($instance->id);
  93          $filteredwarnings = array_filter($result['warnings'], function($warning) {
  94              return $warning['warningcode'] === 'timelimitnotenabled';
  95          });
  96          $this->assertCount(1, $filteredwarnings);
  97          $this->assertEquals(0, $result['submissionid']);
  98          $warning = array_pop($filteredwarnings);
  99          $this->assertEquals($instance->id, $warning['itemid']);
 100          $this->assertEquals('Time limit is not enabled for assignment.', $warning['item']);
 101      }
 102  
 103      /**
 104       * Test start_submission if time limit is not set for assignment.
 105       */
 106      public function test_start_submission_when_time_limit_not_set() {
 107          set_config('enabletimelimit', '1', 'assign');
 108          list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status();
 109          $result = start_submission::execute($instance->id);
 110          $filteredwarnings = array_filter($result['warnings'], function($warning) {
 111              return $warning['warningcode'] === 'timelimitnotenabled';
 112          });
 113          $this->assertCount(1, $filteredwarnings);
 114          $this->assertEquals(0, $result['submissionid']);
 115          $warning = array_pop($filteredwarnings);
 116          $this->assertEquals($instance->id, $warning['itemid']);
 117          $this->assertEquals('Time limit is not enabled for assignment.', $warning['item']);
 118      }
 119  
 120      /**
 121       * Test start_submission if user already has open submission.
 122       */
 123      public function test_start_submission_when_submission_already_open() {
 124          global $DB;
 125          set_config('enabletimelimit', '1', 'assign');
 126          list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
 127              false, ['timelimit' => 300]);
 128          $submission = $assign->get_user_submission($student1->id, true);
 129          $submission->timestarted = time();
 130          $DB->update_record('assign_submission', $submission);
 131          $result = start_submission::execute($instance->id);
 132          $filteredwarnings = array_filter($result['warnings'], function($warning) {
 133              return $warning['warningcode'] === 'opensubmissionexists';
 134          });
 135          $this->assertCount(1, $filteredwarnings);
 136          $this->assertEquals(0, $result['submissionid']);
 137          $warning = array_pop($filteredwarnings);
 138          $this->assertEquals($instance->id, $warning['itemid']);
 139          $this->assertEquals('Open assignment submission already exists.', $warning['item']);
 140      }
 141  
 142      /**
 143       * Test start_submission if user has already submitted with no additional attempts available.
 144       */
 145      public function test_start_submission_with_no_attempts_available() {
 146          global $DB;
 147          set_config('enabletimelimit', '1', 'assign');
 148          list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
 149              false, ['timelimit' => 300]);
 150          $submission = $assign->get_user_submission($student1->id, true);
 151          $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
 152          $DB->update_record('assign_submission', $submission);
 153          $result = start_submission::execute($instance->id);
 154          $filteredwarnings = array_filter($result['warnings'], function($warning) {
 155              return $warning['warningcode'] === 'submissionnotopen';
 156          });
 157          $this->assertCount(1, $filteredwarnings);
 158          $this->assertEquals(0, $result['submissionid']);
 159          $warning = array_pop($filteredwarnings);
 160          $this->assertEquals($instance->id, $warning['itemid']);
 161          $this->assertEquals('This assignment is not open for submissions', $warning['item']);
 162      }
 163  
 164      /**
 165       * Test start_submission if user has no open submissions.
 166       */
 167      public function test_start_submission_with_new_submission() {
 168          global $DB;
 169          set_config('enabletimelimit', '1', 'assign');
 170          list($assign, $instance, $student1, $student2, $teacher, $g1, $g2) = $this->create_submission_for_testing_status(
 171              false, ['timelimit' => 300]);
 172          // Clear all current submissions.
 173          $DB->delete_records('assign_submission', ['assignment' => $instance->id]);
 174          $result = start_submission::execute($instance->id);
 175          $this->assertCount(0, $result['warnings']);
 176          $this->assertNotEmpty($result['submissionid']);
 177      }
 178  }