(** Tests for the html5_checker library *) (** Helper to create a reader from a string *) let reader_of_string s = Bytesrw.Bytes.Reader.of_string s (** Helper to check if a message contains a substring *) let message_contains msg substring = String.lowercase_ascii msg.Html5_checker.Message.message |> fun s -> String.length s >= String.length substring && try ignore (Str.search_forward (Str.regexp_case_fold (Str.quote substring)) s 0); true with Not_found -> false (** Test that valid HTML5 produces no errors *) let test_valid_html5 () = Printf.printf "Test 1: Valid HTML5 document\n"; let html = {|
Hello world
|} in let reader = reader_of_string html in let result = Html5_checker.check reader in let errors = Html5_checker.errors result in Printf.printf " Found %d error(s)\n" (List.length errors); if List.length errors > 0 then begin List.iter (fun msg -> Printf.printf " - %s\n" msg.Html5_checker.Message.message ) errors; end else Printf.printf " OK: No errors as expected\n" (** Test that missing DOCTYPE is detected *) let test_missing_doctype () = Printf.printf "\nTest 2: Missing DOCTYPE\n"; let html = "Hello" in let reader = reader_of_string html in let result = Html5_checker.check reader in let errors = Html5_checker.errors result in Printf.printf " Found %d error(s)\n" (List.length errors); if List.length errors = 0 then Printf.printf " Warning: Expected parse errors for missing DOCTYPE\n" else begin List.iter (fun msg -> Printf.printf " - %s\n" msg.Html5_checker.Message.message ) errors; end (** Test that obsolete elements are detected *) let test_obsolete_element () = Printf.printf "\nTest 3: Obsolete
|} in
let reader = reader_of_string html in
let result = Html5_checker.check reader in
let all_msgs = Html5_checker.messages result in
Printf.printf " Found %d message(s)\n" (List.length all_msgs);
let img_msgs = List.filter (fun m ->
message_contains m "alt" || (message_contains m "img" && message_contains m "attribute")
) all_msgs in
if List.length img_msgs > 0 then begin
Printf.printf " Found img/alt-related messages:\n";
List.iter (fun msg ->
Printf.printf " - %s\n" msg.Html5_checker.Message.message
) img_msgs;
end else
Printf.printf " Note: No missing alt attribute errors found (checker may not be enabled)\n"
(** Test invalid nesting *)
let test_invalid_nesting () =
Printf.printf "\nTest 7: Invalid nesting - inside \n";
let html = {|
Link Nested
|} in
let reader = reader_of_string html in
let result = Html5_checker.check reader in
let all_msgs = Html5_checker.messages result in
Printf.printf " Found %d message(s)\n" (List.length all_msgs);
let nesting_msgs = List.filter (fun m ->
message_contains m "nesting" || message_contains m "nested" || message_contains m "ancestor"
) all_msgs in
if List.length nesting_msgs > 0 then begin
Printf.printf " Found nesting-related messages:\n";
List.iter (fun msg ->
Printf.printf " - %s\n" msg.Html5_checker.Message.message
) nesting_msgs;
end else
Printf.printf " Note: No nesting errors found (checker may not be enabled)\n"
(** Test form inside form *)
let test_form_nesting () =
Printf.printf "\nTest 8: Invalid nesting -
|} in
let reader = reader_of_string html in
let result = Html5_checker.check reader in
let all_msgs = Html5_checker.messages result in
Printf.printf " Found %d message(s)\n" (List.length all_msgs);
let form_msgs = List.filter (fun m ->
message_contains m "form"
) all_msgs in
if List.length form_msgs > 0 then begin
Printf.printf " Found form-related messages:\n";
List.iter (fun msg ->
Printf.printf " - %s\n" msg.Html5_checker.Message.message
) form_msgs;
end else
Printf.printf " Note: No form nesting errors found (checker may not be enabled)\n"
(** Test output formatting *)
let test_output_formats () =
Printf.printf "\nTest 9: Output format testing\n";
let html = {|Test
|} in let reader = reader_of_string html in let result = Html5_checker.check reader in Printf.printf " Testing text format:\n"; let text_output = Html5_checker.format_text result in Printf.printf " Length: %d chars\n" (String.length text_output); Printf.printf " Testing JSON format:\n"; let json_output = Html5_checker.format_json result in Printf.printf " Length: %d chars\n" (String.length json_output); Printf.printf " Testing GNU format:\n"; let gnu_output = Html5_checker.format_gnu result in Printf.printf " Length: %d chars\n" (String.length gnu_output) (** Test has_errors function *) let test_has_errors () = Printf.printf "\nTest 10: has_errors function\n"; (* Valid document should have no errors *) let valid_html = "Valid
" in let result1 = Html5_checker.check (reader_of_string valid_html) in Printf.printf " Valid document has_errors: %b\n" (Html5_checker.has_errors result1); (* Document with likely parse errors *) let invalid_html = "Unclosed" in let result2 = Html5_checker.check (reader_of_string invalid_html) in Printf.printf " Invalid document has_errors: %b\n" (Html5_checker.has_errors result2) (** Test check_dom with pre-parsed document *) let test_check_dom () = Printf.printf "\nTest 11: check_dom with pre-parsed document\n"; let html = "
Test
" in let reader = reader_of_string html in let parsed = Html5rw.parse reader in let result = Html5_checker.check_dom parsed in let all_msgs = Html5_checker.messages result in Printf.printf " check_dom found %d message(s)\n" (List.length all_msgs); Printf.printf " OK: check_dom completed successfully\n" (** Test system_id parameter *) let test_system_id () = Printf.printf "\nTest 12: system_id parameter\n"; let html = "Test
" in let reader = reader_of_string html in let result = Html5_checker.check ~system_id:"test.html" reader in match Html5_checker.system_id result with | Some id -> Printf.printf " system_id: %s\n" id | None -> Printf.printf " Warning: system_id not set\n" (** Test collect_parse_errors flag *) let test_collect_parse_errors_flag () = Printf.printf "\nTest 13: collect_parse_errors flag\n"; let html = "Test
" in let result_with = Html5_checker.check ~collect_parse_errors:true (reader_of_string html) in let msgs_with = Html5_checker.messages result_with in Printf.printf " With parse errors: %d message(s)\n" (List.length msgs_with); let result_without = Html5_checker.check ~collect_parse_errors:false (reader_of_string html) in let msgs_without = Html5_checker.messages result_without in Printf.printf " Without parse errors: %d message(s)\n" (List.length msgs_without) (** Test document accessor *) let test_document_accessor () = Printf.printf "\nTest 14: document accessor\n"; let html = "Test
" in let reader = reader_of_string html in let result = Html5_checker.check reader in let _doc = Html5_checker.document result in Printf.printf " OK: document accessor works\n" (** Test message severity filtering *) let test_severity_filtering () = Printf.printf "\nTest 15: Message severity filtering\n"; let html = "Test
" in let reader = reader_of_string html in let result = Html5_checker.check reader in let all_msgs = Html5_checker.messages result in let errors = Html5_checker.errors result in let warnings = Html5_checker.warnings result in Printf.printf " Total messages: %d\n" (List.length all_msgs); Printf.printf " Errors: %d\n" (List.length errors); Printf.printf " Warnings: %d\n" (List.length warnings); (* Verify that errors + warnings <= all messages *) if List.length errors + List.length warnings <= List.length all_msgs then Printf.printf " OK: Message counts are consistent\n" else Printf.printf " Warning: Message counts inconsistent\n" (** Run all tests *) let () = Printf.printf "Running html5_checker tests...\n"; Printf.printf "========================================\n\n"; test_valid_html5 (); test_missing_doctype (); test_obsolete_element (); test_duplicate_id (); test_heading_skip (); test_img_without_alt (); test_invalid_nesting (); test_form_nesting (); test_output_formats (); test_has_errors (); test_check_dom (); test_system_id (); test_collect_parse_errors_flag (); test_document_accessor (); test_severity_filtering (); Printf.printf "\n========================================\n"; Printf.printf "All tests completed!\n"; Printf.printf "\nNote: Some checkers may not be enabled yet.\n"; Printf.printf "Tests marked with 'Note:' indicate features that may be\n"; Printf.printf "implemented in future versions.\n"