-
Regex on code where the DOM already answers the question. Six steps assert an opening tag against the raw source string:
assert.match(code, /
/i);
In every one of these steps a later hint in the same file already queries the element with document.querySelector, so the regex check adds nothing the DOM cannot express. Affected: 66a83601cd819e37f0dccd14 (Step 1, the header, h1 and p opening tags), 66a8380d911e3f4270d5cadc (Step 2, main), 66a83bdcf425e7446900b7c4 (Step 3, form), 66a83e5e491625454b6f62c3 (Step 4, fieldset), 66a83fec026a7a4631e084d2 (Step 5, legend), 66a84111965a0c46df6bbd0a (Step 6, label).
The matching closing-tag regexes in those same files are a separate case and should stay. The parser implies the end tag, so the element still appears in the DOM whether or not the learner closed it, and no DOM query distinguishes the two.
-
Unguarded property access after an optional chain. In 66a83601cd819e37f0dccd14 (Step 1):
assert.strictEqual(pElement?.previousElementSibling.tagName, 'H1');
The optional chain covers a missing paragraph, but a paragraph that exists as the first child gives a null previousElementSibling and the access throws a TypeError instead of failing with the hint text.
-
Tautological assertion. In 66a93bbe65a26169dbf3bc39 (Step 10):
assert.strictEqual(document.querySelector('fieldset label[for="email"]')?.getAttribute('for'), 'email');
The selector already filters on for="email", so the comparison can only ever be 'email' against 'email' or undefined. On failure the learner is shown undefined rather than the attribute value they wrote.
-
Boolean attribute check accepts only one of the two valid spellings. In 66a93c95bc58e26a8fe95818 (Step 11):
assert.strictEqual(document.querySelector('input#email')?.getAttribute('required'), "");
For a boolean attribute the spec allows either the empty string or the attribute's own name as the value, so required, required="" and required="required" all mean the same thing. getAttribute returns the literal string, so the last form fails. The step description only tells the learner to add the attribute, and 66a937e74920ba68ebe5e86d (Step 9) checks the same attribute with an attribute selector that accepts any valid spelling.
-
Test variables named for the wrong element. In 67a51d3a8a6fe123b77b0c6e (Step 12):
const label1 = document.querySelector('label:nth-of-type(1) + input');
label1 and label2 both hold input elements, so the two hints read as though they check the labels.
-
Stray blank line inside a test block. Two test blocks open with an empty line before the assertion:
assert.strictEqual(document.querySelector('option[value="good"]')?.textContent.trim(), 'Good');
Affected: 66a972137acd1179fa3fe8a0 (Step 26) and 66a97ca8c4cbae7d0bb6e0ad (Step 29). Every other test block in both files opens directly with the assertion.
Describe the Issue
The test code in the
workshop-hotel-feedback-formhints has several problems that affect what the tests actually accept and reject.Regex on
codewhere the DOM already answers the question. Six steps assert an opening tag against the raw source string:In every one of these steps a later hint in the same file already queries the element with
document.querySelector, so the regex check adds nothing the DOM cannot express. Affected:66a83601cd819e37f0dccd14(Step 1, theheader,h1andpopening tags),66a8380d911e3f4270d5cadc(Step 2,main),66a83bdcf425e7446900b7c4(Step 3,form),66a83e5e491625454b6f62c3(Step 4,fieldset),66a83fec026a7a4631e084d2(Step 5,legend),66a84111965a0c46df6bbd0a(Step 6,label).The matching closing-tag regexes in those same files are a separate case and should stay. The parser implies the end tag, so the element still appears in the DOM whether or not the learner closed it, and no DOM query distinguishes the two.
Unguarded property access after an optional chain. In
66a83601cd819e37f0dccd14(Step 1):The optional chain covers a missing paragraph, but a paragraph that exists as the first child gives a null
previousElementSiblingand the access throws aTypeErrorinstead of failing with the hint text.Tautological assertion. In
66a93bbe65a26169dbf3bc39(Step 10):The selector already filters on
for="email", so the comparison can only ever be'email'against'email'orundefined. On failure the learner is shownundefinedrather than the attribute value they wrote.Boolean attribute check accepts only one of the two valid spellings. In
66a93c95bc58e26a8fe95818(Step 11):For a boolean attribute the spec allows either the empty string or the attribute's own name as the value, so
required,required=""andrequired="required"all mean the same thing.getAttributereturns the literal string, so the last form fails. The step description only tells the learner to add the attribute, and66a937e74920ba68ebe5e86d(Step 9) checks the same attribute with an attribute selector that accepts any valid spelling.Test variables named for the wrong element. In
67a51d3a8a6fe123b77b0c6e(Step 12):label1andlabel2both holdinputelements, so the two hints read as though they check the labels.Stray blank line inside a test block. Two test blocks open with an empty line before the assertion:
Affected:
66a972137acd1179fa3fe8a0(Step 26) and66a97ca8c4cbae7d0bb6e0ad(Step 29). Every other test block in both files opens directly with the assertion.Affected Pages
Expected behavior
The presence of an element is tested through the DOM, so the opening-tag checks in Steps 1 through 6 behave the same way the rest of each hints block does. The closing-tag checks stay as regex, since nothing in the DOM reflects a missing end tag.
The Step 1 sibling check fails with its hint message when the paragraph is in the wrong place, rather than throwing a
TypeError.The Step 10
forattribute hint reports whether the label exists with that attribute, and its failure output reflects what the learner wrote.The Step 11
requiredhint passes for every spelling the HTML spec permits, matching how66a937e74920ba68ebe5e86d(Step 9) checks the same attribute.The two Step 12 test variables are named for the
inputelements they hold.Every test block begins with its assertion.