Skip to content

Commit f878b34

Browse files
committed
test: use testable_question_attempt instead of stubbing
1 parent ff22063 commit f878b34

File tree

1 file changed

+61
-57
lines changed

1 file changed

+61
-57
lines changed

tests/attempt_ui/question_ui_renderer_test.php

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@
1919
defined('MOODLE_INTERNAL') || die();
2020

2121
global $CFG;
22+
require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
2223
require_once($CFG->dirroot . '/question/type/questionpy/question.php');
2324

2425
use coding_exception;
2526
use PHPUnit\Framework\MockObject\Stub;
2627
use qtype_questionpy\api\api;
28+
use qtype_questionpy\constants;
2729
use qtype_questionpy_question;
2830
use question_attempt;
31+
use question_attempt_step;
32+
use testable_question_attempt;
2933

3034
/**
3135
* Unit tests for {@see question_ui_renderer}.
@@ -80,7 +84,7 @@ public function test_should_hide_inline_feedback(): void {
8084
<div xmlns="http://www.w3.org/1999/xhtml">
8185
<span>No feedback</span>
8286
</div>
83-
EXPECTED, $result);
87+
EXPECTED, $result->html);
8488
}
8589

8690
/**
@@ -104,7 +108,7 @@ public function test_should_show_inline_feedback(): void {
104108
<span>General feedback</span>
105109
<span>Specific feedback</span>
106110
</div>
107-
EXPECTED, $result);
111+
EXPECTED, $result->html);
108112
}
109113

110114
/**
@@ -122,27 +126,27 @@ public function test_should_mangle_names(): void {
122126
$result = $ui->render();
123127

124128
$this->assert_html_string_equals_html_string(<<<EXPECTED
125-
<div xmlns="http://www.w3.org/1999/xhtml" id="mangled:my_div">
126-
<datalist id="mangled:my_list">
129+
<div xmlns="http://www.w3.org/1999/xhtml" id="q1:1_my_div">
130+
<datalist id="q1:1_my_list">
127131
<option>42</option>
128132
</datalist>
129-
<label>Wrapping label <input class="form-control qpy-input" name="mangled:my_number"
130-
type="number" list="mangled:my_list"/></label>
131-
<label for="mangled:my_select">Separate label</label>
132-
<select class="form-control qpy-input" id="mangled:my_select" name="mangled:my_select">
133+
<label>Wrapping label <input class="form-control qpy-input" name="q1:1_my_number"
134+
type="number" list="q1:1_my_list"/></label>
135+
<label for="q1:1_my_select">Separate label</label>
136+
<select class="form-control qpy-input" id="q1:1_my_select" name="q1:1_my_select">
133137
<option value="1">One</option>
134138
<option value="2">Two</option>
135139
</select>
136-
<input class="qpy-input" type="radio" name="mangled:my_radio" value="1"/>
137-
<input class="qpy-input" type="radio" name="mangled:my_radio" value="2"/>
138-
<textarea class="form-control qpy-input" name="mangled:my_text"/>
139-
<button class="btn btn-primary qpy-input" name="mangled:my_button">Click me!</button>
140-
<map name="mangled:my_map">
140+
<input class="qpy-input" type="radio" name="q1:1_my_radio" value="1"/>
141+
<input class="qpy-input" type="radio" name="q1:1_my_radio" value="2"/>
142+
<textarea class="form-control qpy-input" name="q1:1_my_text"/>
143+
<button class="btn btn-primary qpy-input" name="q1:1_my_button">Click me!</button>
144+
<map name="q1:1_my_map">
141145
<area shape="circle" coords="1, 2, 3"/>
142146
</map>
143-
<img src="https://picsum.photos/200/300" usemap="#mangled:my_map"/>
147+
<img src="https://picsum.photos/200/300" usemap="#q1:1_my_map"/>
144148
</div>
145-
EXPECTED, $result);
149+
EXPECTED, $result->html);
146150
}
147151

148152
/**
@@ -179,7 +183,7 @@ public function test_should_shuffle_correctly_and_replace_indices(): void {
179183
</div>
180184
</div>
181185
</div>
182-
EXPECTED, $result);
186+
EXPECTED, $result->html);
183187
}
184188

185189
/**
@@ -195,7 +199,7 @@ public function test_should_shuffle_the_same_way_in_same_attempt(): void {
195199
$firstresult = (new question_ui_renderer($input, [], new \question_display_options(), $qa))->render();
196200
for ($i = 0; $i < 10; $i++) {
197201
$result = (new question_ui_renderer($input, [], new \question_display_options(), $qa))->render();
198-
$this->assertEquals($firstresult, $result);
202+
$this->assertEquals($firstresult->html, $result->html);
199203
}
200204
}
201205

@@ -225,7 +229,7 @@ public function test_should_resolve_placeholders(): void {
225229
<span>Plain parameter: Value of param &lt;b>one&lt;/b>.&lt;script>'Oh no, danger!'&lt;/script>
226230
</span>
227231
</div>
228-
EXPECTED, $result);
232+
EXPECTED, $result->html);
229233
}
230234

231235
/**
@@ -257,7 +261,7 @@ public function test_should_correctly_handle_broken_html_in_placeholder_expansio
257261
<span>Noclean parameter: <format-float>123</format-float><unknown-tag></unknown-tag><div>unclosed</div></span>
258262
<span>Plain parameter: &lt;qpy:format-float>123&lt;/qpy:format-float>&lt;unknown-tag>&lt;/unknown-tag>&lt;div>unclosed</span>
259263
</div>
260-
EXPECTED, $result);
264+
EXPECTED, $result->html);
261265
// phpcs:enable moodle.Files.LineLength.TooLong
262266
}
263267

@@ -283,7 +287,7 @@ public function test_should_remove_placeholders_when_no_corresponding_value(): v
283287
<span>Noclean parameter: </span>
284288
<span>Plain parameter: </span>
285289
</div>
286-
EXPECTED, $result);
290+
EXPECTED, $result->html);
287291
}
288292

289293
/**
@@ -312,7 +316,7 @@ public function test_should_soften_validations(): void {
312316
data-qpy_minlength="5" data-qpy_maxlength="10"
313317
aria-valuemin="17" data-qpy_min="17" aria-valuemax="42" data-qpy_max="42"/>
314318
</div>
315-
EXPECTED, $result);
319+
EXPECTED, $result->html);
316320
}
317321

318322
/**
@@ -338,7 +342,7 @@ public function test_should_defuse_buttons(): void {
338342
<input class="btn btn-primary qpy-input" type="button" value="Reset"/>
339343
<input class="btn btn-primary qpy-input" type="button" value="Button"/>
340344
</div>
341-
EXPECTED, $result);
345+
EXPECTED, $result->html);
342346
}
343347

344348
/**
@@ -363,7 +367,7 @@ public function test_should_remove_element_with_if_role_attribute(): void {
363367

364368
$this->assert_html_string_equals_html_string(<<<EXPECTED
365369
<div xmlns="http://www.w3.org/1999/xhtml"></div>
366-
EXPECTED, $result);
370+
EXPECTED, $result->html);
367371
}
368372

369373
/**
@@ -395,7 +399,7 @@ public function test_should_not_remove_element_with_if_role_attribute(): void {
395399
<div>You're a proctor!</div>
396400
<div>You're any of the above!</div>
397401
</div>
398-
EXPECTED, $result);
402+
EXPECTED, $result->html);
399403
}
400404

401405
/**
@@ -421,7 +425,7 @@ public function test_should_format_floats_in_en(): void {
421425
Pad with zeros: 1.10000
422426
Strip zeros: 1.1
423427
</div>
424-
EXPECTED, $result);
428+
EXPECTED, $result->html);
425429
}
426430

427431
/**
@@ -444,7 +448,7 @@ public function test_should_replace_qpy_urls(): void {
444448
static link: <a href="https://www.example.com/moodle/pluginfile.php//qtype_questionpy/static/deadbeef/local/minimal_example/path1/path2/filename.txt">https://www.example.com/moodle/pluginfile.php//qtype_questionpy/static/deadbeef/local/minimal_example/path1/path2/filename.txt</a>
445449
minimal path: <a href="https://www.example.com/moodle/pluginfile.php//qtype_questionpy/static/deadbeef/local/minimal_example/f">https://www.example.com/moodle/pluginfile.php//qtype_questionpy/static/deadbeef/local/minimal_example/f</a>
446450
</div>
447-
EXPECTED, $result);
451+
EXPECTED, $result->html);
448452
// phpcs:enable moodle.Files.LineLength.MaxExceeded
449453
}
450454

@@ -457,44 +461,41 @@ public function test_should_replace_qpy_urls(): void {
457461
*/
458462
public function test_should_correctly_fill_data(): void {
459463
$input = file_get_contents(__DIR__ . '/question_uis/input-values.xhtml');
460-
$qa = $this->create_question_attempt_stub('deadbeef');
461-
$newvalues = [
464+
$qa = $this->create_question_attempt_stub('deadbeef', lastresponse: [
462465
'my_text' => 'new',
463466
'my_checkbox_value' => 'value',
464467
'my_checkbox_on' => 'on',
465468
'my_radio' => 'value1',
466469
'my_select' => 'value3',
467470
'my_hidden' => 'new',
468471
'my_button' => 'should be ignored',
469-
];
470-
$qa->method('get_last_qt_var')
471-
->willReturnCallback(fn($name) => $newvalues[$name]);
472+
]);
472473

473474
$ui = new question_ui_renderer($input, [], new \question_display_options(), $qa);
474475
$result = $ui->render();
475476

476477
$this->assert_html_string_equals_html_string(<<<EXPECTED
477-
<div xmlns="http://www.w3.org/1999/xhtml" id="mangled:my_div">
478-
<input class="form-control qpy-input" type="text" name="mangled:my_text" value="new"/>
478+
<div xmlns="http://www.w3.org/1999/xhtml" id="q1:1_my_div">
479+
<input class="form-control qpy-input" type="text" name="q1:1_my_text" value="new"/>
479480
480-
<input class="qpy-input" type="checkbox" name="mangled:my_checkbox_value" value="value" checked="checked"/>
481-
<input class="qpy-input" type="checkbox" name="mangled:my_checkbox_on" checked="checked"/>
481+
<input class="qpy-input" type="checkbox" name="q1:1_my_checkbox_value" value="value" checked="checked"/>
482+
<input class="qpy-input" type="checkbox" name="q1:1_my_checkbox_on" checked="checked"/>
482483
483-
<input class="qpy-input" type="radio" name="mangled:my_radio" value="value1" checked="checked"/>
484-
<input class="qpy-input" type="radio" name="mangled:my_radio" value="value2"/>
484+
<input class="qpy-input" type="radio" name="q1:1_my_radio" value="value1" checked="checked"/>
485+
<input class="qpy-input" type="radio" name="q1:1_my_radio" value="value2"/>
485486
486-
<select class="form-control qpy-input" name="mangled:my_select">
487+
<select class="form-control qpy-input" name="q1:1_my_select">
487488
<option value="value1"/>
488489
<option value="value2"/>
489490
<option value="value3" selected="selected"/>
490491
</select>
491492
492-
<input class="form-control qpy-input" type="hidden" name="mangled:my_hidden" value="new"/>
493+
<input class="form-control qpy-input" type="hidden" name="q1:1_my_hidden" value="new"/>
493494
494-
<input class="btn btn-primary qpy-input" name="mangled:my_button" type="button" value="value1"/>
495-
<input class="btn btn-primary qpy-input" name="mangled:my_button" type="button" value="value2"/>
495+
<input class="btn btn-primary qpy-input" name="q1:1_my_button" type="button" value="value1"/>
496+
<input class="btn btn-primary qpy-input" name="q1:1_my_button" type="button" value="value2"/>
496497
</div>
497-
EXPECTED, $result);
498+
EXPECTED, $result->html);
498499
}
499500

500501
/**
@@ -506,46 +507,49 @@ public function test_should_correctly_fill_data(): void {
506507
*/
507508
public function test_should_add_fallback_option_to_select_when_value_isnt_present(): void {
508509
$input = file_get_contents(__DIR__ . '/question_uis/select.xhtml');
509-
$qa = $this->create_question_attempt_stub('deadbeef');
510-
$qa->method('get_last_qt_var')
511-
->willReturn('something');
510+
$qa = $this->create_question_attempt_stub('deadbeef', lastresponse: [
511+
'my_select' => 'something',
512+
]);
512513

513514
$ui = new question_ui_renderer($input, [], new \question_display_options(), $qa);
514515
$result = $ui->render();
515516

516517
$this->assert_html_string_equals_html_string(<<<EXPECTED
517518
<div xmlns="http://www.w3.org/1999/xhtml" >
518-
<select class="form-control qpy-input" name="mangled:my_select">
519+
<select class="form-control qpy-input" name="q1:1_my_select">
519520
<option value="value1"/>
520521
<option value="value2"/>
521522
<option value="value3"/>
522523
<option value="something" selected="selected">(the selected option is no longer available)</option>
523524
</select>
524525
</div>
525-
EXPECTED, $result);
526+
EXPECTED, $result->html);
526527
}
527528

528529
/**
529530
* Creates a stub question attempt which should fulfill the needs of most tests.
530531
*
531532
* @param string|null $packagehash explicit package hash. Random if unset.
532533
* @param int|null $id explicit attempt database id. Random if unset.
534+
* @param array $lastresponse last response submitted in the attempt
533535
* @return question_attempt&Stub
536+
* @throws coding_exception
534537
*/
535-
private function create_question_attempt_stub(?string $packagehash = null, ?int $id = null): question_attempt {
538+
private function create_question_attempt_stub(?string $packagehash = null, ?int $id = null,
539+
array $lastresponse = []): question_attempt {
536540
$packagehash ??= hash('sha256', random_string(64));
537541
$id ??= mt_rand();
538542
$question = new qtype_questionpy_question($packagehash, '{}', null, $this->createStub(api::class));
539543

540-
$qa = $this->createStub(question_attempt::class);
541-
$qa->method('get_database_id')
542-
->willReturn($id);
543-
$qa->method('get_question')
544-
->willReturn($question);
545-
$qa->method('get_qt_field_name')
546-
->willReturnCallback(function ($name) {
547-
return "mangled:$name";
548-
});
544+
$step = new question_attempt_step(array_merge($lastresponse, [
545+
constants::QT_VAR_RESPONSE_MARKER => '',
546+
]));
547+
548+
$qa = new testable_question_attempt($question, 1);
549+
$qa->set_database_id($id);
550+
$qa->set_slot(1);
551+
$qa->add_step($step);
552+
549553
return $qa;
550554
}
551555
}

0 commit comments

Comments
 (0)