Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions src/dayamlchecker/accessibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
"field",
"__line__",
}
FIELD_VISIBILITY_KEYS = (
"show if",
"hide if",
"js show if",
"js hide if",
)
GENERIC_LINK_TEXT = {
"click here",
"here",
Expand Down Expand Up @@ -522,7 +528,7 @@ def _check_choice_labels(
def _check_duplicate_field_labels(
doc: dict[str, Any], document_start_line: int
) -> list[FindingDraft]:
labels: dict[str, list[tuple[int, str]]] = {}
labels: dict[str, list[tuple[int, str, bool]]] = {}
for field in _iter_fields(doc):
if not _field_collects_user_input(field):
continue
Expand All @@ -534,18 +540,20 @@ def _check_duplicate_field_labels(
(
_field_line_number(doc, field, document_start_line),
label,
_field_has_visibility_logic(field),
)
)

findings: list[FindingDraft] = []
for entries in labels.values():
if len(entries) < 2:
always_visible_entries = [entry for entry in entries if not entry[2]]
if len(always_visible_entries) < 2:
continue
findings.append(
draft(
MessageId.ACCESSIBILITY_DUPLICATE_FIELD_LABEL,
line_number=entries[0][0],
labels=", ".join(label for _, label in entries[:3]),
line_number=always_visible_entries[0][0],
labels=", ".join(label for _, label, _ in always_visible_entries[:3]),
)
)
return findings
Expand Down Expand Up @@ -1280,6 +1288,23 @@ def _field_collects_user_input(field: dict[str, Any]) -> bool:
return any(str(key).strip() not in FIELD_NON_LABEL_KEYS for key in field.keys())


def _field_has_visibility_logic(field: dict[str, Any]) -> bool:
return any(
_has_nonempty_visibility_condition(field.get(key))
for key in FIELD_VISIBILITY_KEYS
)


def _has_nonempty_visibility_condition(value: Any) -> bool:
if value is None:
return False
if isinstance(value, str):
return bool(value.strip())
if isinstance(value, (dict, list, tuple, set)):
return bool(value)
return True


def _iter_choice_labels_with_lines(
choice_value: Any,
) -> list[tuple[str, Optional[int]]]:
Expand Down
66 changes: 66 additions & 0 deletions tests/test_yaml_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,72 @@ def test_accessibility_no_label_uses_variable_from_no_label_key(self):
f"Expected no-label accessibility error to include variable name, got: {errs}",
)

def test_accessibility_duplicate_field_label_fails_for_always_visible_fields(self):
yaml_content = """question: |
Enter contact information
fields:
- Name: first_name
- Name: second_name
"""
errs = find_errors_from_string(
yaml_content,
input_file="<string_invalid>",
lint_mode="accessibility",
)
self.assertTrue(
any(e.code == "WA515" for e in errs),
f"Expected duplicate field label warning, got: {errs}",
)

def test_accessibility_duplicate_field_label_suppressed_for_conditional_other_context(
self,
):
yaml_content = """question: |
What else should we know?
fields:
- Help types: help_types
datatype: checkboxes
choices:
- Housing
- Other
- Other: help_other
show if: help_types["Other"]
- Document types: document_types
datatype: checkboxes
choices:
- ID
- Other
- Other: document_other
show if: document_types["Other"]
"""
errs = find_errors_from_string(
yaml_content,
input_file="<string_valid>",
lint_mode="accessibility",
)
self.assertFalse(
any(e.code == "WA515" for e in errs),
f"Did not expect duplicate field label warning for contextual Other fields, got: {errs}",
)

def test_accessibility_duplicate_field_label_suppressed_for_hidden_field(self):
yaml_content = """question: |
Enter mailing information
fields:
- Address: mailing_address
- Address: physical_address
hide if: use_mailing_address
"""
errs = find_errors_from_string(
yaml_content,
input_file="<string_valid>",
lint_mode="accessibility",
)
self.assertFalse(
any(e.code == "WA515" for e in errs),
f"Did not expect duplicate field label warning for hidden duplicate, got: {errs}",
)

def test_accessibility_tagged_pdf_info_for_docx_without_setting(self):
yaml_content = """attachments:
- name: Letter
Expand Down
Loading