Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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 core_question;
18
 
19
use core_question\local\bank\question_bank_helper;
20
 
21
/**
22
 * question bank helper class tests.
23
 *
24
 * @package    core_question
25
 * @copyright  2024 onwards Catalyst IT EU {@link https://catalyst-eu.net}
26
 * @author     Simon Adams <simon.adams@catalyst-eu.net>
27
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28
 * @covers \core_question\local\bank\question_bank_helper
29
 */
30
final class question_bank_helper_test extends \advanced_testcase {
31
 
32
    /**
33
     * Assert that at least 1 module type that shares questions exists and that mod_qbank is in the returned list.
34
     *
35
     * @return void
36
     * @covers ::get_activity_types_with_shareable_questions
37
     */
38
    public function test_get_shareable_modules(): void {
39
        $openmods = question_bank_helper::get_activity_types_with_shareable_questions();
40
        $this->assertGreaterThanOrEqual(1, count($openmods));
41
        $this->assertContains('qbank', $openmods);
42
        $this->assertNotContains('quiz', $openmods);
43
    }
44
 
45
    /**
46
     * Assert that at least 1 module type that does not share questions exists and that mod_quiz is in the returned list.
47
     *
48
     * @return void
49
     * @covers ::get_activity_types_with_private_questions
50
     */
51
    public function test_get_private_modules(): void {
52
        $closedmods = question_bank_helper::get_activity_types_with_private_questions();
53
        $this->assertGreaterThanOrEqual(1, count($closedmods));
54
        $this->assertContains('quiz', $closedmods);
55
        $this->assertNotContains('qbank', $closedmods);
56
    }
57
 
58
    /**
59
     * Setup some courses with quiz and qbank module instances and set different permissions for a user.
60
     * Then assert that the correct results are returned from calls to the class methods.
61
     *
62
     * @covers ::get_activity_instances_with_shareable_questions
63
     * @covers ::get_activity_instances_with_private_questions
64
     * @return void
65
     */
66
    public function test_get_instances(): void {
67
        global $DB;
68
 
69
        $this->resetAfterTest();
70
        $user = self::getDataGenerator()->create_user();
71
        $roles = $DB->get_records('role', [], '', 'shortname, id');
72
        self::setUser($user);
73
 
74
        $qgen = self::getDataGenerator()->get_plugin_generator('core_question');
75
        $sharedmodgen = self::getDataGenerator()->get_plugin_generator('mod_qbank');
76
        $privatemodgen = self::getDataGenerator()->get_plugin_generator('mod_quiz');
77
        $category1 = self::getDataGenerator()->create_category();
78
        $category2 = self::getDataGenerator()->create_category();
79
        $course1 = self::getDataGenerator()->create_course(['category' => $category1->id]);
80
        $course2 = self::getDataGenerator()->create_course(['category' => $category1->id]);
81
        $course3 = self::getDataGenerator()->create_course(['category' => $category2->id]);
82
        $course4 = self::getDataGenerator()->create_course(['category' => $category2->id]);
83
 
84
        $sharedmod1 = $sharedmodgen->create_instance(['course' => $course1]);
85
        $sharedmod1context = \context_module::instance($sharedmod1->cmid);
86
        $sharedmod1qcat1 = question_get_default_category($sharedmod1context->id);
87
        $sharedmod1qcat2 = $qgen->create_question_category(['contextid' => $sharedmod1context->id]);
88
        $sharedmod1qcat2child = $qgen->create_question_category([
89
            'contextid' => $sharedmod1context->id,
90
            'parent' => $sharedmod1qcat2->id,
91
            'name' => 'A, B, C',
92
        ]);
93
        $privatemod1 = $privatemodgen->create_instance(['course' => $course1]);
94
        $privatemod1context = \context_module::instance($privatemod1->cmid);
95
        $privatemod1qcat1 = question_get_default_category($privatemod1context->id);
96
        role_assign($roles['editingteacher']->id, $user->id, \context_module::instance($sharedmod1->cmid));
97
        role_assign($roles['editingteacher']->id, $user->id, \context_module::instance($privatemod1->cmid));
98
 
99
        $sharedmod2 = $sharedmodgen->create_instance(['course' => $course2]);
100
        $sharedmod2context = \context_module::instance($sharedmod2->cmid);
101
        $sharedmod2qcat1 = question_get_default_category($sharedmod2context->id);
102
        $sharedmod2qcat2 = $qgen->create_question_category(['contextid' => $sharedmod2context->id]);
103
        $sharedmod2qcat2child = $qgen->create_question_category([
104
            'contextid' => $sharedmod2context->id,
105
            'parent' => $sharedmod2qcat2->id,
106
        ]);
107
        $privatemod2 = $privatemodgen->create_instance(['course' => $course2]);
108
        $privatemod2context = \context_module::instance($privatemod2->cmid);
109
        $privatemod1qcat1 = question_get_default_category($privatemod2context->id);
110
        role_assign($roles['editingteacher']->id, $user->id, \context_module::instance($sharedmod2->cmid));
111
        role_assign($roles['editingteacher']->id, $user->id, \context_module::instance($privatemod2->cmid));
112
 
113
        // User doesn't have the capability on this one.
114
        $sharedmod3 = $sharedmodgen->create_instance(['course' => $course3]);
115
        $privatemod3 = $privatemodgen->create_instance(['course' => $course3]);
116
 
117
        // Exclude this course in the results despite having the capability.
118
        $sharedmod4 = $sharedmodgen->create_instance(['course' => $course4]);
119
        role_assign($roles['editingteacher']->id, $user->id, \context_module::instance($sharedmod4->cmid));
120
 
121
        $sharedbanks = question_bank_helper::get_activity_instances_with_shareable_questions(
122
            [],
123
            [$course4->id],
124
            ['moodle/question:add'],
125
            true
126
        );
127
 
128
        $count = 0;
129
        foreach ($sharedbanks as $courseinstance) {
130
            // Must all be mod_qbanks.
131
            $this->assertEquals('qbank', $courseinstance->cminfo->modname);
132
            // Must have 2 categories each bank.
133
            $this->assertCount(3, $courseinstance->questioncategories);
134
            // Must not include the bank the user does not have access to.
135
            $this->assertNotEquals($sharedmod3->name, $courseinstance->name);
136
            $this->assertNotEquals($privatemod3->name, $courseinstance->name);
137
            $count++;
138
        }
139
        // Expect count of 2 bank instances.
140
        $this->assertEquals(2, $count);
141
 
142
        $privatebanks = question_bank_helper::get_activity_instances_with_private_questions(
143
            [$course1->id],
144
            [],
145
            ['moodle/question:add'],
146
            true
147
        );
148
 
149
        $count = 0;
150
        foreach ($privatebanks as $courseinstance) {
151
            // Must all be mod_quiz.
152
            $this->assertEquals('quiz', $courseinstance->cminfo->modname);
153
            // Must have 1 category in each bank.
154
            $this->assertCount(1, $courseinstance->questioncategories);
155
            // Must only include the bank from course 1.
156
            $this->assertNotContains($courseinstance->cminfo->course, [$course2->id, $course3->id, $course4->id]);
157
            $count++;
158
        }
159
        // Expect count of 1 bank instances.
160
        $this->assertEquals(1, $count);
161
    }
162
 
163
    /**
164
     * We should be able to filter sharable question bank instances by name.
165
     *
166
     * @covers ::get_activity_instances_with_shareable_questions
167
     * @return void
168
     */
169
    public function test_get_instances_by_name(): void {
170
        global $DB;
171
 
172
        $this->resetAfterTest();
173
        $user = self::getDataGenerator()->create_user();
174
        $roles = $DB->get_records('role', [], '', 'shortname, id');
175
        self::setUser($user);
176
 
177
        $sharedmodgen = self::getDataGenerator()->get_plugin_generator('mod_qbank');
178
        $category1 = self::getDataGenerator()->create_category();
179
        $course1 = self::getDataGenerator()->create_course(['category' => $category1->id]);
180
        role_assign($roles['editingteacher']->id, $user->id, \core\context\course::instance($course1->id));
181
 
182
        $sharedmods = [];
183
        for ($i = 1; $i <= 21; $i++) {
184
            $sharedmods[$i] = $sharedmodgen->create_instance(['course' => $course1, 'name' => "Shared bank {$i}"]);
185
        }
186
        $sharedmods[22] = $sharedmodgen->create_instance(['course' => $course1, 'name' => "Another bank"]);
187
 
188
        // We get all banks with no parameters.
189
        $allsharedbanks = question_bank_helper::get_activity_instances_with_shareable_questions();
190
        $this->assertCount(22, $allsharedbanks);
191
 
192
        // Searching for "2", we get the 4 banks with "2" in the name.
193
        $twobanks = question_bank_helper::get_activity_instances_with_shareable_questions(search: '2');
194
        $this->assertCount(4, $twobanks);
195
        $this->assertEquals(
196
            [$sharedmods[2]->cmid, $sharedmods[12]->cmid, $sharedmods[20]->cmid, $sharedmods[21]->cmid],
197
            array_map(fn($bank) => $bank->modid, $twobanks),
198
        );
199
 
200
        // Searching for "Shared bank" with no limit, we should get all 21, but not "Another bank".
201
        $sharedbanks = question_bank_helper::get_activity_instances_with_shareable_questions(search: 'Shared bank');
202
        $this->assertCount(21, $sharedbanks);
203
        $this->assertEmpty(array_filter($sharedbanks, fn($bank) => in_array($bank->name, ['Another bank'])));
204
 
205
        // Searching for "Shared bank" with a limit of 20, we should get all except number 21 and "Another bank".
206
        $limitedbanks = question_bank_helper::get_activity_instances_with_shareable_questions(search: 'Shared bank', limit: 20);
207
        $this->assertCount(20, $limitedbanks);
208
        $this->assertEmpty(array_filter($limitedbanks, fn($bank) => in_array($bank->name, ['Shared bank 21', 'Another bank'])));
209
    }
210
 
211
    /**
212
     * Assert creating a default mod_qbank instance on a course provides the expected boilerplate settings.
213
     *
214
     * @return void
215
     * @covers ::create_default_open_instance
216
     */
217
    public function test_create_default_open_instance(): void {
218
        global $DB;
219
 
220
        $this->resetAfterTest();
221
        self::setAdminUser();
222
 
223
        $course = self::getDataGenerator()->create_course();
224
 
225
        // Create the instance and assert default values.
226
        question_bank_helper::create_default_open_instance($course, $course->fullname);
227
        $modinfo = get_fast_modinfo($course);
228
        $cminfos = $modinfo->get_instances_of('qbank');
229
        $this->assertCount(1, $cminfos);
230
        $cminfo = reset($cminfos);
231
        $this->assertEquals($course->fullname, $cminfo->get_name());
232
        $this->assertEquals(0, $cminfo->sectionnum);
233
        $modrecord = $DB->get_record('qbank', ['id' => $cminfo->instance]);
234
        $this->assertEquals(question_bank_helper::TYPE_STANDARD, $modrecord->type);
235
        $this->assertEmpty($cminfo->idnumber);
236
        $this->assertEmpty($cminfo->content);
237
 
238
        // Create a system type bank.
239
        question_bank_helper::create_default_open_instance($course, 'System bank 1', question_bank_helper::TYPE_SYSTEM);
240
 
241
        // Try and create another system type bank.
242
        question_bank_helper::create_default_open_instance($course, 'System bank 2', question_bank_helper::TYPE_SYSTEM);
243
 
244
        $modinfo = get_fast_modinfo($course);
245
        $cminfos = $modinfo->get_instances_of('qbank');
246
        $cminfos = array_filter($cminfos, static function($cminfo) {
247
            global $DB;
248
            return $DB->record_exists('qbank', ['id' => $cminfo->instance, 'type' => question_bank_helper::TYPE_SYSTEM]);
249
        });
250
 
251
        // Can only be 1 system 'type' bank per course.
252
        $this->assertCount(1, $cminfos);
253
        $cminfo = reset($cminfos);
254
        $this->assertEquals('System bank 1', $cminfo->get_name());
255
        $moddata = $DB->get_record('qbank', ['id' => $cminfo->instance]);
256
        $this->assertEquals(get_string('systembankdescription', 'question'), $moddata->intro);
257
        $this->assertEquals(1, $cminfo->showdescription);
258
    }
259
 
260
    /**
261
     * Create a default instance, passing a name that is too long for the database.
262
     *
263
     * @return void
264
     * @throws \coding_exception
265
     * @throws \dml_exception
266
     * @throws \moodle_exception
267
     */
268
    public function test_create_default_open_instance_with_long_name(): void {
269
        $this->resetAfterTest();
270
        self::setAdminUser();
271
 
272
        $coursename = random_string(question_bank_helper::BANK_NAME_MAX_LENGTH);
273
        $course = self::getDataGenerator()->create_course(['shortname' => $coursename]);
274
 
275
        $this->expectExceptionMessage('The provided bankname is too long for the database field.');
276
        question_bank_helper::create_default_open_instance(
277
            $course,
278
            get_string('defaultbank', 'core_question', ['coursename' => $coursename]),
279
        );
280
    }
281
 
282
    /**
283
     * Create a default instance, passing a multibyte-character name.
284
     *
285
     * The name has more bytes than the max length, but is within the character limit as they are multibyte characters.
286
     */
287
    public function test_create_default_open_instance_with_multibyte_name(): void {
288
        $this->resetAfterTest();
289
        self::setAdminUser();
290
 
291
        $coursename = '';
292
        while (strlen($coursename) < question_bank_helper::BANK_NAME_MAX_LENGTH) {
293
            $coursename .= '🙂';
294
        }
295
        $course = self::getDataGenerator()->create_course(['shortname' => '🙂']);
296
        $bankname = get_string('defaultbank', 'core_question', ['coursename' => $coursename]);
297
        $this->assertTrue(strlen($bankname) > question_bank_helper::BANK_NAME_MAX_LENGTH);
298
        $this->assertTrue(\core_text::strlen($bankname) < question_bank_helper::BANK_NAME_MAX_LENGTH);
299
 
300
        question_bank_helper::create_default_open_instance($course, $bankname);
301
 
302
        $modinfo = get_fast_modinfo($course);
303
        $cminfos = $modinfo->get_instances_of('qbank');
304
        $this->assertCount(1, $cminfos);
305
        $cminfo = reset($cminfos);
306
        $this->assertEquals($bankname, $cminfo->get_name());
307
    }
308
 
309
    /**
310
     * Assert that viewing a question bank logs the view for that user up to a maximum of 5 unique bank views.
311
     *
312
     * @return void
313
     * @covers ::get_recently_used_open_banks
314
     * @covers ::add_bank_context_to_recently_viewed
315
     */
316
    public function test_recently_viewed_question_banks(): void {
317
        $this->resetAfterTest();
318
 
319
        $user = self::getDataGenerator()->create_user();
320
        $course1 = self::getDataGenerator()->create_course();
321
        $course2 = self::getDataGenerator()->create_course();
322
        self::getDataGenerator()->enrol_user($user->id, $course1->id, 'editingteacher');
323
        $banks = [];
324
        $banks[] = self::getDataGenerator()->create_module('qbank', ['course' => $course1->id]);
325
        $banks[] = self::getDataGenerator()->create_module('qbank', ['course' => $course1->id]);
326
        $banks[] = self::getDataGenerator()->create_module('qbank', ['course' => $course1->id]);
327
        $banks[] = self::getDataGenerator()->create_module('qbank', ['course' => $course2->id]);
328
        $banks[] = self::getDataGenerator()->create_module('qbank', ['course' => $course2->id]);
329
        $banks[] = self::getDataGenerator()->create_module('qbank', ['course' => $course2->id]);
330
 
331
        self::setUser($user);
332
 
333
        // Trigger bank view on each of them.
334
        foreach ($banks as $bank) {
335
            $cat = question_get_default_category(\context_module::instance($bank->cmid)->id, true);
336
            $context = \context::instance_by_id($cat->contextid);
337
            question_bank_helper::add_bank_context_to_recently_viewed($context);
338
        }
339
 
340
        $viewedorder = array_reverse($banks);
341
        // Check that the courseid filter works.
342
        $recentlyviewed = question_bank_helper::get_recently_used_open_banks($user->id, $course1->id);
343
        $this->assertCount(3, $recentlyviewed);
344
        // We should have the viewed banks in course 2.
345
        $courseviewed = array_slice($banks, 3, 3);
346
        $this->assertEqualsCanonicalizing(array_column($recentlyviewed, 'modid'), array_column($courseviewed, 'cmid'));
347
 
348
        // Check that the capability filter works.
349
        $recentlyviewed = question_bank_helper::get_recently_used_open_banks($user->id, havingcap: ['moodle/question:useall']);
350
        $this->assertCount(2, $recentlyviewed);
351
        // We should have the 2 most recently viewed banks in course 1.
352
        $capabilityviewed = array_slice($banks, 1, 2);
353
        $this->assertEqualsCanonicalizing(array_column($recentlyviewed, 'modid'), array_column($capabilityviewed, 'cmid'));
354
 
355
        $recentlyviewed = question_bank_helper::get_recently_used_open_banks($user->id);
356
 
357
        // We only keep a record of 5 maximum.
358
        $this->assertCount(5, $recentlyviewed);
359
        foreach ($recentlyviewed as $order => $record) {
360
            $this->assertEquals($viewedorder[$order]->cmid, $record->modid);
361
        }
362
 
363
        // Now if we view one of those again it should get bumped to the front of the list.
364
        $bank3cat = question_get_default_category(\context_module::instance($banks[2]->cmid)->id, true);
365
        $bank3context = \context::instance_by_id($bank3cat->contextid);
366
        question_bank_helper::add_bank_context_to_recently_viewed($bank3context);
367
 
368
        $recentlyviewed = question_bank_helper::get_recently_used_open_banks($user->id);
369
 
370
        // We should still have 5 maximum.
371
        $this->assertCount(5, $recentlyviewed);
372
        // The recently viewed on got bumped to the front.
373
        $this->assertEquals($banks[2]->cmid, $recentlyviewed[0]->modid);
374
        // The others got sorted accordingly behind it.
375
        $this->assertEquals($banks[5]->cmid, $recentlyviewed[1]->modid);
376
        $this->assertEquals($banks[4]->cmid, $recentlyviewed[2]->modid);
377
        $this->assertEquals($banks[3]->cmid, $recentlyviewed[3]->modid);
378
        $this->assertEquals($banks[1]->cmid, $recentlyviewed[4]->modid);
379
 
380
        // Now create a quiz and trigger the bank view of it.
381
        $quiz = self::getDataGenerator()->get_plugin_generator('mod_quiz')->create_instance(['course' => $course1]);
382
        $quizcat = question_get_default_category(\context_module::instance($quiz->cmid)->id, true);
383
        $quizcontext = \context::instance_by_id($quizcat->contextid);
384
        question_bank_helper::add_bank_context_to_recently_viewed($quizcontext);
385
 
386
        $recentlyviewed = question_bank_helper::get_recently_used_open_banks($user->id);
387
        // We should still have 5 maximum.
388
        $this->assertCount(5, $recentlyviewed);
389
 
390
        // Make sure that we only store bank views for plugins that support FEATURE_PUBLISHES_QUESTIONS.
391
        foreach ($recentlyviewed as $record) {
392
            $this->assertNotEquals($quiz->cmid, $record->modid);
393
        }
394
 
395
        // Now delete one of the viewed bank modules and get the records again.
396
        course_delete_module($banks[2]->cmid);
397
        $recentlyviewed = question_bank_helper::get_recently_used_open_banks($user->id);
398
        $this->assertCount(4, $recentlyviewed);
399
 
400
        // Check the order was retained.
401
        $this->assertEquals($banks[5]->cmid, $recentlyviewed[0]->modid);
402
        $this->assertEquals($banks[4]->cmid, $recentlyviewed[1]->modid);
403
        $this->assertEquals($banks[3]->cmid, $recentlyviewed[2]->modid);
404
        $this->assertEquals($banks[1]->cmid, $recentlyviewed[3]->modid);
405
    }
406
 
407
    /**
408
     * Assert that getting a default qbank instance on a course works with and without the "$createifnotexists" argument.
409
     *
410
     * @return void
411
     * @covers ::get_default_open_instance_system_type
412
     */
413
    public function test_get_default_open_instance_system_type(): void {
414
        global $DB;
415
 
416
        $this->resetAfterTest();
417
        self::setAdminUser();
418
 
419
        $course = self::getDataGenerator()->create_course();
420
        $modinfo = get_fast_modinfo($course);
421
        $qbanks = $modinfo->get_instances_of('qbank');
422
        $this->assertCount(0, $qbanks);
423
        $qbank = question_bank_helper::get_default_open_instance_system_type($course);
424
        $this->assertNull($qbank);
425
        $qbank = question_bank_helper::get_default_open_instance_system_type($course, true);
426
        $this->assertEquals(get_string('systembank', 'question'), $qbank->get_name());
427
        $modrecord = $DB->get_record('qbank', ['id' => $qbank->instance]);
428
        $this->assertEquals(question_bank_helper::TYPE_SYSTEM, $modrecord->type);
429
        // Create module other than a qbank with an ID that isn't used by a qbank yet.
430
        do {
431
            $wiki = self::getDataGenerator()->create_module('wiki', [
432
                'course' => $course->id,
433
            ]);
434
        } while ($DB->record_exists('qbank', ['id' => $wiki->id]));
435
        // Swap the qbank instance record for one with the same ID as the wiki instance.
436
        $newqbank = clone($modrecord);
437
        $newqbank->id = $wiki->id;
438
        $DB->insert_record_raw('qbank', $newqbank, customsequence: true);
439
        $DB->delete_records('qbank', ['id' => $qbank->id]);
440
        $DB->set_field('course_modules', 'instance', $newqbank->id, ['instance' => $qbank->instance]);
441
        // Retry the above again.
442
        \course_modinfo::purge_course_caches([$course->id]);
443
        $qbank = question_bank_helper::get_default_open_instance_system_type($course);
444
        $this->assertEquals(get_string('systembank', 'question'), $qbank->get_name());
445
        $modrecord = $DB->get_record('qbank', ['id' => $qbank->instance]);
446
        $this->assertEquals(question_bank_helper::TYPE_SYSTEM, $modrecord->type);
447
    }
448
 
449
    /**
450
     * Assert that get_bank_name_string returns suitably truncated strings.
451
     *
452
     * @dataProvider bank_name_strings
453
     * @param string $identifier
454
     * @param string $component
455
     * @param mixed $params
456
     * @param string $expected
457
     */
458
    public function test_get_bank_name_string(string $identifier, string $component, mixed $params, string $expected): void {
459
        $this->assertEquals($expected, question_bank_helper::get_bank_name_string($identifier, $component, $params));
460
    }
461
 
462
    /**
463
     * Get string examples with different parameter types and lengths.
464
     *
465
     * @return array[]
466
     */
467
    public static function bank_name_strings(): array {
468
        $longname = 'One two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen ' .
469
            'eighteen nineteen twenty twenty-one twenty-two twenty-three twenty-four twenty-five twenty-six twenty-seven ' .
470
            'twenty-eight twenty-nine thirty thirty-one';
471
        return [
472
            'String with no parameters' => [
473
                'systembank',
474
                'question',
475
                null,
476
                'System shared question bank',
477
            ],
478
            'String with short string parameter' => [
479
                'topfor',
480
                'question',
481
                'Test course',
482
                'Top for Test course',
483
            ],
484
            'String with long string parameter' => [
485
                'topfor',
486
                'question',
487
                $longname,
488
                'Top for One two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen ' .
489
                    'seventeen eighteen nineteen twenty twenty-one twenty-two twenty-three twenty-four twenty-five twenty-six ' .
490
                    'twenty-seven twenty-eight ...',
491
            ],
492
            'String with short array parameter' => [
493
                'defaultbank',
494
                'question',
495
                ['coursename' => 'Test course'],
496
                'Test course course question bank',
497
            ],
498
            'String with long array parameter' => [
499
                'defaultbank',
500
                'question',
501
                ['coursename' => $longname],
502
                'One two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen ' .
503
                    'eighteen nineteen twenty twenty-one twenty-two twenty-three twenty-four twenty-five twenty-six ' .
504
                    'twenty-seven twenty-eight ... course question bank',
505
            ],
506
            'String with multiple long array parameters' => [
507
                'markoutofmax',
508
                'question',
509
                ['mark' => $longname, 'max' => $longname],
510
                'Mark One two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen ' .
511
                    'eighteen ... out of One two three four five six seven eight nine ten eleven twelve thirteen fourteen ' .
512
                    'fifteen sixteen seventeen eighteen ...',
513
            ],
514
            'Long lang string' => [
515
                'howquestionsbehave_help',
516
                'question',
517
                null,
518
                'Students can interact with the questions in the quiz in various different ways. For example, you may wish the ' .
519
                    'students to enter an answer to each question and then submit the entire quiz, before anything is graded or ' .
520
                    'they get any feedback. That would ...',
521
            ],
522
        ];
523
    }
524
}