Packages
Library for accessibility snapshot testing in Phoenix applications using axe-core and Playwright.
Current section
Files
Jump to
Current section
Files
lib/telemetry_capture/analyzers/form_validation.ex
defmodule Excessibility.TelemetryCapture.Analyzers.FormValidation do
@moduledoc """
Analyzes form validation patterns.
Detects excessive validation roundtrips without form submission.
This may indicate UX issues (too many server calls) or missing debouncing.
Threshold: >5 validations without submit triggers warning.
## Output
%{
findings: [
%{
severity: :warning,
message: "7 consecutive validations without submit - consider debouncing",
events: [],
metadata: %{streak: 7}
}
],
stats: %{
validation_count: 10,
submit_count: 1,
max_validation_streak: 7
}
}
"""
@behaviour Excessibility.TelemetryCapture.Analyzer
@excessive_threshold 5
def name, do: :form_validation
def default_enabled?, do: true
def analyze(%{timeline: []}, _opts) do
%{
findings: [],
stats: %{validation_count: 0, submit_count: 0, max_validation_streak: 0}
}
end
def analyze(%{timeline: timeline}, _opts) do
{validation_count, submit_count, max_streak} = analyze_validation_flow(timeline)
stats = %{
validation_count: validation_count,
submit_count: submit_count,
max_validation_streak: max_streak
}
findings =
if max_streak > @excessive_threshold do
[
%{
severity: :warning,
message: "#{max_streak} consecutive validations without submit - consider debouncing",
events: [],
metadata: %{streak: max_streak}
}
]
else
[]
end
%{findings: findings, stats: stats}
end
defp analyze_validation_flow(timeline) do
{validation_count, submit_count, current_streak, max_streak} =
Enum.reduce(timeline, {0, 0, 0, 0}, fn entry, {v_count, s_count, streak, max} ->
cond do
validation_event?(entry) ->
new_streak = streak + 1
{v_count + 1, s_count, new_streak, max(max, new_streak)}
submit_event?(entry) ->
{v_count, s_count + 1, 0, max}
true ->
{v_count, s_count, streak, max}
end
end)
{validation_count, submit_count, max(current_streak, max_streak)}
end
defp validation_event?(%{event: event}) do
String.contains?(event, "validate")
end
defp submit_event?(%{event: event}) do
String.contains?(event, "submit") or String.contains?(event, "save")
end
end