Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-docgen

Documentation publishing for Pudu: articles, API references, navigation, search, and static websites

0.1.0Apache-2.01

InstallClose

ApiExportTest.pudu

Pudu369 lines8.6 KB

GitHub ↗
1/** @Docgen.Api.ExportTests — extracted declarations round out as model, Markdown, and API pages */2module PuduLangDocgen.ApiExportTest34import Std.Io as Io5import Std.Json as Json6import Std.Test as Test7import PuduLangDocgen.Api.Export as Export8import PuduLangDocgen.Api.Model as Model9import PuduLangDocgen.Api.Parser as Parser1011/// A module with a documented record, an undocumented union, a trait, a function, and a constant.12const SOURCE: Str = "/** @M.Module — mod doc */\nmodule M\n\n/// A rec.\nexport type R = \{\n  /// Field a.\n  a: Int\n\}\n\nexport type U = A | B\n\n/// Tr.\nexport trait T \{\n  /// Go.\n  fn go(self: &Self, n: Int) -> Int\n\}\n\n/// Adds.\nexport fn add(a: Int) -> Int \{ a \}\n\nexport const K: Int = 1\n"1314/// A module without documentation holding one empty record.15const BARE: Str = "module N\n\nexport type E = \{\}\n"1617/// Both modules as parsed.18fn units() -> Array[Model.Unit] { [Parser.parse("src/M.pudu", SOURCE), Parser.parse("src/N.pudu", BARE)] }1920/// The text written at a path in a format, or a marker when nothing is.21fn written(format: Str, path: Str) -> Str {22  for (found, text) in Export.files(&units(), format) {23    if found == path { return text }24  }25  "missing " + path26}2728/// Expected markdown output for `M.md`.29fn expectedMarkdownMMd() -> Str {30  [31    "---",32    "uid: M",33    "title: M",34    "---",35    "",36    "# M",37    "",38    "Mod doc",39    "",40    "- <xref:M.R>: A rec.",41    "- <xref:M.U>",42    "- <xref:M.T>: Tr.",43    "",44    "## add \{#add\}",45    "",46    "```pudu",47    "fn add(a: Int) -> Int",48    "```",49    "",50    "Adds.",51    "",52    "## K \{#K\}",53    "",54    "```pudu",55    "const K: Int = 1",56    "```",57    "",58    ""59  ].join("\n")60}6162/// Expected markdown output for `M.R.md`.63fn expectedMarkdownMRMd() -> Str {64  [65    "---",66    "uid: M.R",67    "title: R",68    "---",69    "",70    "# R",71    "",72    "Module <xref:M>",73    "",74    "```pudu",75    "type R = \{ a: Int \}",76    "```",77    "",78    "A rec.",79    "",80    "| Name | Type | Description |",81    "| --- | --- | --- |",82    "| `a` | `Int` | Field a. |",83    ""84  ].join("\n")85}8687/// Expected markdown output for `M.U.md`.88fn expectedMarkdownMUMd() -> Str {89  [90    "---",91    "uid: M.U",92    "title: U",93    "---",94    "",95    "# U",96    "",97    "Module <xref:M>",98    "",99    "```pudu",100    "type U = A | B",101    "```",102    "",103    "| Name | Type | Description |",104    "| --- | --- | --- |",105    "| `A` | `` |  |",106    "| `B` | `` |  |",107    ""108  ].join("\n")109}110111/// Expected markdown output for `M.T.md`.112fn expectedMarkdownMTMd() -> Str {113  [114    "---",115    "uid: M.T",116    "title: T",117    "---",118    "",119    "# T",120    "",121    "Module <xref:M>",122    "",123    "```pudu",124    "trait T",125    "```",126    "",127    "Tr.",128    "",129    "## go \{#go\}",130    "",131    "```pudu",132    "fn go(self: &Self, n: Int) -> Int",133    "```",134    "",135    "Go.",136    "",137    ""138  ].join("\n")139}140141/// Expected markdown output for `N.md`.142fn expectedMarkdownNMd() -> Str {143  [144    "---",145    "uid: N",146    "title: N",147    "---",148    "",149    "# N",150    "",151    "- <xref:N.E>",152    ""153  ].join("\n")154}155156/// Expected markdown output for `N.E.md`.157fn expectedMarkdownNEMd() -> Str {158  [159    "---",160    "uid: N.E",161    "title: E",162    "---",163    "",164    "# E",165    "",166    "Module <xref:N>",167    "",168    "```pudu",169    "type E = \{ \}",170    "```",171    "",172    ""173  ].join("\n")174}175176/// Expected markdown output for `toc.yml`.177fn expectedMarkdownTocYml() -> Str {178  [179    "- name: M",180    "  href: M.md",181    "  items:",182    "  - name: R",183    "    href: M.R.md",184    "  - name: T",185    "    href: M.T.md",186    "  - name: U",187    "    href: M.U.md",188    "- name: N",189    "  href: N.md",190    "  items:",191    "  - name: E",192    "    href: N.E.md",193    ""194  ].join("\n")195}196197/// Expected apiPage output for `M.yml`.198fn expectedApipageMYml() -> Str {199  [200    "#YamlMime:ApiPage",201    "title: M",202    "languageId: pudu",203    "body:",204    "- h1: M",205    "- markdown: Mod doc",206    "- h2: Types",207    "- list:",208    "  - text: R",209    "    url: M.R.html",210    "  - text: U",211    "    url: M.U.html",212    "  - text: T",213    "    url: M.T.html",214    "- api3: add",215    "  id: add",216    "- code: \"fn add(a: Int) -> Int\"",217    "- markdown: Adds.",218    "- parameters:",219    "  - name: a",220    "    type: Int",221    "- api3: K",222    "  id: K",223    "- code: \"const K: Int = 1\"",224    ""225  ].join("\n")226}227228/// Expected apiPage output for `M.R.yml`.229fn expectedApipageMRYml() -> Str {230  [231    "#YamlMime:ApiPage",232    "title: R",233    "languageId: pudu",234    "body:",235    "- h1: R",236    "- facts:",237    "  - name: Module",238    "    value:",239    "      text: M",240    "      url: M.html",241    "- code: \"type R = \{ a: Int \}\"",242    "- markdown: A rec.",243    "- h2: Fields",244    "- parameters:",245    "  - name: a",246    "    type: Int",247    "    description: Field a.",248    ""249  ].join("\n")250}251252/// Expected apiPage output for `M.U.yml`.253fn expectedApipageMUYml() -> Str {254  [255    "#YamlMime:ApiPage",256    "title: U",257    "languageId: pudu",258    "body:",259    "- h1: U",260    "- facts:",261    "  - name: Module",262    "    value:",263    "      text: M",264    "      url: M.html",265    "- code: \"type U = A | B\"",266    "- h2: Variants",267    "- parameters:",268    "  - name: A",269    "    type: \"\"",270    "    description: \"\"",271    "  - name: B",272    "    type: \"\"",273    "    description: \"\"",274    ""275  ].join("\n")276}277278/// Expected apiPage output for `M.T.yml`.279fn expectedApipageMTYml() -> Str {280  [281    "#YamlMime:ApiPage",282    "title: T",283    "languageId: pudu",284    "body:",285    "- h1: T",286    "- facts:",287    "  - name: Module",288    "    value:",289    "      text: M",290    "      url: M.html",291    "- code: trait T",292    "- markdown: Tr.",293    "- h2: Methods",294    "- api3: go",295    "  id: go",296    "- code: \"fn go(self: &Self, n: Int) -> Int\"",297    "- markdown: Go.",298    "- parameters:",299    "  - name: n",300    "    type: Int",301    ""302  ].join("\n")303}304305/// Expected apiPage output for `N.yml`.306fn expectedApipageNYml() -> Str {307  [308    "#YamlMime:ApiPage",309    "title: N",310    "languageId: pudu",311    "body:",312    "- h1: N",313    "- h2: Types",314    "- list:",315    "  - text: E",316    "    url: N.E.html",317    ""318  ].join("\n")319}320321/// Expected apiPage output for `N.E.yml`.322fn expectedApipageNEYml() -> Str {323  [324    "#YamlMime:ApiPage",325    "title: E",326    "languageId: pudu",327    "body:",328    "- h1: E",329    "- facts:",330    "  - name: Module",331    "    value:",332    "      text: N",333    "      url: N.html",334    "- code: \"type E = \{ \}\"",335    ""336  ].join("\n")337}338339/// Runs every export format contract.340fn main() -> Int {341  let json = Export.files(&units(), "json")342  let checks = Test.suite("Api export", &[343      Test.equals("json paths", &json.map(fn(entry: (Str, Str)) -> Str {344            let (path, _text) = entry345            path346          }), &["M.json", "N.json", "toc.yml"]),347      Test.that("json model decodes", match Json.decode(written("json", "M.json")) { case Ok(found) => Json.encode(&found).contains("\"uid\":\"M.T.go\"") case Err(_) => false }),348      Test.equals("json toc links json files", &written("json", "toc.yml"), &"- name: M\n  href: M.json\n  items:\n  - name: R\n    href: M.R.json\n  - name: T\n    href: M.T.json\n  - name: U\n    href: M.U.json\n- name: N\n  href: N.json\n  items:\n  - name: E\n    href: N.E.json\n"),349      Test.equals("markdown paths", &Export.files(&units(), "markdown").length(), &7),350      Test.equals("formats", &Export.FORMATS, &["json", "markdown", "apiPage"]),351      Test.equals("markdown M.md", &written("markdown", "M.md"), &expectedMarkdownMMd()),352      Test.equals("markdown M.R.md", &written("markdown", "M.R.md"), &expectedMarkdownMRMd()),353      Test.equals("markdown M.U.md", &written("markdown", "M.U.md"), &expectedMarkdownMUMd()),354      Test.equals("markdown M.T.md", &written("markdown", "M.T.md"), &expectedMarkdownMTMd()),355      Test.equals("markdown N.md", &written("markdown", "N.md"), &expectedMarkdownNMd()),356      Test.equals("markdown N.E.md", &written("markdown", "N.E.md"), &expectedMarkdownNEMd()),357      Test.equals("markdown toc.yml", &written("markdown", "toc.yml"), &expectedMarkdownTocYml()),358      Test.equals("apiPage M.yml", &written("apiPage", "M.yml"), &expectedApipageMYml()),359      Test.equals("apiPage M.R.yml", &written("apiPage", "M.R.yml"), &expectedApipageMRYml()),360      Test.equals("apiPage M.U.yml", &written("apiPage", "M.U.yml"), &expectedApipageMUYml()),361      Test.equals("apiPage M.T.yml", &written("apiPage", "M.T.yml"), &expectedApipageMTYml()),362      Test.equals("apiPage N.yml", &written("apiPage", "N.yml"), &expectedApipageNYml()),363      Test.equals("apiPage N.E.yml", &written("apiPage", "N.E.yml"), &expectedApipageNEYml())364    ])365  let ran = Test.run(&checks)366  for failure in Test.failuresOf(&ran) { let _printed = Io.writeErrorLine(failure) }367  Test.report(&ran)368}369