{"id":"38612392d4fa156e0346906b8c017b5ebe036d2bc8780447f92f52622015ef59","type":"Contented","path":"/jest/pipelines/jest-markdown","modifiedDate":1686373756200,"sections":["Pipelines"],"fields":{"title":"Jest Markdown Pipeline"},"html":"<nav class=\"toc\"><ol class=\"toc-level toc-level-1\"><li class=\"toc-item toc-item-h1\"><a class=\"toc-link toc-link-h1\" href=\"#jest-markdown-pipeline\">Jest Markdown Pipeline</a><ol class=\"toc-level toc-level-2\"><li class=\"toc-item toc-item-h2\"><a class=\"toc-link toc-link-h2\" href=\"#comments-parsing\">Comments Parsing</a><ol class=\"toc-level toc-level-3\"><li class=\"toc-item toc-item-h3\"><a class=\"toc-link toc-link-h3\" href=\"#this-section-is-generated-by-the-code-snippet-below\">This section is generated by the code snippet below.</a></li></ol></li><li class=\"toc-item toc-item-h2\"><a class=\"toc-link toc-link-h2\" href=\"#including-codeblocks\">Including Codeblocks</a></li><li class=\"toc-item toc-item-h2\"><a class=\"toc-link toc-link-h2\" href=\"#beta-pipeline\">Beta Pipeline</a><ol class=\"toc-level toc-level-3\"><li class=\"toc-item toc-item-h3\"><a class=\"toc-link toc-link-h3\" href=\"#myapi-javascript-client\">MyAPI: Javascript Client</a><ol class=\"toc-level toc-level-4\"><li class=\"toc-item toc-item-h4\"><a class=\"toc-link toc-link-h4\" href=\"#getrecords\">GetRecords</a><ol class=\"toc-level toc-level-5\"><li class=\"toc-item toc-item-h5\"><a class=\"toc-link toc-link-h5\" href=\"#example\">Example</a></li></ol></li><li class=\"toc-item toc-item-h4\"><a class=\"toc-link toc-link-h4\" href=\"#putrecord\">PutRecord</a><ol class=\"toc-level toc-level-5\"><li class=\"toc-item toc-item-h5\"><a class=\"toc-link toc-link-h5\" href=\"#example-1\">Example</a></li></ol></li></ol></li></ol></li></ol></li></ol></nav><h1 id=\"jest-markdown-pipeline\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#jest-markdown-pipeline\"><span class=\"icon icon-link\"></span></a>Jest Markdown Pipeline</h1>\n<p>\"Nothing is better than documentation with examples. But nothing is worse than examples that\ndon't work because the code has changed since the documentation was written.\" - rustbook</p>\n<p>Example code blocks in our markdown or inline documentation comments can be useful to quickly\ndemonstrate how one can use our software. As they are part of our living standards, each example\ncode should be functional code that can be asserted and tested. Documentation example code should be\nautomated, tested and linted as part of our workflow.</p>\n<p>Initially, we were thinking of creating a <code>md-jest</code> for parsing code blocks in markdown and transforming them into\njest tests. Similar to how <code>ts-jest</code> transform TS to CommonJS, but using <code>contented-processor</code> to transform MD files.</p>\n<p><a href=\"https://github.com/eli-lim\" target=\"_blank\" rel=\"nofollow\">@eli-lim</a> suggested we transform jest files <code>*.test.ts</code> into Markdown instead. We\nget the DX of writing test with Jest and IDE support (without having to support write our own runner). It is much\neasier to transform comments to markdown than transform markdown to code (although not much harder, the focus here is\non the DX). Further, you get the natural flow of writing narrative and writing tests as a narrative.</p>\n<blockquote>\n<p>This page, is written in a jest test file. <code>JestMarkdown.spec.ts</code></p>\n</blockquote>\n<h2 id=\"comments-parsing\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#comments-parsing\"><span class=\"icon icon-link\"></span></a>Comments Parsing</h2>\n<p>All comments are automatically picked up as Markdown with indent stripped. Indent are stripped using\n<code>strip-indent</code>, <code>*</code> are also stripped. For bullet points, you should use <code>-</code> and avoid using <code>*</code> to prevent\nunintentional stripping.</p>\n<ul>\n<li><code>//</code> - Line Comment</li>\n<li><code>/*</code> - Block Comment</li>\n<li><code>/**</code> - Block Comment</li>\n</ul>\n<hr>\n<h3 id=\"this-section-is-generated-by-the-code-snippet-below\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#this-section-is-generated-by-the-code-snippet-below\"><span class=\"icon icon-link\"></span></a>This section is generated by the code snippet below.</h3>\n<p>This is a multi line with <code>*</code> stripped from each line.</p>\n<p>This is a <code>Line Comment</code></p>\n<p>This is a <code>Block Comment</code></p>\n<p>This is a <code>Multi Line</code>\n<code>Block Comment</code> without <code>*</code>.</p>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #768390\">/**</span></span>\n<span class=\"line\"><span style=\"color: #768390\"> * ### This section is generated by the code snippet below.</span></span>\n<span class=\"line\"><span style=\"color: #768390\"> *</span></span>\n<span class=\"line\"><span style=\"color: #768390\"> * This is a multi line with `*` stripped from each line.</span></span>\n<span class=\"line\"><span style=\"color: #768390\"> */</span></span>\n<span class=\"line\"><span style=\"color: #768390\">// This is a `Line Comment`</span></span>\n<span class=\"line\"><span style=\"color: #768390\">/* This is a `Block Comment` */</span></span>\n<span class=\"line\"><span style=\"color: #768390\">/* This is a `Multi Line`</span></span>\n<span class=\"line\"><span style=\"color: #768390\"> `Block Comment` without `*`. */</span></span></code></pre>\n<h2 id=\"including-codeblocks\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#including-codeblocks\"><span class=\"icon icon-link\"></span></a>Including Codeblocks</h2>\n<p><code>JestMarkdown</code> has the ability to \"pickup\" codes and add them into a codeblock. Codeblock is parsed line by line,\n<code>@contented codeblock:start</code> indicate the starting line and <code>@contented codeblock:end</code> indicate the ending line.\nEverything between will be included into a codeblock. Although not recommended, you can nest multiple\n<code>@contented codeblock</code> between.</p>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #96D0FF\">'@contented codeblock:start'</span><span style=\"color: #ADBAC7\">,</span></span></code></pre>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #96D0FF\">'@contented codeblock:end'</span><span style=\"color: #ADBAC7\">,</span></span></code></pre>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #DCBDFB\">it</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'this it statement is in a codeblock with nested codeblock'</span><span style=\"color: #ADBAC7\">, () </span><span style=\"color: #F47067\">=></span><span style=\"color: #ADBAC7\"> {</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  </span><span style=\"color: #F47067\">const</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #6CB6FF\">symbols</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">=</span><span style=\"color: #ADBAC7\"> [</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #768390\">// @contented codeblock:start</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #96D0FF\">'@contented codeblock:start'</span><span style=\"color: #ADBAC7\">,</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #768390\">// @contented codeblock:end</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #96D0FF\">'everything in between will be included as a TypeScript codeblock ```ts</span><span style=\"color: #6CB6FF\">\\n</span><span style=\"color: #96D0FF\">${codes}</span><span style=\"color: #6CB6FF\">\\n</span><span style=\"color: #96D0FF\">```'</span><span style=\"color: #ADBAC7\">,</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #768390\">// @contented codeblock:start</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #96D0FF\">'@contented codeblock:end'</span><span style=\"color: #ADBAC7\">,</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #768390\">// @contented codeblock:end</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  ];</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  </span><span style=\"color: #DCBDFB\">expect</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #DCBDFB\">join</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #F47067\">...</span><span style=\"color: #ADBAC7\">symbols)).</span><span style=\"color: #DCBDFB\">toBeDefined</span><span style=\"color: #ADBAC7\">();</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">});</span></span></code></pre>\n<h2 id=\"beta-pipeline\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#beta-pipeline\"><span class=\"icon icon-link\"></span></a>Beta Pipeline</h2>\n<div class=\"admonitions yellow\"><p>This Pipeline is currently in Beta!</p></div>\n<p>This pipeline is considered Beta, while the idea and the intent will stay intact. We want to optimize this\npipeline for better integration with Jest. Better integration with Jest Semantic <code>describe</code>, <code>it</code>, <code>before</code>, and\n<code>after</code>; to achieve a more natural authoring process.</p>\n<p>Imagine the below:</p>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #DCBDFB\">describe</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'MyAPI: Javascript Client'</span><span style=\"color: #ADBAC7\">, () </span><span style=\"color: #F47067\">=></span><span style=\"color: #ADBAC7\"> {</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  </span><span style=\"color: #F47067\">const</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #6CB6FF\">api</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">=</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">new</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #DCBDFB\">MyApi</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'https://my-api.com'</span><span style=\"color: #ADBAC7\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  </span><span style=\"color: #DCBDFB\">describe</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'GetRecords'</span><span style=\"color: #ADBAC7\">, () </span><span style=\"color: #F47067\">=></span><span style=\"color: #ADBAC7\"> {</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #DCBDFB\">it</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'Example'</span><span style=\"color: #ADBAC7\">, </span><span style=\"color: #F47067\">function</span><span style=\"color: #ADBAC7\"> () {</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">      </span><span style=\"color: #F47067\">const</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #6CB6FF\">records</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">=</span><span style=\"color: #ADBAC7\"> api.</span><span style=\"color: #DCBDFB\">GetRecords</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #6CB6FF\">10</span><span style=\"color: #ADBAC7\">);</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    });</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  });</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  </span><span style=\"color: #DCBDFB\">describe</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'PutRecord'</span><span style=\"color: #ADBAC7\">, () </span><span style=\"color: #F47067\">=></span><span style=\"color: #ADBAC7\"> {</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    </span><span style=\"color: #DCBDFB\">it</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'Example'</span><span style=\"color: #ADBAC7\">, </span><span style=\"color: #F47067\">async</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">function</span><span style=\"color: #ADBAC7\"> () {</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">      </span><span style=\"color: #F47067\">await</span><span style=\"color: #ADBAC7\"> api.</span><span style=\"color: #DCBDFB\">PutRecord</span><span style=\"color: #ADBAC7\">({</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        text: </span><span style=\"color: #96D0FF\">'MyText'</span><span style=\"color: #ADBAC7\">,</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">      });</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    });</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  });</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">});</span></span></code></pre>\n<p>Should generate this Markdown:</p>\n<h3 id=\"myapi-javascript-client\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#myapi-javascript-client\"><span class=\"icon icon-link\"></span></a>MyAPI: Javascript Client</h3>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #F47067\">const</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #6CB6FF\">api</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">=</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">new</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #DCBDFB\">MyApi</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #96D0FF\">'https://my-api.com'</span><span style=\"color: #ADBAC7\">);</span></span></code></pre>\n<h4 id=\"getrecords\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#getrecords\"><span class=\"icon icon-link\"></span></a>GetRecords</h4>\n<h5 id=\"example\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#example\"><span class=\"icon icon-link\"></span></a>Example</h5>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #F47067\">const</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #6CB6FF\">records</span><span style=\"color: #ADBAC7\"> </span><span style=\"color: #F47067\">=</span><span style=\"color: #ADBAC7\"> api.</span><span style=\"color: #DCBDFB\">GetRecords</span><span style=\"color: #ADBAC7\">(</span><span style=\"color: #6CB6FF\">10</span><span style=\"color: #ADBAC7\">);</span></span></code></pre>\n<h4 id=\"putrecord\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#putrecord\"><span class=\"icon icon-link\"></span></a>PutRecord</h4>\n<h5 id=\"example-1\"><a aria-hidden=\"true\" tabindex=\"-1\" href=\"#example-1\"><span class=\"icon icon-link\"></span></a>Example</h5>\n<pre class=\"shiki\" style=\"background-color: #22272e\"><code><span class=\"line\"><span style=\"color: #F47067\">await</span><span style=\"color: #ADBAC7\"> api.</span><span style=\"color: #DCBDFB\">PutRecord</span><span style=\"color: #ADBAC7\">({</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">  text: </span><span style=\"color: #96D0FF\">'MyText'</span><span style=\"color: #ADBAC7\">,</span></span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">});</span></span></code></pre>","headings":[{"depth":1,"id":"jest-markdown-pipeline","title":"Jest Markdown Pipeline","children":[{"depth":2,"id":"comments-parsing","title":"Comments Parsing","children":[{"depth":3,"id":"this-section-is-generated-by-the-code-snippet-below","title":"This section is generated by the code snippet below.","children":[]}]},{"depth":2,"id":"including-codeblocks","title":"Including Codeblocks","children":[]},{"depth":2,"id":"beta-pipeline","title":"Beta Pipeline","children":[{"depth":3,"id":"myapi-javascript-client","title":"MyAPI: Javascript Client","children":[]}]}]}]}