summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/test_citation.ml111
-rw-r--r--test/test_colitur.ml1
2 files changed, 112 insertions, 0 deletions
diff --git a/test/test_citation.ml b/test/test_citation.ml
index 75fffe8..e234942 100644
--- a/test/test_citation.ml
+++ b/test/test_citation.ml
@@ -200,3 +200,114 @@ let parse_suite =
("modern name, vulgate id", `Quick, parses "Rev 12:1" "apocalypse|12:1");
("unknown book", `Quick, test_rejects_unknown_book);
("garbage", `Quick, test_rejects_garbage) ]
+
+module R = Colitur_citation.Render
+
+let names id form =
+ let n = B.to_string id in
+ match form with `Abbr -> (if n = "luke" then "Luc." else n)
+ | `Full -> (if n = "luke" then "Evangelium secundum Lucam" else n)
+
+let render_with fields input expected () =
+ let style = R.style_of_fields fields in
+ match P.parse input with
+ | Error e -> Alcotest.failf "%s did not parse: %s" input e
+ | Ok t -> Alcotest.(check s) input expected (R.render style ~names t)
+
+let test_unquotes_trailing_space () =
+ let st = R.style_of_fields [ ("part_sep", "\"; \"") ] in
+ Alcotest.(check s) "quotes stripped, space kept" "; " (R.part_sep st)
+
+let test_bare_value_untouched () =
+ let st = R.style_of_fields [ ("range", "{first}-{last}") ] in
+ Alcotest.(check s) "no quotes" "{first}-{last}" (R.range st)
+
+(* [subst] has no test pressure of its own anywhere else in the suite, so
+ these three isolate its contract directly through the only surface that
+ calls it: a [range]/[chapter_verse] template chosen so nothing else in
+ the pipeline (verse-list joining, book naming) can mask the result. *)
+let test_subst_no_placeholder () =
+ (* A template with no "{" at all passes through completely unchanged. *)
+ render_with [ ("book", "abbr"); ("chapter_verse", "fixed-text") ] "Luke 2:21"
+ "Luc. fixed-text" ()
+
+let test_subst_two_placeholders () =
+ (* Two DIFFERENT known placeholders, reordered relative to the record's
+ own field order ([last] before [first]) -- proves substitution is by
+ name, not by position. *)
+ render_with
+ [ ("book", "abbr"); ("range", "{last}~{first}") ]
+ "Luke 5:12-14" "Luc. 5:14~12" ()
+
+let test_subst_unknown_placeholder_alone () =
+ (* A template that is NOTHING but an unrecognised placeholder: it must
+ survive byte-for-byte, proving [subst] never touches an unmatched
+ "{...}" run even when there is no surrounding literal text to anchor
+ on. *)
+ render_with [ ("book", "abbr"); ("range", "{nope}") ] "Luke 5:12-14"
+ "Luc. 5:{nope}" ()
+
+(* [roman_numeral] is private to Render (not in the .mli, matching
+ [View.roman_numeral]'s own precedent -- tested indirectly, never
+ exposed). Reached through [render] with a [chapter_verse] template of
+ bare [{chapter_roman}], [book_sep] emptied and [names] returning "", so
+ the assertion isolates exactly the numeral and nothing else. *)
+let roman_of n =
+ let luke = match B.of_token "Luke" with Some id -> id | None -> assert false in
+ let t : P.t = { P.book = luke; parts = [ { P.chapter = n; verses = [ { P.first = 1; last = None } ] } ] } in
+ let style = R.style_of_fields [ ("book_sep", ""); ("chapter_verse", "{chapter_roman}") ] in
+ R.render style ~names:(fun _ _ -> "") t
+
+let test_roman_numeral_values () =
+ List.iter
+ (fun (n, expected) -> Alcotest.(check s) (string_of_int n) expected (roman_of n))
+ [ (1, "I"); (4, "IV"); (9, "IX"); (14, "XIV"); (40, "XL"); (150, "CL") ]
+
+let test_roman_numeral_non_positive () =
+ (* The one input that could loop forever in a naive implementation: a
+ non-positive chapter returns the arabic form instead. Completing at
+ all is part of what this test proves. *)
+ Alcotest.(check s) "zero" "0" (roman_of 0);
+ Alcotest.(check s) "negative" "-3" (roman_of (-3))
+
+let render_suite =
+ ( "Citation/render",
+ [ Alcotest.test_case "latin default" `Quick
+ (render_with [ ("book", "abbr") ] "Luke 5:12-14" "Luc. 5:12-14");
+ Alcotest.test_case "full name" `Quick
+ (render_with [ ("book", "full") ] "Luke 5:12-14"
+ "Evangelium secundum Lucam 5:12-14");
+ Alcotest.test_case "comma style" `Quick
+ (render_with
+ [ ("book", "abbr"); ("chapter_verse", "{chapter}, {verses}") ]
+ "Luke 5:12-14" "Luc. 5, 12-14");
+ Alcotest.test_case "multi part" `Quick
+ (render_with [ ("book", "abbr"); ("part_sep", "\"; \"") ]
+ "Joel 2:23-24; 26-27" "joel 2:23-24; 2:26-27");
+ Alcotest.test_case "unquote" `Quick test_unquotes_trailing_space;
+ Alcotest.test_case "bare value" `Quick test_bare_value_untouched;
+ (* The Missal's own convention, scan-verified: "Matth. 11, 2" /
+ "Ioann. 1, 1" -- dotted abbreviation, comma, ARABIC chapter. *)
+ Alcotest.test_case "missal convention" `Quick
+ (render_with
+ [ ("book", "abbr"); ("chapter_verse", "{chapter}, {verses}") ]
+ "Luke 5:12-14" "Luc. 5, 12-14");
+ Alcotest.test_case "roman chapter" `Quick
+ (render_with
+ [ ("book", "abbr"); ("chapter_verse", "{chapter_roman}, {verses}") ]
+ "Luke 5:12-14" "Luc. V, 12-14");
+ (* U+00A0 between book and reference, for typeset output. *)
+ Alcotest.test_case "nbsp book sep" `Quick
+ (render_with [ ("book", "abbr"); ("book_sep", "\"\xc2\xa0\"") ]
+ "Luke 5:12-14" "Luc.\xc2\xa05:12-14");
+ Alcotest.test_case "unknown placeholder survives" `Quick
+ (render_with
+ [ ("book", "abbr"); ("chapter_verse", "{chapter}:{nope}") ]
+ "Luke 5:12-14" "Luc. 5:{nope}");
+ Alcotest.test_case "subst: no placeholder" `Quick test_subst_no_placeholder;
+ Alcotest.test_case "subst: two placeholders" `Quick test_subst_two_placeholders;
+ Alcotest.test_case "subst: unknown placeholder alone" `Quick
+ test_subst_unknown_placeholder_alone;
+ Alcotest.test_case "roman_numeral: table values" `Quick test_roman_numeral_values;
+ Alcotest.test_case "roman_numeral: non-positive" `Quick
+ test_roman_numeral_non_positive ] )
diff --git a/test/test_colitur.ml b/test/test_colitur.ml
index fb2c20c..6084adb 100644
--- a/test/test_colitur.ml
+++ b/test/test_colitur.ml
@@ -7,6 +7,7 @@ let () =
Test_citation_coverage.suite;
Test_citation.suite;
("parse", Test_citation.parse_suite);
+ Test_citation.render_suite;
Test_config.suite;
Test_overlay.suite; Test_overlay_ini.suite; Test_temporal_ef.suite; Test_validate.suite; Test_precedence.suite;
Test_calendar.suite; Test_precedence_ef.suite; Test_sanctoral_ef.suite; Test_rite_ef.suite;