commit 7835c21a2e54612e597c3a75e86ab36353621129
parent e43319905105548d91102e98c5926df838e05dcb
Author: Andrew Laack <andrew@laack.co>
Date: Tue, 1 Sep 2026 19:59:40 -0500
Setup basic testing for rendering
Diffstat:
11 files changed, 118 insertions(+), 23 deletions(-)
diff --git a/learning/Makefile b/learning/Makefile
@@ -0,0 +1,4 @@
+run:
+ dune exec learning ../courses
+tests:
+ dune runtest
diff --git a/learning/dune.lock/kdf.1.1.0.pkg b/learning/dune.lock/kdf.1.1.0.pkg
@@ -1,19 +0,0 @@
-(version 1.1.0)
-
-(build
- (all_platforms
- ((action
- (progn
- (when %{pkg-self:dev} (run dune subst))
- (run dune build -p %{pkg-self:name} -j %{jobs}))))))
-
-(depends
- (all_platforms
- (ocaml dune digestif mirage-crypto)))
-
-(source
- (fetch
- (url
- https://github.com/robur-coop/kdf/releases/download/v1.1.0/kdf-1.1.0.tbz)
- (checksum
- sha512=85a8e95389be1040fa1ac76dc49a87d205366b5220f5c023d5ec3e72d5c193a9379dfd920027b9b58aee227300a4c558763380f607cc6558497352c13a82ed15)))
diff --git a/learning/dune.lock/kdf.1.1.1.pkg b/learning/dune.lock/kdf.1.1.1.pkg
@@ -0,0 +1,19 @@
+(version 1.1.1)
+
+(build
+ (all_platforms
+ ((action
+ (progn
+ (when %{pkg-self:dev} (run dune subst))
+ (run dune build -p %{pkg-self:name} -j %{jobs}))))))
+
+(depends
+ (all_platforms
+ (ocaml dune digestif mirage-crypto)))
+
+(source
+ (fetch
+ (url
+ https://github.com/robur-coop/kdf/releases/download/v1.1.1/kdf-1.1.1.tbz)
+ (checksum
+ sha512=8584c24b249d9d264fc58e1cd8299968b6098fe915fe7c8f935937c7e3cb200bde0bd0fdb042fb000337fb0b6298866068933cd20b95e51a021cbf3e9e3c6456)))
diff --git a/learning/dune.lock/lock.dune b/learning/dune.lock/lock.dune
@@ -12,7 +12,7 @@
((source
https://github.com/ocaml-dune/opam-repository-relocatable.git#d64df82c7e16de819a770cabf4066a06243ed80b))
((source
- https://github.com/ocaml/opam-repository.git#faef8a99e98446bcc68159b6b5a4d5c00c816dfc))))
+ https://github.com/ocaml/opam-repository.git#da8b7e6fa7491ffc5dc8eee7f8f60452a1b26ce7))))
(expanded_solver_variable_bindings
(variable_values
diff --git a/learning/lib/shared.ml b/learning/lib/shared.ml
@@ -1 +1,2 @@
-let course_dir = if Array.length Sys.argv > 1 then Sys.argv.(1) ^ "/" else "../courses/"
+(* ALWAYS pass in directory to watch. Fallback should only be for tests. *)
+let course_dir = if Array.length Sys.argv > 1 then Sys.argv.(1) ^ "/" else "./test_courses/"
diff --git a/learning/test/dune b/learning/test/dune
@@ -1,3 +1,5 @@
(test
(name test_learning)
- (libraries learning))
+ (libraries learning)
+ (deps (glob_files_rec ./test_courses/*))
+ )
diff --git a/learning/test/test_courses/course_0/0_example.sl b/learning/test/test_courses/course_0/0_example.sl
@@ -0,0 +1,4 @@
+# H
+## H
+### H
+This is an example sl file.
diff --git a/learning/test/test_courses/course_0/1_example.sl b/learning/test/test_courses/course_0/1_example.sl
@@ -0,0 +1,10 @@
+#TEST
+##TEST
+##TEST
+###TEST
+=>TEST
+=>eTEST
+```TEST
+??TEST
+>TEST
+*TEST
diff --git a/learning/test/test_courses/course_0/hidden.md b/learning/test/test_courses/course_0/hidden.md
@@ -0,0 +1 @@
+This is a hidden file...
diff --git a/learning/test/test_learning.ml b/learning/test/test_learning.ml
@@ -1 +1,2 @@
let () = Test_line_parsing.test_line_parsing ()
+let () = Test_rendering.test_rendering ()
diff --git a/learning/test/test_rendering.ml b/learning/test/test_rendering.ml
@@ -1,4 +1,76 @@
open Learning
+let courses = Array.to_list (Render.get_course_array)
+let expected_courses = ["course_0";"course_1";"course_empty"]
+let course_0_page_0 = Render.render_page "course_0" "0_example.sl"
+let course_0_page_1 = Render.render_page "course_0" "1_example.sl"
+let pages_in_order = Render.get_pages_in_order "course_0"
+
+
+let contains s1 s2 =
+ let len1 = String.length s1 and len2 = String.length s2 in
+ let rec go idx =
+ if idx + len2 > len1 then false
+ else if String.sub s1 idx len2 = s2 then true
+ else go (idx + 1)
+ in
+ go 0
+
+
let test_rendering () =
- print_endline (Render.get_path_to_page "smt" "smt")
+
+ (* Verify non-sl extension pages are hidden for course listings. *)
+ assert ((List.length pages_in_order) = 2);
+
+ (*Verify happy path course listing.*)
+ assert (courses = expected_courses);
+ assert ((Render.render_page "course_0" "0_example.sl") != "");
+
+ (*
+ Verify sensible expectations about each line. We assume the
+ mapping between sl headers and html headers, and then check
+ text existence.
+ *)
+
+ assert (contains course_0_page_0 "<h1>");
+ assert (contains course_0_page_0 "<h2>");
+ assert (contains course_0_page_0 "<h3>");
+ assert (contains course_0_page_0 "This is an example sl file.");
+
+ (*
+ Verify the following don't render when mis-specified:
+ - # -> h1
+ - ## -> h2
+ - ### -> h3
+ - => -> href
+ - =>e -> iframe
+ - ``` -> results in subsequent preformatted lines
+ - ?? -> summary (used to hide / unhide in html)
+ - > -> blockquote
+ - * -> ul
+ *)
+
+ (* TODO: These are brittle; add classes for rendering / validation in templates. *)
+ assert (not (contains course_0_page_1 "<h1>"));
+ assert (not (contains course_0_page_1 "<h2>"));
+ assert (not (contains course_0_page_1 "<h3>"));
+ assert (not (contains course_0_page_1 "href=TEST"));
+ assert (not (contains course_0_page_1 "iframe"));
+ assert (not (contains course_0_page_1 "<pre-formatted>"));
+ assert (not (contains course_0_page_1 "summary"));
+ assert (not (contains course_0_page_1 "quote"));
+ assert (not (contains course_0_page_1 "ul"));
+
+(*
+ type line_format =
+ | Normal
+ | HeaderL1
+ | HeaderL2
+ | HeaderL3
+ | Embedded
+ | Preformatted
+ | Hidden
+ | Quote
+ | Link
+ | ListItem
+*)