Settings > Appearance: the career order checkbox points aria-describedby at a help text with no id #207

Closed
opened 2026-09-15 15:14:30 +00:00 by tiagoagueda · 0 comments
Owner

CI's browser suite fails on main:

FAILED tests/e2e/test_described_by.py::test_no_page_references_an_element_that_is_not_there[chromium]
  /settings/
    id_show_career_order_helptext referenced by <input type="checkbox" name="show_career_order" aria-describedby="id_show_career_order_helptext" id="id_show_c...
1 failed, 95 passed, 5946 deselected in 310.80s

What is wrong

Django renders the Show the order number on each career entry checkbox with aria-describedby="id_show_career_order_helptext", because the field has help text. Nothing on the page has that id, so a screen reader is told the checkbox is described by an element that does not exist, and the sentence explaining the preference cannot be reached from the checkbox. This is the same dangling reference #114 removed from every other form.

Why

src/postulo/templates/settings/appearance.html, in the Your career card added by #203 (0e76bab12):

<label class="flex items-start gap-3 ...">
  {{ form.show_career_order }}
  <span>
    <span class="block">{{ form.show_career_order.label }}</span>
    <span class="block text-ink-500 dark:text-ink-400">{{ form.show_career_order.help_text }}</span>
  </span>
</label>
{% include "partials/field_feedback.html" with field=form.show_career_order errors_only=True %}

The template draws the help text itself, inside the label, so it passes errors_only=True to stop partials/field_feedback.html drawing it a second time. That is the right call, but errors_only is for a caller that "has already drawn the help itself ... and has put the id on it" (the partial's own comment). This caller drew it without the id. The Navigation fieldset a few lines above in the same template does it correctly: id="{{ form.navigation.auto_id }}_helptext".

Fix

Put id="{{ form.show_career_order.auto_id }}_helptext" on the help-text span. The help stays inside the <label>, so it will also be part of the checkbox's accessible name. If a name and a description that repeat each other read badly, move the span out of the label and keep the id on it.

tests/e2e/test_described_by.py already covers this and should pass again once the fix lands. No new test is needed. Ideally a unit-level check would also catch it, so a template like this fails the fast suite and not only the five-minute browser walk.

CI's browser suite fails on `main`: ``` FAILED tests/e2e/test_described_by.py::test_no_page_references_an_element_that_is_not_there[chromium] /settings/ id_show_career_order_helptext referenced by <input type="checkbox" name="show_career_order" aria-describedby="id_show_career_order_helptext" id="id_show_c... 1 failed, 95 passed, 5946 deselected in 310.80s ``` ## What is wrong Django renders the *Show the order number on each career entry* checkbox with `aria-describedby="id_show_career_order_helptext"`, because the field has help text. Nothing on the page has that id, so a screen reader is told the checkbox is described by an element that does not exist, and the sentence explaining the preference cannot be reached from the checkbox. This is the same dangling reference #114 removed from every other form. ## Why `src/postulo/templates/settings/appearance.html`, in the *Your career* card added by #203 (`0e76bab12`): ```django <label class="flex items-start gap-3 ..."> {{ form.show_career_order }} <span> <span class="block">{{ form.show_career_order.label }}</span> <span class="block text-ink-500 dark:text-ink-400">{{ form.show_career_order.help_text }}</span> </span> </label> {% include "partials/field_feedback.html" with field=form.show_career_order errors_only=True %} ``` The template draws the help text itself, inside the label, so it passes `errors_only=True` to stop `partials/field_feedback.html` drawing it a second time. That is the right call, but `errors_only` is for a caller that "has already drawn the help itself ... and has put the id on it" (the partial's own comment). This caller drew it without the id. The *Navigation* fieldset a few lines above in the same template does it correctly: `id="{{ form.navigation.auto_id }}_helptext"`. ## Fix Put `id="{{ form.show_career_order.auto_id }}_helptext"` on the help-text span. The help stays inside the `<label>`, so it will also be part of the checkbox's accessible name. If a name and a description that repeat each other read badly, move the span out of the label and keep the id on it. `tests/e2e/test_described_by.py` already covers this and should pass again once the fix lands. No new test is needed. Ideally a unit-level check would also catch it, so a template like this fails the fast suite and not only the five-minute browser walk.
tiagoagueda added this to the 0.3.0 milestone 2026-09-15 15:14:30 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#207
No description provided.