Skip to content

feat(html_analyze): implement noStaticElementInteractions#10069

Merged
Netail merged 6 commits into
biomejs:nextfrom
Netail:feat/port-no-static-element-interactions
Apr 25, 2026
Merged

feat(html_analyze): implement noStaticElementInteractions#10069
Netail merged 6 commits into
biomejs:nextfrom
Netail:feat/port-no-static-element-interactions

Conversation

@Netail

@Netail Netail commented Apr 20, 2026

Copy link
Copy Markdown
Member

Summary

Port noStaticElementInteractions to HTML

Closes #8155

Test Plan

unit tests

Docs

@changeset-bot

changeset-bot Bot commented Apr 20, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6a7427d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@biomejs/biome Minor
@biomejs/cli-win32-x64 Minor
@biomejs/cli-win32-arm64 Minor
@biomejs/cli-darwin-x64 Minor
@biomejs/cli-darwin-arm64 Minor
@biomejs/cli-linux-x64 Minor
@biomejs/cli-linux-arm64 Minor
@biomejs/cli-linux-x64-musl Minor
@biomejs/cli-linux-arm64-musl Minor
@biomejs/wasm-web Minor
@biomejs/wasm-bundler Minor
@biomejs/wasm-nodejs Minor
@biomejs/backend-jsonrpc Patch
@biomejs/js-api Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added A-Linter Area: linter L-HTML Language: HTML and super languages labels Apr 20, 2026
@Netail Netail force-pushed the feat/port-no-static-element-interactions branch from f32df0c to fff0434 Compare April 20, 2026 19:16
@codspeed-hq

codspeed-hq Bot commented Apr 20, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 69.55%

⚡ 3 improved benchmarks
❌ 7 regressed benchmarks
✅ 239 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
css_analyzer[foundation_11602414662825430680.css] 238.4 ms 276.4 ms -13.72%
css_analyzer[pure_9395922602181450299.css] 23.6 ms 26.9 ms -12.15%
css_analyzer[tachyons_11778168428173736564.css] 178.7 ms 198.1 ms -9.77%
html_analyzer[index_1033418810622582172.html] 469.2 µs 1,179.1 µs -60.21%
html_analyzer[real/wikipedia-fr-Guerre_de_Canudos.html] 450.6 ms 1,270.9 ms -64.55%
html_analyzer[real/wikipedia-Unix.html] 166.2 ms 514.4 ms -67.69%
html_analyzer[real/wikipedia-JavaScript.html] 189.3 ms 621.6 ms -69.55%
execute_optimized[code_snippet] 453.3 µs 416.1 µs +8.94%
execute_optimized[or_pattern] 585.7 µs 543.7 µs +7.73%
execute_optimized[where_clause] 454 µs 412 µs +10.19%

Comparing Netail:feat/port-no-static-element-interactions (6a7427d) with next (aaf4af0)

Open in CodSpeed

@Netail Netail marked this pull request as ready for review April 20, 2026 19:32
@Netail Netail mentioned this pull request Apr 20, 2026
32 tasks
@coderabbitai

coderabbitai Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a new HTML accessibility lint rule noStaticElementInteractions and a changeset entry. Introduces a shared event-handler matcher in crates/biome_aria (event_handlers::matches_event_handler) and per-language has_event_handler helpers for HTML/JSX. Refactors existing non‑interactive/static interaction rules to use the shared matcher, narrows checked handler categories, updates diagnostic messages, and adds comprehensive valid/invalid test fixtures for HTML, Astro, Svelte and Vue.

Possibly related PRs

Suggested labels

A-Parser

Suggested reviewers

  • dyc3
  • ematipico
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: implementing the noStaticElementInteractions rule for HTML analysis.
Description check ✅ Passed The description clearly relates to the changeset, explaining the port of noStaticElementInteractions to HTML and referencing issue #8155.
Linked Issues check ✅ Passed The PR fully implements the noStaticElementInteractions rule port to HTML as required by issue #8155, including test fixtures for multiple file types (.html, .astro, .vue, .svelte) and a minor changeset.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing noStaticElementInteractions. Minor refactoring of event handler detection in related rules (#8155 objective) and new shared utilities are in-scope supporting infrastructure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_html_analyze/src/lint/a11y/no_static_element_interactions.rs`:
- Around line 104-128: The INTERACTIVE_HANDLERS constant is missing "onmouseup",
causing static-element interaction checks (and Vue directive resolution for
`@mouseup` / v-on:mouseup) to miss those cases; update the INTERACTIVE_HANDLERS
array to include "onmouseup" alongside "onmousedown" so the lint in
no_static_element_interactions (which relies on INTERACTIVE_HANDLERS) correctly
flags mouseup handlers in HTML and Vue fixtures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fec3251b-9d2a-4c67-8549-32f5d74afae0

📥 Commits

Reviewing files that changed from the base of the PR and between 69aadc2 and fff0434.

⛔ Files ignored due to path filters (8)
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/astro/invalid.astro.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/astro/valid.astro.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/svelte/invalid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/svelte/valid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/valid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/vue/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/vue/valid.vue.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (10)
  • .changeset/common-toes-trade.md
  • crates/biome_html_analyze/src/lint/a11y/no_static_element_interactions.rs
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/astro/invalid.astro
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/astro/valid.astro
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/invalid.html
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/svelte/invalid.svelte
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/svelte/valid.svelte
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/valid.html
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/vue/invalid.vue
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/vue/valid.vue

Comment thread crates/biome_html_analyze/src/lint/a11y/no_static_element_interactions.rs Outdated

@dyc3 dyc3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets try to reduce the perf regressions if possible.

Comment on lines +88 to +102
fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> {
let node = ctx.query();
Some(RuleDiagnostic::new(
rule_category!(),
node.range(),
markup! {
"Static Elements should not be interactive."
},
).note(
markup! {
"To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value."
}
))
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Static Elements should not be interactive." doesn't really illustrate why. remember the rule pillars. A good rule of thumb is if you don't have 3 markup! notes, then you are missing something.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied it over from the JS rule, included the improvement in this PR. Both rules I touched in this PR

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other rules are old, and rule pillars weren't a thing. There's a good opportunity to improve things

"onkeyup",
"onfocus",
"onblur",
];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a unit test to ensure this is sorted, then use binary search. to do lookups in this list. That's likely the cause of the perf regression.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added and abstracted the event handlers bit to the aria crate (which I first planned in a later PR)

Comment on lines +131 to +140
fn has_handler_props(element: &AnyHtmlTagElement) -> bool {
INTERACTIVE_HANDLERS.iter().any(|handler| {
element.find_attribute_by_name(handler).is_some()
|| handler.strip_prefix("on").is_some_and(|handler_name| {
element
.find_vue_event_handling_directive(handler_name)
.is_some()
})
})
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iterate on the attributes in the outer loop, do lookups in the list on the inside.

@github-actions github-actions Bot added A-Parser Area: parser L-JavaScript Language: JavaScript and super languages labels Apr 22, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`:
- Around line 129-130: The EVENT_HANDLER_TYPES constant currently includes
"image", which causes the rule in no_noninteractive_element_interactions
(constant EVENT_HANDLER_TYPES) to treat passive image handlers like
onload/onerror as interaction events and trigger false positives; remove "image"
from the slice so the array only contains "focus", "keyboard", and "mouse"
(i.e., update EVENT_HANDLER_TYPES to &["focus", "keyboard", "mouse"]) and
run/update any tests or references that assume the former set.

In
`@crates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs`:
- Around line 135-136: The EVENT_HANDLER_TYPES constant currently includes
"image", which causes lifecycle handlers like onLoad/onError to be treated as
interactive; update the constant in no_noninteractive_element_interactions.rs to
remove the "image" entry so it only contains "focus", "keyboard", and "mouse"
(i.e., change EVENT_HANDLER_TYPES to &[&str] = &["focus", "keyboard", "mouse"])
to align the rule with its mouse/key handler intent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 28437db2-38fe-4193-a60d-55356e694d37

📥 Commits

Reviewing files that changed from the base of the PR and between fff0434 and 59eedd0.

⛔ Files ignored due to path filters (11)
  • Cargo.lock is excluded by !**/*.lock and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/astro/invalid.astro.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/svelte/invalid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/vue/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/astro/invalid.astro.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/invalid.html.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/svelte/invalid.svelte.snap is excluded by !**/*.snap and included by **
  • crates/biome_html_analyze/tests/specs/a11y/noStaticElementInteractions/vue/invalid.vue.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/a11y/noNoninteractiveElementInteractions/invalid.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/a11y/noStaticElementInteractions/invalid.jsx.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (10)
  • crates/biome_aria/Cargo.toml
  • crates/biome_aria/src/event_handlers.rs
  • crates/biome_aria/src/lib.rs
  • crates/biome_html_analyze/src/a11y.rs
  • crates/biome_html_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
  • crates/biome_html_analyze/src/lint/a11y/no_static_element_interactions.rs
  • crates/biome_html_syntax/src/element_ext.rs
  • crates/biome_js_analyze/src/a11y.rs
  • crates/biome_js_analyze/src/lint/a11y/no_noninteractive_element_interactions.rs
  • crates/biome_js_analyze/src/lint/a11y/no_static_element_interactions.rs
💤 Files with no reviewable changes (1)
  • crates/biome_html_syntax/src/element_ext.rs
✅ Files skipped from review due to trivial changes (2)
  • crates/biome_aria/Cargo.toml
  • crates/biome_aria/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_html_analyze/src/lint/a11y/no_static_element_interactions.rs

@ematipico

Copy link
Copy Markdown
Member

Lets try to reduce the perf regressions if possible.

Perf regression are false positives. I doubt this PR has anything to do with CSS

@Netail Netail requested a review from dyc3 April 22, 2026 07:48
@github-actions github-actions Bot removed the A-Parser Area: parser label Apr 22, 2026
}

// Only check the focus, keyboard and mouse event handler types.
const EVENT_HANDLER_TYPES: &[&str] = &["focus", "keyboard", "mouse"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its not worth a binary search if there's so few elements. binary_search only starts to help performance at ~20 items, give or take

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't do a binary search on these, only on the keys & within the values array of the EVENT_HANDLERS

Comment thread crates/biome_html_analyze/src/a11y.rs Outdated
.is_some_and(|t| {
matches_event_handler(
handler_types,
format!("on{}", t.text_trimmed()).as_str(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format! results in string allocations.

Comment thread crates/biome_html_analyze/src/a11y.rs Outdated
.is_some_and(|t| {
matches_event_handler(
handler_types,
format!("on{}", t.text_trimmed()).as_str(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.

Comment thread crates/biome_aria/src/event_handlers.rs Outdated
Comment on lines +3 to +18
// https://github.com/jsx-eslint/jsx-ast-utils/blob/v3.3.5/src/eventHandlers.js
const EVENT_HANDLERS: &[(&str, &[&str])] = &[
(
"animation",
&["onanimationend", "onanimationiteration", "onanimationstart"],
),
("clipboard", &["oncopy", "oncut", "onpaste"]),
(
"composition",
&[
"oncompositionend",
"oncompositionstart",
"oncompositionupdate",
],
),
("focus", &["onblur", "onfocus"]),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On one hand, I can see why you did this refactor. But I don't think its going to perform very well. Now, instead of doing one lookup into a list, you are doing 2 (look up the key, then check the values) multiplied by how many categories you are looking at.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On one hand, I can see why you did this refactor.

Mainly dragging it to the aria crate, the map was already used in noStaticElementInteractions, so dragged it over. If you have any suggestion, I am open to change :)

@dyc3 dyc3 Apr 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the short term, I would rather the rules just have one list they binary search. You could strip the on prefixes from them and do something like text.starts_with("on") && text[2..].binary_search() to be able to deal with the vue directives cases, and avoid the format!s.

@Netail Netail Apr 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But that would mean, 4-6 rules with an array to maintain, instead of 1 single source of truth. It's just that some require a few extra event handlers than others. Doesn't that also increase unnecessarily the binary?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's true, but a better refactor would be a macro or something so we can filter the lists at compile time instead of at run time. Or maybe we could use bitflags in some way to apply filters. It's something I'd rather have in a different PR so it doesn't block this rule getting merged, and to better see what the benchmarks say about it.

And regarding binary size, best case the compiler sees the same strings and deduplicates them, worst case we increase the binary size by a kilobyte tops. Probably doesn't matter all that much.

@Netail Netail Apr 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text[2..].binary_search() to be able to deal with the vue directives cases, and avoid the format!s.

Huh? But wouldn't you then binary search through the string? (if that's even possible) Instead of searching through an array for the value

Refactoring the list stuff in another PR sounds good

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry i meant list.binary_search(text[2..]). i was trying to illustrate how you could deal with the vue directives.

@ematipico ematipico requested a review from dyc3 April 24, 2026 07:37
@ematipico

ematipico commented Apr 24, 2026

Copy link
Copy Markdown
Member

That's rule @Netail , so I think you update the description in Closes #...

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/biome_aria/src/event_handlers.rs`:
- Around line 98-105: Add behavioral matcher tests alongside the existing
ordering checks to assert actual matching behavior for different casings and
prefix forms; create a new test (or extend test_order) that looks up handlers in
EVENT_HANDLERS (the EVENT_HANDLERS map/vec and its matcher logic) for strings
like "onclick", "onClick", "ONCLICK", and "click" and assert the expected
handler is returned (or that matching succeeds/fails as intended) for each
variant; reference the EVENT_HANDLERS symbol and any matching function used by
the runtime so the test exercises the same lookup/matching code path and
prevents regressions in prefix/casing handling.
- Around line 82-85: The code strips an "on" prefix using starts_with("on")
which misses HTML-style attributes like "OnClick"/"ONCLICK"; change the prefix
check to be case-insensitive (e.g. check the first two bytes/chars with
eq_ignore_ascii_case("on") or use a case-insensitive substring compare) before
slicing event_handler, then compute event_handler_lower =
event_handler.to_lowercase_cow() as before; update the logic around the
event_handler variable in event_handlers.rs (the starts_with("on") check and
subsequent slicing) so any case variant of "on" is removed correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e64672ac-9631-4c57-9e4d-0a337cd7b292

📥 Commits

Reviewing files that changed from the base of the PR and between 59eedd0 and 54636c8.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock and included by **
📒 Files selected for processing (2)
  • crates/biome_aria/src/event_handlers.rs
  • crates/biome_html_analyze/src/a11y.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_html_analyze/src/a11y.rs

Comment thread crates/biome_aria/src/event_handlers.rs Outdated
Comment on lines +98 to +105
#[test]
fn test_order() {
assert!(EVENT_HANDLERS.is_sorted_by_key(|(k, _)| *k));

for (_, v) in EVENT_HANDLERS.iter() {
assert!(v.is_sorted());
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Please add behavioural matcher tests, not only ordering checks.

Nice guard on sorting. Add direct assertions for prefix/casing paths (onclick, onClick, ONCLICK, click) so this doesn’t regress again.

Suggested test shape
 #[test]
 fn test_order() {
     assert!(EVENT_HANDLERS.is_sorted_by_key(|(k, _)| *k));

     for (_, v) in EVENT_HANDLERS.iter() {
         assert!(v.is_sorted());
     }
 }
+
+#[test]
+fn test_matches_event_handler_normalisation() {
+    let mouse = &["mouse"];
+
+    assert!(matches_event_handler(mouse, "click"));
+    assert!(matches_event_handler(mouse, "onclick"));
+    assert!(matches_event_handler(mouse, "onClick"));
+    assert!(matches_event_handler(mouse, "ONCLICK"));
+    assert!(!matches_event_handler(mouse, "onnotarealevent"));
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_aria/src/event_handlers.rs` around lines 98 - 105, Add
behavioral matcher tests alongside the existing ordering checks to assert actual
matching behavior for different casings and prefix forms; create a new test (or
extend test_order) that looks up handlers in EVENT_HANDLERS (the EVENT_HANDLERS
map/vec and its matcher logic) for strings like "onclick", "onClick", "ONCLICK",
and "click" and assert the expected handler is returned (or that matching
succeeds/fails as intended) for each variant; reference the EVENT_HANDLERS
symbol and any matching function used by the runtime so the test exercises the
same lookup/matching code path and prevents regressions in prefix/casing
handling.

@Netail Netail force-pushed the feat/port-no-static-element-interactions branch from 54636c8 to 461e748 Compare April 25, 2026 17:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
crates/biome_aria/src/event_handlers.rs (1)

99-106: ⚠️ Potential issue | 🟡 Minor

Please add behavioural tests, not only ordering checks.

Line 99-Line 106 only proves sortedness; it doesn’t protect actual matching behaviour. Please add direct assertions for click, onclick, onClick, ONCLICK, and a negative case so normalisation doesn’t regress again.

Proposed test addition
 #[test]
 fn test_order() {
     assert!(EVENT_HANDLERS.is_sorted_by_key(|(k, _)| *k));

     for (_, v) in EVENT_HANDLERS.iter() {
         assert!(v.is_sorted());
     }
 }
+
+#[test]
+fn test_matches_event_handler_normalisation() {
+    let mouse = &["mouse"];
+
+    assert!(matches_event_handler(mouse, "click"));
+    assert!(matches_event_handler(mouse, "onclick"));
+    assert!(matches_event_handler(mouse, "onClick"));
+    assert!(matches_event_handler(mouse, "ONCLICK"));
+    assert!(!matches_event_handler(mouse, "onnotarealevent"));
+}

As per coding guidelines, “All code changes MUST include appropriate tests: lint rules require snapshot tests in tests/specs/{group}/{rule}/... and bug fixes require tests that reproduce and validate the fix.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_aria/src/event_handlers.rs` around lines 99 - 106, The current
test_order only checks sortedness; add a behavioural test (e.g., new fn
test_event_normalisation or extend test_order) that asserts EVENT_HANDLERS
contains a handler for the normalized event key and that different casings map
to the same entry: check lookups for "click", "onclick", "onClick", and
"ONCLICK" all resolve to the same handler value from EVENT_HANDLERS (use the
same key-normalisation used by insertion/lookup code), and include a negative
assertion that a non-matching variant (e.g., "on-click" or "clicker") is not
present. Reference EVENT_HANDLERS and the test function name (test_order) so the
behaviour checks live alongside the ordering assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@crates/biome_aria/src/event_handlers.rs`:
- Around line 99-106: The current test_order only checks sortedness; add a
behavioural test (e.g., new fn test_event_normalisation or extend test_order)
that asserts EVENT_HANDLERS contains a handler for the normalized event key and
that different casings map to the same entry: check lookups for "click",
"onclick", "onClick", and "ONCLICK" all resolve to the same handler value from
EVENT_HANDLERS (use the same key-normalisation used by insertion/lookup code),
and include a negative assertion that a non-matching variant (e.g., "on-click"
or "clicker") is not present. Reference EVENT_HANDLERS and the test function
name (test_order) so the behaviour checks live alongside the ordering
assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1f0f2e57-dd54-4eca-9572-576b917ecac9

📥 Commits

Reviewing files that changed from the base of the PR and between 54636c8 and 461e748.

📒 Files selected for processing (2)
  • crates/biome_aria/src/event_handlers.rs
  • crates/biome_html_analyze/src/a11y.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_html_analyze/src/a11y.rs

@dyc3 dyc3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine

@Netail Netail merged commit 0eb9310 into biomejs:next Apr 25, 2026
36 of 37 checks passed
@Netail Netail deleted the feat/port-no-static-element-interactions branch April 25, 2026 18:20
@github-actions github-actions Bot mentioned this pull request Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Linter Area: linter L-HTML Language: HTML and super languages L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants