<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://conductofcode.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://conductofcode.io/" rel="alternate" type="text/html" hreflang="en-us" /><updated>2024-09-22T11:41:23+02:00</updated><id>https://conductofcode.io/feed.xml</id><title type="html">Conduct of Code</title><subtitle>Henrik Lau Eriksson on the conduct of code</subtitle><author><name>Henrik Lau Eriksson</name></author><entry><title type="html">Creating custom PowerToys Run plugins</title><link href="https://conductofcode.io/post/creating-custom-powertoys-run-plugins/" rel="alternate" type="text/html" title="Creating custom PowerToys Run plugins" /><published>2024-02-13T23:00:00+01:00</published><updated>2024-09-22T14:00:00+02:00</updated><id>https://conductofcode.io/post/creating-custom-powertoys-run-plugins</id><content type="html" xml:base="https://conductofcode.io/post/creating-custom-powertoys-run-plugins/"><![CDATA[<p>PowerToys Run is a quick launcher for Windows. It is open-source and modular for additional plugins.</p>

<p>Official plugins include:</p>

<ul>
  <li>Calculator</li>
  <li>Unit Converter</li>
  <li>Value Generator</li>
  <li>Windows Search</li>
</ul>

<p>At the time of writing, there are 20 plugins out of the box.</p>

<p>If you think the official plugins are not enough, you can write our own.
The easiest way to get started is to look at what others did.</p>

<ul>
  <li>Official plugins:
    <ul>
      <li><a href="https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Plugins">https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Plugins</a></li>
    </ul>
  </li>
  <li>GitHub topic with potentially interesting repos:
    <ul>
      <li><a href="https://github.com/topics/powertoys-run-plugin">powertoys-run-plugin</a></li>
    </ul>
  </li>
</ul>

<p>Browsing through some of the GitHub repos found above, gives you an idea of how the source code of a plugin looks like.</p>

<h2 id="contents">Contents<!-- omit in toc --></h2>

<ul>
  <li><a href="#demo-plugin">Demo Plugin</a></li>
  <li><a href="#project">Project</a></li>
  <li><a href="#metadata">Metadata</a></li>
  <li><a href="#main">Main</a></li>
  <li><a href="#interfaces">Interfaces</a>
    <ul>
      <li><a href="#iplugin">IPlugin</a></li>
      <li><a href="#iplugini18n">IPluginI18n</a></li>
      <li><a href="#idelayedexecutionplugin">IDelayedExecutionPlugin</a></li>
      <li><a href="#icontextmenu">IContextMenu</a></li>
      <li><a href="#isettingprovider">ISettingProvider</a></li>
    </ul>
  </li>
  <li><a href="#classes">Classes</a>
    <ul>
      <li><a href="#plugininitcontext">PluginInitContext</a></li>
      <li><a href="#query">Query</a></li>
      <li><a href="#result">Result</a></li>
      <li><a href="#contextmenuresult">ContextMenuResult</a></li>
    </ul>
  </li>
  <li><a href="#actions">Actions</a></li>
  <li><a href="#logging">Logging</a></li>
  <li><a href="#dependencies">Dependencies</a></li>
  <li><a href="#tests">Tests</a></li>
  <li><a href="#distribution">Distribution</a></li>
  <li><a href="#linting">Linting</a></li>
  <li><a href="#resources">Resources</a></li>
</ul>

<h2 id="demo-plugin">Demo Plugin</h2>

<p>As a demo, I created a simple plugin that counts the words and characters of the query.</p>

<p><img src="demo-plugin.png" alt="Demo Plugin" /></p>

<ul>
  <li>ActionKeyword: <code class="language-plaintext highlighter-rouge">demo</code></li>
</ul>

<p>Settings:</p>

<p><img src="demo-settings.png" alt="Demo Settings" /></p>

<ul>
  <li>Count spaces: <code class="language-plaintext highlighter-rouge">true</code> | <code class="language-plaintext highlighter-rouge">false</code></li>
</ul>

<p>The source code:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/ConductOfCode/tree/master/PowerToysRun">https://github.com/hlaueriksson/ConductOfCode/tree/master/PowerToysRun</a></li>
</ul>

<p>Throughout this blog post, the demo plugin will be used as an example.</p>

<h2 id="project">Project</h2>

<p>Before you create your own project, first take a look at the official checklist:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/modules/launcher/new-plugin-checklist.md">New plugin checklist</a></li>
</ul>

<p>Key takeaways from the checklist:</p>

<ul>
  <li>Project name: <code class="language-plaintext highlighter-rouge">Community.PowerToys.Run.Plugin.&lt;PluginName&gt;</code></li>
  <li>Target framework: <code class="language-plaintext highlighter-rouge">net8.0-windows</code></li>
  <li>Create a <code class="language-plaintext highlighter-rouge">Main.cs</code> class</li>
  <li>Create a <code class="language-plaintext highlighter-rouge">plugin.json</code> file</li>
</ul>

<p>In Visual Studio, create a new <a href="https://learn.microsoft.com/en-us/dotnet/core/tutorials/library-with-visual-studio">Class Library</a> project.</p>

<p>The edit the <code class="language-plaintext highlighter-rouge">.csproj</code> file to look something like this:</p>

<script src="https://gist.github.com/hlaueriksson/5484a19def85f618d7a2297628486c80.js?file=Community.PowerToys.Run.Plugin.Demo.csproj"> </script>

<ul>
  <li>Platforms: <code class="language-plaintext highlighter-rouge">x64</code> and <code class="language-plaintext highlighter-rouge">ARM64</code></li>
  <li><code class="language-plaintext highlighter-rouge">UseWPF</code> to include references to WPF assemblies</li>
  <li>Dependencies: PowerToys and Wox <code class="language-plaintext highlighter-rouge">.dll</code> assemblies</li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">.dll</code> files referenced in the <code class="language-plaintext highlighter-rouge">.csproj</code> file are examples of dependencies needed, depending on what features your plugin should support.</p>

<p>Unfortunately, there are no official NuGet packages for these assemblies.</p>

<p>Traditionally, plugin authors commit these <code class="language-plaintext highlighter-rouge">.dll</code> files to the repo in a <code class="language-plaintext highlighter-rouge">libs</code> folder.
Both the <code class="language-plaintext highlighter-rouge">x64</code> and <code class="language-plaintext highlighter-rouge">ARM64</code> versions.</p>

<p>You can copy the DLLs for your platform architecture from the installation location:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">C:\Program Files\PowerToys\</code>
    <ul>
      <li>Machine wide installation of PowerToys</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">%LocalAppData%\PowerToys\</code>
    <ul>
      <li>Per user installation of PowerToys</li>
    </ul>
  </li>
</ul>

<p>You can build the DLLs for the other platform architecture from source:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/tree/main/doc/devdocs#compiling-powertoys">Compiling PowerToys</a></li>
</ul>

<p>Other plugin authors like to resolve the dependencies by referencing the PowerToys projects directly.
Like the approach by Lin Yu-Chieh (Victor):</p>

<ul>
  <li><a href="https://github.com/lin-ycv/EverythingPowerToys/wiki">EverythingPowerToys</a></li>
</ul>

<p>I have created a NuGet package that simplifies referencing all PowerToys Run plugin dependencies:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Dependencies">https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Dependencies</a></li>
</ul>

<p>When using <code class="language-plaintext highlighter-rouge">Community.PowerToys.Run.Plugin.Dependencies</code> the <code class="language-plaintext highlighter-rouge">.csproj</code> file can look like this:</p>

<script src="https://gist.github.com/hlaueriksson/5484a19def85f618d7a2297628486c80.js?file=Community.PowerToys.Run.Plugin.Demo.Dependencies.csproj"> </script>

<p>I have also created <code class="language-plaintext highlighter-rouge">dotnet new</code> templates that simplifies creating PowerToys Run plugin projects and solutions:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Templates">https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Templates</a></li>
</ul>

<p><img src="dotnet-new-templates.png" alt="dotnet new list PowerToys" /></p>

<p>Anyway, it doesn’t matter if you create a project via templates or manually.
The project should start out with these files:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Images\*.png</code>
    <ul>
      <li>Typically dark and light versions of icons</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Main.cs</code>
    <ul>
      <li>The starting point of the plugin logic</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">plugin.json</code>
    <ul>
      <li>The plugin metadata</li>
    </ul>
  </li>
</ul>

<h2 id="metadata">Metadata</h2>

<p>Create a <code class="language-plaintext highlighter-rouge">plugin.json</code> file that looks something like this:</p>

<script src="https://gist.github.com/hlaueriksson/5484a19def85f618d7a2297628486c80.js?file=plugin.json"> </script>

<p>The format is described in the Dev Documentation:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/modules/launcher/new-plugin-checklist.md">New plugin checklist</a></li>
</ul>

<h2 id="main">Main</h2>

<p>Create a <code class="language-plaintext highlighter-rouge">Main.cs</code> file that looks something like this:</p>

<script src="https://gist.github.com/hlaueriksson/5484a19def85f618d7a2297628486c80.js?file=Main.cs"> </script>

<p>The <code class="language-plaintext highlighter-rouge">Main</code> class must have a public, static string property named <code class="language-plaintext highlighter-rouge">PluginID</code>:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="kt">string</span> <span class="n">PluginID</span> <span class="p">=&gt;</span> <span class="s">"AE953C974C2241878F282EA18A7769E4"</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>32 digits <code class="language-plaintext highlighter-rouge">Guid</code> without hyphens</li>
  <li>Must match the value in the <code class="language-plaintext highlighter-rouge">plugin.json</code> file</li>
</ul>

<p>In addition, the <code class="language-plaintext highlighter-rouge">Main</code> class should implement a few interfaces.</p>

<p>Let’s break down the implemented <em>interfaces</em> and the <em>classes</em> used in the example above.</p>

<h2 id="interfaces">Interfaces</h2>

<p>Some interfaces of interest from the <code class="language-plaintext highlighter-rouge">Wox.Plugin</code> assembly:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">IPlugin</code></li>
  <li><code class="language-plaintext highlighter-rouge">IPluginI18n</code></li>
  <li><code class="language-plaintext highlighter-rouge">IDelayedExecutionPlugin</code></li>
  <li><code class="language-plaintext highlighter-rouge">IContextMenu</code></li>
  <li><code class="language-plaintext highlighter-rouge">ISettingProvider</code></li>
</ul>

<h3 id="iplugin">IPlugin</h3>

<p>The most important interface is <code class="language-plaintext highlighter-rouge">IPlugin</code>:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">interface</span> <span class="nc">IPlugin</span>
<span class="p">{</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">Result</span><span class="p">&gt;</span> <span class="nf">Query</span><span class="p">(</span><span class="n">Query</span> <span class="n">query</span><span class="p">);</span>

    <span class="k">void</span> <span class="nf">Init</span><span class="p">(</span><span class="n">PluginInitContext</span> <span class="n">context</span><span class="p">);</span>

    <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>

    <span class="kt">string</span> <span class="n">Description</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Query</code> is the method that does the actual logic in the plugin</li>
  <li><code class="language-plaintext highlighter-rouge">Init</code> is used to initialize the plugin
    <ul>
      <li>Save a reference to the <code class="language-plaintext highlighter-rouge">PluginInitContext</code> for later use</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Name</code> ought to match the value in the <code class="language-plaintext highlighter-rouge">plugin.json</code> file, but can be localized</li>
</ul>

<h3 id="iplugini18n">IPluginI18n</h3>

<p>If you want to support internationalization you can implement the <code class="language-plaintext highlighter-rouge">IPluginI18n</code> interface:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">interface</span> <span class="nc">IPluginI18n</span>
<span class="p">{</span>
    <span class="kt">string</span> <span class="nf">GetTranslatedPluginTitle</span><span class="p">();</span>

    <span class="kt">string</span> <span class="nf">GetTranslatedPluginDescription</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="idelayedexecutionplugin">IDelayedExecutionPlugin</h3>

<p>The <code class="language-plaintext highlighter-rouge">IDelayedExecutionPlugin</code> interface provides an alternative <code class="language-plaintext highlighter-rouge">Query</code> method:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">interface</span> <span class="nc">IDelayedExecutionPlugin</span>
<span class="p">{</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">Result</span><span class="p">&gt;</span> <span class="nf">Query</span><span class="p">(</span><span class="n">Query</span> <span class="n">query</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">delayedExecution</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The delayed execution can be used for queries that take some time to run.
PowerToys Run will add a slight delay before the <code class="language-plaintext highlighter-rouge">Query</code> method is invoked, so that the user has some extra milliseconds to finish typing that command.</p>

<p>A delay can be useful for queries that performs:</p>

<ul>
  <li>I/O operations</li>
  <li>HTTP requests</li>
</ul>

<h3 id="icontextmenu">IContextMenu</h3>

<p>The <code class="language-plaintext highlighter-rouge">IContextMenu</code> interface is used to add context menu buttons to the query results:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">interface</span> <span class="nc">IContextMenu</span>
<span class="p">{</span>
    <span class="n">List</span><span class="p">&lt;</span><span class="n">ContextMenuResult</span><span class="p">&gt;</span> <span class="nf">LoadContextMenus</span><span class="p">(</span><span class="n">Result</span> <span class="n">selectedResult</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li>Every <code class="language-plaintext highlighter-rouge">Result</code> can be enhanced with custom buttons</li>
</ul>

<h3 id="isettingprovider">ISettingProvider</h3>

<p>If the plugin is sophisticated enough to have custom settings, implement the <code class="language-plaintext highlighter-rouge">ISettingProvider</code> interface:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">interface</span> <span class="nc">ISettingProvider</span>
<span class="p">{</span>
    <span class="n">Control</span> <span class="nf">CreateSettingPanel</span><span class="p">();</span>

    <span class="k">void</span> <span class="nf">UpdateSettings</span><span class="p">(</span><span class="n">PowerLauncherPluginSettings</span> <span class="n">settings</span><span class="p">);</span>

    <span class="n">IEnumerable</span><span class="p">&lt;</span><span class="n">PluginAdditionalOption</span><span class="p">&gt;</span> <span class="n">AdditionalOptions</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">CreateSettingPanel</code> usually throw a <code class="language-plaintext highlighter-rouge">NotImplementedException</code></li>
  <li><code class="language-plaintext highlighter-rouge">UpdateSettings</code> is invoked when the user updates the settings in the PowerToys GUI
    <ul>
      <li>Use this method to save the custom settings and update the state of the plugin</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">AdditionalOptions</code> is invoked when the PowerToys GUI displays the settings
    <ul>
      <li>Use this property to define how the custom settings are renderer in the PowerToys GUI</li>
    </ul>
  </li>
</ul>

<h2 id="classes">Classes</h2>

<p>Some classes of interest from the <code class="language-plaintext highlighter-rouge">Wox.Plugin</code> assembly:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">PluginInitContext</code></li>
  <li><code class="language-plaintext highlighter-rouge">Query</code></li>
  <li><code class="language-plaintext highlighter-rouge">Result</code></li>
  <li><code class="language-plaintext highlighter-rouge">ContextMenuResult</code></li>
</ul>

<h3 id="plugininitcontext">PluginInitContext</h3>

<p>A <code class="language-plaintext highlighter-rouge">PluginInitContext</code> instance is passed as argument to the <code class="language-plaintext highlighter-rouge">Init</code> method:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">class</span> <span class="nc">PluginInitContext</span>
<span class="p">{</span>
    <span class="k">public</span> <span class="n">PluginMetadata</span> <span class="n">CurrentPluginMetadata</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">internal</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>

    <span class="k">public</span> <span class="n">IPublicAPI</span> <span class="n">API</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">PluginMetadata</code> can be useful if you need the path to the <code class="language-plaintext highlighter-rouge">PluginDirectory</code> or the <code class="language-plaintext highlighter-rouge">ActionKeyword</code> of the plugin</li>
  <li><code class="language-plaintext highlighter-rouge">IPublicAPI</code> is mainly used to <code class="language-plaintext highlighter-rouge">GetCurrentTheme</code>, but can also <code class="language-plaintext highlighter-rouge">ShowMsg</code>, <code class="language-plaintext highlighter-rouge">ShowNotification</code> or <code class="language-plaintext highlighter-rouge">ChangeQuery</code></li>
</ul>

<h3 id="query">Query</h3>

<p>A <code class="language-plaintext highlighter-rouge">Query</code> instance is passed to the <code class="language-plaintext highlighter-rouge">Query</code> methods defined in the <code class="language-plaintext highlighter-rouge">IPlugin</code> and <code class="language-plaintext highlighter-rouge">IDelayedExecutionPlugin</code> interfaces.</p>

<p>Properties of interest:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Search</code> returns what the user has searched for, excluding the action keyword.</li>
  <li><code class="language-plaintext highlighter-rouge">Terms</code> returns the search as a collection of substrings, split by space (<code class="language-plaintext highlighter-rouge">" "</code>)</li>
</ul>

<h3 id="result">Result</h3>

<p>A list of <code class="language-plaintext highlighter-rouge">Result</code> objects are returned by the <code class="language-plaintext highlighter-rouge">Query</code> methods defined in the <code class="language-plaintext highlighter-rouge">IPlugin</code> and <code class="language-plaintext highlighter-rouge">IDelayedExecutionPlugin</code> interfaces.</p>

<p>Example of how to create a new result:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="n">Result</span>
<span class="p">{</span>
    <span class="n">QueryTextDisplay</span> <span class="p">=</span> <span class="n">query</span><span class="p">.</span><span class="n">Search</span><span class="p">,</span> <span class="c1">// displayed where the user types queries</span>
    <span class="n">IcoPath</span> <span class="p">=</span> <span class="n">IconPath</span><span class="p">,</span> <span class="c1">// displayed on the left side</span>
    <span class="n">Title</span> <span class="p">=</span> <span class="s">"A title displayed in the top of the result"</span><span class="p">,</span>
    <span class="n">SubTitle</span> <span class="p">=</span> <span class="s">"A subtitle displayed under the main title"</span><span class="p">,</span>
    <span class="n">ToolTipData</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ToolTipData</span><span class="p">(</span><span class="s">"A tooltip title"</span><span class="p">,</span> <span class="s">"A tooltip text\nthat can have\nmultiple lines"</span><span class="p">),</span>
    <span class="n">Action</span> <span class="p">=</span> <span class="n">_</span> <span class="p">=&gt;</span>
    <span class="p">{</span>
        <span class="n">Log</span><span class="p">.</span><span class="nf">Debug</span><span class="p">(</span><span class="s">"The actual action of the result when pressing Enter."</span><span class="p">,</span> <span class="nf">GetType</span><span class="p">());</span>
        <span class="cm">/*
        For example:
        - Copy something to the clipboard
        - Open a URL in a browser
        */</span>
    <span class="p">},</span>
    <span class="n">Score</span> <span class="p">=</span> <span class="m">1</span><span class="p">,</span> <span class="c1">// the higher, the better query match</span>
    <span class="n">ContextData</span> <span class="p">=</span> <span class="n">someObject</span><span class="p">,</span> <span class="c1">// used together with the IContextMenu interface</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="contextmenuresult">ContextMenuResult</h3>

<p>A list of <code class="language-plaintext highlighter-rouge">ContextMenuResult</code> objects are returned by the <code class="language-plaintext highlighter-rouge">LoadContextMenus</code> method defined in the <code class="language-plaintext highlighter-rouge">IContextMenu</code> interface.
These objects are rendered as small buttons, displayed on the right side of the query result.</p>

<p>Example of how to create a new context menu result:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="n">ContextMenuResult</span>
<span class="p">{</span>
    <span class="n">PluginName</span> <span class="p">=</span> <span class="n">Name</span><span class="p">,</span>
    <span class="n">Title</span> <span class="p">=</span> <span class="s">"A title displayed as a tooltip"</span><span class="p">,</span>
    <span class="n">FontFamily</span> <span class="p">=</span> <span class="s">"Segoe Fluent Icons,Segoe MDL2 Assets"</span><span class="p">,</span>
    <span class="n">Glyph</span> <span class="p">=</span> <span class="s">"\xE8C8"</span><span class="p">,</span> <span class="c1">// Copy</span>
    <span class="n">AcceleratorKey</span> <span class="p">=</span> <span class="n">Key</span><span class="p">.</span><span class="n">C</span><span class="p">,</span>
    <span class="n">AcceleratorModifiers</span> <span class="p">=</span> <span class="n">ModifierKeys</span><span class="p">.</span><span class="n">Control</span><span class="p">,</span>
    <span class="n">Action</span> <span class="p">=</span> <span class="n">_</span> <span class="p">=&gt;</span>
    <span class="p">{</span>
        <span class="n">Log</span><span class="p">.</span><span class="nf">Debug</span><span class="p">(</span><span class="s">"The actual action of the context menu result, when clicking the button or pressing the keyboard shortcut."</span><span class="p">,</span> <span class="nf">GetType</span><span class="p">());</span>
        <span class="cm">/*
        For example:
        - Copy something to the clipboard
        - Open a URL in a browser
        */</span>
    <span class="p">},</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Find the perfect <code class="language-plaintext highlighter-rouge">Glyph</code> to use from:</p>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/windows/apps/design/style/segoe-fluent-icons-font">Segoe Fluent Icons font</a></li>
  <li><a href="https://learn.microsoft.com/en-us/windows/apps/design/style/segoe-ui-symbol-font">Segoe MDL2 Assets icons</a></li>
</ul>

<h2 id="actions">Actions</h2>

<p>Examples of actions to use with <code class="language-plaintext highlighter-rouge">Result</code> or <code class="language-plaintext highlighter-rouge">ContextMenuResult</code>:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Action</span> <span class="p">=</span> <span class="n">_</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="n">System</span><span class="p">.</span><span class="n">Windows</span><span class="p">.</span><span class="n">Clipboard</span><span class="p">.</span><span class="nf">SetText</span><span class="p">(</span><span class="s">"Some text to copy to the clipboard"</span><span class="p">);</span>
    <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Action</span> <span class="p">=</span> <span class="n">_</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="kt">var</span> <span class="n">url</span> <span class="p">=</span> <span class="s">"https://conductofcode.io/"</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(!</span><span class="n">Helper</span><span class="p">.</span><span class="nf">OpenCommandInShell</span><span class="p">(</span><span class="n">DefaultBrowserInfo</span><span class="p">.</span><span class="n">Path</span><span class="p">,</span> <span class="n">DefaultBrowserInfo</span><span class="p">.</span><span class="n">ArgumentsPattern</span><span class="p">,</span> <span class="n">url</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="n">Log</span><span class="p">.</span><span class="nf">Error</span><span class="p">(</span><span class="s">"Open default browser failed."</span><span class="p">,</span> <span class="nf">GetType</span><span class="p">());</span>
        <span class="n">Context</span><span class="p">?.</span><span class="n">API</span><span class="p">.</span><span class="nf">ShowMsg</span><span class="p">(</span><span class="s">$"Plugin: </span><span class="p">{</span><span class="n">Name</span><span class="p">}</span><span class="s">"</span><span class="p">,</span> <span class="s">"Open default browser failed."</span><span class="p">);</span>
        <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="logging">Logging</h2>

<p>Logging is done with the static <code class="language-plaintext highlighter-rouge">Log</code> class, from the <code class="language-plaintext highlighter-rouge">Wox.Plugin.Logger</code> namespace.
Under the hood, <code class="language-plaintext highlighter-rouge">NLog</code> is used.</p>

<p>Five log levels:</p>

<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Log</span><span class="p">.</span><span class="nf">Debug</span><span class="p">(</span><span class="s">"A debug message"</span><span class="p">,</span> <span class="nf">GetType</span><span class="p">());</span>
<span class="n">Log</span><span class="p">.</span><span class="nf">Info</span><span class="p">(</span><span class="s">"An information message"</span><span class="p">,</span> <span class="nf">GetType</span><span class="p">());</span>
<span class="n">Log</span><span class="p">.</span><span class="nf">Warn</span><span class="p">(</span><span class="s">"A warning message"</span><span class="p">,</span> <span class="nf">GetType</span><span class="p">());</span>
<span class="n">Log</span><span class="p">.</span><span class="nf">Error</span><span class="p">(</span><span class="s">"An error message"</span><span class="p">,</span> <span class="nf">GetType</span><span class="p">());</span>
<span class="n">Log</span><span class="p">.</span><span class="nf">Exception</span><span class="p">(</span><span class="s">"An exceptional message"</span><span class="p">,</span> <span class="k">new</span> <span class="nf">Exception</span><span class="p">(),</span> <span class="nf">GetType</span><span class="p">());</span>
</code></pre></div></div>

<p>The logs are written to <code class="language-plaintext highlighter-rouge">.txt</code> files, rolled by date, at:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">%LocalAppData%\Microsoft\PowerToys\PowerToys Run\Logs\&lt;Version&gt;\</code></li>
</ul>

<h2 id="dependencies">Dependencies</h2>

<p>If you have the need to add third party dependencies, take a look at what is already used by PowerToys.</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/blob/main/Directory.Packages.props">Directory.Packages.props</a></li>
</ul>

<p>NuGet packages and the versions specified in the <code class="language-plaintext highlighter-rouge">.props</code> file are candidates to reference in your own <code class="language-plaintext highlighter-rouge">.csproj</code> file.</p>

<p>Packages of interest:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">LazyCache</code></li>
  <li><code class="language-plaintext highlighter-rouge">System.Text.Json</code></li>
</ul>

<p>If the plugin uses any third party dependencies that are not referenced by PowerToys Run, you need to enable <code class="language-plaintext highlighter-rouge">DynamicLoading</code>.</p>

<p>In the <code class="language-plaintext highlighter-rouge">plugin.json</code> file:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="err">//</span><span class="w"> </span><span class="err">...</span><span class="w">
    </span><span class="nl">"DynamicLoading"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">true</code> makes PowerToys Run dynamically load any <code class="language-plaintext highlighter-rouge">.dll</code> files in the plugin folder</li>
</ul>

<h2 id="tests">Tests</h2>

<p>You can write unit tests for your plugin.
The official plugins use the <a href="https://github.com/microsoft/testfx">MSTest</a> framework and <code class="language-plaintext highlighter-rouge">Moq</code> for mocking.</p>

<ul>
  <li>Project name: <code class="language-plaintext highlighter-rouge">Community.PowerToys.Run.Plugin.&lt;PluginName&gt;.UnitTests</code></li>
  <li>Target framework: <code class="language-plaintext highlighter-rouge">net8.0-windows</code></li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">.csproj</code> file of a unit test project may look something like this:</p>

<script src="https://gist.github.com/hlaueriksson/5484a19def85f618d7a2297628486c80.js?file=Community.PowerToys.Run.Plugin.Demo.UnitTests.csproj"> </script>

<ul>
  <li>Apart from the actual test assemblies, some package references are also needed</li>
  <li>As well as references to PowerToys and Wox <code class="language-plaintext highlighter-rouge">.dll</code> assemblies</li>
</ul>

<p>Unit tests of the <code class="language-plaintext highlighter-rouge">Main</code> class may look something like this:</p>

<script src="https://gist.github.com/hlaueriksson/5484a19def85f618d7a2297628486c80.js?file=MainTests.cs"> </script>

<p>Some of the official plugins have unit test coverage:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Plugins">https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Plugins</a></li>
</ul>

<h2 id="distribution">Distribution</h2>

<p>Unfortunately, the plugin manager in PowerToys Run does not offer support for downloading new plugins.</p>

<p>Community plugins are traditionally packaged in <code class="language-plaintext highlighter-rouge">.zip</code> files and distributed via releases in GitHub repositories.</p>

<p>The process is described in a unofficial checklist:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/awesome-powertoys-run-plugins/blob/main/checklist.md">Community plugin checklist</a></li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">Everything</code> plugin by Lin Yu-Chieh (Victor) is next level and is <a href="https://github.com/lin-ycv/EverythingPowerToys/releases">distributed</a> via:</p>

<ul>
  <li>Self-Extraction Installer (EXE)</li>
  <li>Manual Installation (ZIP)</li>
  <li>WinGet</li>
  <li>Chocolatey</li>
</ul>

<h2 id="linting">Linting</h2>

<p>I have created a linter for PowerToys Run community plugins:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Lint">https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Lint</a></li>
</ul>

<p><img src="ptrun-lint.png" alt="ptrun-lint" /></p>

<p>When running the linter on your plugin any issues are reported with a code and a description.
If nothing shows up, your plugin is awesome.
The lint rules are codified from the guidelines in the <a href="https://github.com/hlaueriksson/awesome-powertoys-run-plugins/blob/main/checklist.md">Community plugin checklist</a>.</p>

<h2 id="resources">Resources</h2>

<p>Demo Plugin:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/ConductOfCode/tree/master/PowerToysRun">https://github.com/hlaueriksson/ConductOfCode/tree/master/PowerToysRun</a></li>
</ul>

<p>Awesome PowerToys Run Plugins:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/awesome-powertoys-run-plugins">https://github.com/hlaueriksson/awesome-powertoys-run-plugins</a></li>
</ul>

<p>Third-Party plugins for PowerToy Run:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/blob/main/doc/thirdPartyRunPlugins.md">https://github.com/microsoft/PowerToys/blob/main/doc/thirdPartyRunPlugins.md</a></li>
</ul>

<p><code class="language-plaintext highlighter-rouge">dotnet new</code> templates for community plugins:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Templates">https://github.com/hlaueriksson/Community.PowerToys.Run.Plugin.Templates</a></li>
</ul>

<p>Documentation:</p>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/windows/powertoys/run">https://learn.microsoft.com/en-us/windows/powertoys/run</a></li>
</ul>

<p>Dev Documentation:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/tree/main/doc/devdocs/modules/launcher">https://github.com/microsoft/PowerToys/tree/main/doc/devdocs/modules/launcher</a></li>
</ul>

<p>If you want to look under the hood, fork or clone the PowerToys repo:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys">https://github.com/microsoft/PowerToys</a></li>
</ul>

<p>Get the solution to build on your machine with the help of the documentation:</p>

<ul>
  <li><a href="https://github.com/microsoft/PowerToys/tree/main/doc/devdocs#compiling-powertoys">Compiling PowerToys</a></li>
</ul>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="PowerToys" /><category term="Plugins" /><category term="C#" /><summary type="html"><![CDATA[A step by step guide on how to create community plugins for PowerToys Run]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/creating-custom-powertoys-run-plugins/vs.png" /><media:content medium="image" url="https://conductofcode.io/post/creating-custom-powertoys-run-plugins/vs.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Retry flaky tests with dotnet test and PowerShell</title><link href="https://conductofcode.io/post/retry-flaky-tests-with-dotnet-test-and-powershell/" rel="alternate" type="text/html" title="Retry flaky tests with dotnet test and PowerShell" /><published>2023-03-26T21:00:00+02:00</published><updated>2023-03-26T21:00:00+02:00</updated><id>https://conductofcode.io/post/retry-flaky-tests-with-dotnet-test-and-powershell</id><content type="html" xml:base="https://conductofcode.io/post/retry-flaky-tests-with-dotnet-test-and-powershell/"><![CDATA[<p>At my current client, <a href="https://career.nordicleisuretravelgroup.com">Nordic Leisure Travel Group</a> , we have a large number of web tests that automates some of the QA effort.
The tests are written in <a href="https://www.selenium.dev">Selenium</a> and <a href="https://playwright.dev">Playwright</a>.
They run on a schedule in <a href="https://www.jenkins.io">Jenkins</a> and we get reports on email.
They take quite some time to run.
Unfortunately some of the tests are a bit flaky and it is hard to make them stable.</p>

<p>Therefore I set out trying to mitigate failed test runs by rerunning the failing tests.</p>

<p>A question/answer on <a href="https://stackoverflow.com/q/61330768">Stack Overflow</a> inspired me to write my own test script.</p>

<p>My requirements were:</p>
<ul>
  <li>Use PowerShell</li>
  <li>Use the <code class="language-plaintext highlighter-rouge">dotnet test</code> CLI command</li>
  <li>Keep track of failing tests and retry them</li>
  <li>Notify the test framework of the current retry iteration</li>
  <li>Make it possible to accept a certain percentage of failing tests</li>
  <li>Output the test result in a coherent way</li>
</ul>

<p>This resulted in the following script:</p>

<ul>
  <li>GitHub: <a href="https://github.com/hlaueriksson/ConductOfCode/blob/master/TestRerun/test.ps1">test.ps1</a></li>
  <li>PowerShell Gallery: <a href="https://www.powershellgallery.com/packages/test-rerun">https://www.powershellgallery.com/packages/test-rerun</a></li>
</ul>

<script src="https://gist.github.com/hlaueriksson/cde2d0fffc08935faaf7d9a58d910c3d.js?file=test.ps1"> </script>

<p>The script runs <code class="language-plaintext highlighter-rouge">dotnet test</code> and uses the trx logger result file to collect failed tests.
Then reruns the failed tests and reports the final result.</p>

<h2 id="parameters">Parameters</h2>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Path</code> - Path to the: project | solution | directory | dll | exe
    <ul>
      <li>Default value: <code class="language-plaintext highlighter-rouge">.</code> (current directory)</li>
      <li>More info: <a href="https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test#arguments">dotnet test arguments</a></li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Configuration</code> - Build configuration for environment specific <code class="language-plaintext highlighter-rouge">appsettings.json</code> file.
    <ul>
      <li>Default value: <code class="language-plaintext highlighter-rouge">Debug</code></li>
      <li>Valid values: <code class="language-plaintext highlighter-rouge">Debug</code> | <code class="language-plaintext highlighter-rouge">Release</code> | <code class="language-plaintext highlighter-rouge">Development</code> | <code class="language-plaintext highlighter-rouge">Production</code></li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Filter</code> - Filter to run selected tests based on: TestCategory | Priority | Name | FullyQualifiedName
    <ul>
      <li>More info: <a href="https://learn.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests">Run selected unit tests</a></li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Settings</code> - Path to the <code class="language-plaintext highlighter-rouge">.runsettings</code> file.
    <ul>
      <li>More info: <a href="https://learn.microsoft.com/en-us/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file">Configure unit tests by using a .runsettings file</a></li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Retries</code> - Number of retries for each failed test.
    <ul>
      <li>Default value: <code class="language-plaintext highlighter-rouge">2</code></li>
      <li>Valid range: <code class="language-plaintext highlighter-rouge">1-9</code></li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Percentage</code> - Required percentage of passed tests.
    <ul>
      <li>Default value: <code class="language-plaintext highlighter-rouge">100</code></li>
      <li>Valid range: <code class="language-plaintext highlighter-rouge">0-100</code></li>
    </ul>
  </li>
</ul>

<h2 id="examples">Examples</h2>

<p>Run regression tests:</p>

<pre><code class="language-ps1">.\test.ps1 -filter "TestCategory=RegressionTest"
</code></pre>

<p>Run FooBar smoke tests in Development:</p>

<pre><code class="language-ps1">.\test.ps1 .\FooBar.Tests\FooBar.Tests.csproj -filter "TestCategory=SmokeTest" -configuration "Development"
</code></pre>

<p>Retry failed tests once and reports the run as green if 95% of the tests passed:</p>

<pre><code class="language-ps1">.\test.ps1 -retries 1 -percentage 95
</code></pre>

<p>Run tests configured with a <code class="language-plaintext highlighter-rouge">.runsettings</code> file:</p>

<pre><code class="language-ps1">.\test.ps1 -settings .\test.runsettings
</code></pre>

<h2 id="output">Output</h2>

<p>If the tests passed, or the required percentage of tests passed, the script returns the exitcode <code class="language-plaintext highlighter-rouge">0</code>.
Otherwise the number of failed tests is returned as exitcode.</p>

<p>Output when successful:</p>

<p><img src="successful.png" alt="Test Rerun Successful." /></p>

<p>Output when required percentage of tests passed:</p>

<p><img src="successful2.png" alt="Test Rerun Successful." /></p>

<p>Output when failed:</p>

<p><img src="failed.png" alt="Test Rerun Failed." /></p>

<p>Showcase:</p>

<p><img src="test.ps1.gif" alt=".\test.ps1 -filter FullyQualifiedName=ConductOfCode.NUnitTests" /></p>

<h2 id="tests">Tests</h2>

<p>To showcase the test script I have written some tests in three popular frameworks.</p>

<p>The script and tests are available in this repo:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/ConductOfCode/tree/master/TestRerun">https://github.com/hlaueriksson/ConductOfCode/tree/master/TestRerun</a></li>
</ul>

<h3 id="nunit">NUnit</h3>

<script src="https://gist.github.com/hlaueriksson/cde2d0fffc08935faaf7d9a58d910c3d.js?file=NUnitTests.cs"> </script>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">Category</code> attribute corresponds to the <code class="language-plaintext highlighter-rouge">TestCategory</code> filter in the script.</li>
  <li>The <code class="language-plaintext highlighter-rouge">Retry</code> parameter in the <code class="language-plaintext highlighter-rouge">TestContext</code> contains the current retry iteration.</li>
</ul>

<h3 id="mstest">MSTest</h3>

<script src="https://gist.github.com/hlaueriksson/cde2d0fffc08935faaf7d9a58d910c3d.js?file=MSTestTests.cs"> </script>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">TestCategory</code> attribute corresponds to the <code class="language-plaintext highlighter-rouge">TestCategory</code> filter in the script.</li>
  <li>The <code class="language-plaintext highlighter-rouge">Retry</code> property in the <code class="language-plaintext highlighter-rouge">TestContext</code> contains the current retry iteration.</li>
</ul>

<h3 id="xunit">XUnit</h3>

<script src="https://gist.github.com/hlaueriksson/cde2d0fffc08935faaf7d9a58d910c3d.js?file=XUnitTests.cs"> </script>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">Trait</code> attribute and <code class="language-plaintext highlighter-rouge">TestCategory</code> parameter corresponds to the <code class="language-plaintext highlighter-rouge">TestCategory</code> filter in the script.</li>
  <li><a href="https://stackoverflow.com/a/55419149">XUnit does not support accessing TestRunParameters</a>, so the current retry iteration is not available in this test framework.</li>
</ul>

<h3 id="playwright">Playwright</h3>

<blockquote>
  <p>Playwright enables reliable end-to-end testing for modern web apps.</p>
</blockquote>

<p>Web testing might be hard to get right and flaky tests can benefit from being retried.</p>

<p>Here is an example with <a href="https://playwright.dev/dotnet/">Playwright</a> and NUnit:</p>

<script src="https://gist.github.com/hlaueriksson/cde2d0fffc08935faaf7d9a58d910c3d.js?file=PlaywrightTests.cs"> </script>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">SetUp</code> method starts a trace recording if the test is in retry mode.</li>
  <li>The <code class="language-plaintext highlighter-rouge">TearDown</code> method exports the trace into a zip archive if the test failed.</li>
</ul>

<p>The trace zip archives of failing tests can be examined at:</p>

<ul>
  <li><a href="https://trace.playwright.dev">https://trace.playwright.dev</a></li>
</ul>

<p>A <code class="language-plaintext highlighter-rouge">.runsettings</code> file can be used to customizing Playwright options:</p>

<script src="https://gist.github.com/hlaueriksson/cde2d0fffc08935faaf7d9a58d910c3d.js?file=test.runsettings"> </script>

<ul>
  <li>More info: <a href="https://playwright.dev/dotnet/docs/test-runners#using-the-runsettings-file">Using the .runsettings file</a></li>
</ul>

<p>Run the Playwright tests with the <code class="language-plaintext highlighter-rouge">.runsettings</code> file:</p>

<pre><code class="language-ps1">.\test.ps1 -filter FullyQualifiedName=ConductOfCode.PlaywrightTests -settings .\test.runsettings
</code></pre>

<h2 id="resources">Resources</h2>

<ul>
  <li>The test script and examples in this blog post: <a href="https://github.com/hlaueriksson/ConductOfCode/tree/master/TestRerun">GitHub</a></li>
  <li>The test script: <a href="https://www.powershellgallery.com/packages/test-rerun">PowerShell Gallery</a></li>
</ul>

<p>If you use Azure Pipelines consider using the Visual Studio Test v2 task with the <code class="language-plaintext highlighter-rouge">rerunFailedTests</code> option:</p>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/vstest-v2">VSTest@2</a></li>
</ul>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="NUnit" /><category term="MSTest" /><category term="xUnit" /><category term="Testing" /><category term="C#" /><summary type="html"><![CDATA[Introducing test.ps1, a script for running flaky tests - Keeps track of failing tests and retries them - Notifies the test framework of the current retry iteration - Makes it possible to accept a certain percentage of failing tests - Outputs the test result in a coherent way]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/retry-flaky-tests-with-dotnet-test-and-powershell/terminal.png" /><media:content medium="image" url="https://conductofcode.io/post/retry-flaky-tests-with-dotnet-test-and-powershell/terminal.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing LoFuUnit</title><link href="https://conductofcode.io/post/introducing-lofuunit/" rel="alternate" type="text/html" title="Introducing LoFuUnit" /><published>2019-12-29T20:00:00+01:00</published><updated>2019-12-29T20:00:00+01:00</updated><id>https://conductofcode.io/post/introducing-lofuunit</id><content type="html" xml:base="https://conductofcode.io/post/introducing-lofuunit/"><![CDATA[<p>About a year ago I was experimenting with <em>local functions</em> and <em>reflection</em>, to improve my unit tests and the way to write BDD specs.
I had been using <a href="https://github.com/machine/machine.specifications">Machine.Specifications</a> and <a href="https://github.com/machine/machine.specifications.fakes">Machine.Fakes</a> for years.
MSpec has served me well, but the lack of <a href="https://github.com/machine/machine.specifications/issues/293">async support</a> made me look for alternatives.</p>

<p>The experiment with local functions in tests led to the release of LoFuUnit:</p>

<ul>
  <li>NuGet: <a href="https://www.nuget.org/packages?q=owners%3Ahlaueriksson+title%3ALoFuUnit">https://www.nuget.org/packages?q=owners%3Ahlaueriksson+title%3ALoFuUnit</a></li>
  <li>GitHub: <a href="https://github.com/hlaueriksson/LoFuUnit">https://github.com/hlaueriksson/LoFuUnit</a></li>
</ul>

<blockquote>
  <p>Testing with <strong>Lo</strong>cal <strong>Fu</strong>nctions 🐯</p>

  <p>in .NET / C# ⚙️</p>

  <p>with your favorite <strong>Unit</strong> Testing Framework ✔️</p>
</blockquote>

<p>Recently I published version <code class="language-plaintext highlighter-rouge">1.1.1</code> of LoFuUnit, so I thought it would be a good time to introduce the framework to you in the form of a blog post.</p>

<h2 id="tests">Tests</h2>

<p>Let’s try LoFuUnit and see how tests are written. I’ll use the same challenge from a previous blog post about <a href="/post/bdd-frameworks-for-dotnet-csharp/">BDD frameworks for .NET / C#</a>:</p>

<p><strong>The subject</strong></p>

<p>The stack, a last-in-first-out (LIFO) collection:</p>

<ul>
  <li><a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.stack-1"><code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code></a></li>
</ul>

<p>The tests will assert the behavior of:</p>

<ul>
  <li>Empty vs nonempty stack</li>
  <li><code class="language-plaintext highlighter-rouge">Peek()</code> and <code class="language-plaintext highlighter-rouge">Pop()</code> methods</li>
  <li><code class="language-plaintext highlighter-rouge">InvalidOperationException</code></li>
</ul>

<p><img src="Stack.png" alt="Stack" /></p>

<p>Tests with <a href="https://www.nuget.org/packages/LoFuUnit.NUnit/">LoFuUnit.NUnit</a>:</p>

<script src="https://gist.github.com/hlaueriksson/79f1dc868fbfc11c65cb8e33d58c0490.js?file=StackTests.cs"> </script>

<ul>
  <li><code class="language-plaintext highlighter-rouge">LoFuUnit.NUnit</code> provides the <code class="language-plaintext highlighter-rouge">[LoFu]</code> attribute, apply it to your test methods</li>
  <li>Write the test steps in local functions, they are implicitly invoked by the <code class="language-plaintext highlighter-rouge">[LoFu]</code> attribute</li>
  <li>Think about the naming of test methods and test functions, it will determine the test output</li>
</ul>

<p>Test output:</p>

<p><img src="result1.png" alt="Unit Test Sessions" /></p>

<p><img src="result2.png" alt="Unit Test Sessions" /></p>

<h2 id="auto-mocks">Auto Mocks</h2>

<blockquote>
  <p>Mocking is nice, automocking is even better</p>
</blockquote>

<p>Auto-mocking is part of LoFuUnit.
Let’s see how auto-mocked tests are written. I’ll use the same challenge from a previous blog post about <a href="/post/automocked-base-class-for-nunit-tests/">Automocked base class for NUnit tests</a>:</p>

<p>The subject:</p>

<script src="https://gist.github.com/hlaueriksson/79f1dc868fbfc11c65cb8e33d58c0490.js?file=HelloWorld.cs"> </script>

<p>Auto-mocked tests with <a href="https://www.nuget.org/packages/LoFuUnit.AutoNSubstitute/">LoFuUnit.AutoNSubstitute</a> and <a href="https://www.nuget.org/packages/LoFuUnit.NUnit/">LoFuUnit.NUnit</a>:</p>

<script src="https://gist.github.com/hlaueriksson/79f1dc868fbfc11c65cb8e33d58c0490.js?file=HelloWorldTests.cs"> </script>

<ul>
  <li><code class="language-plaintext highlighter-rouge">LoFuUnit.AutoNSubstitute</code> provides the base class <code class="language-plaintext highlighter-rouge">LoFuTest&lt;TSubject&gt;</code>, inherit your test fixtures from it</li>
  <li>The <code class="language-plaintext highlighter-rouge">Use&lt;TDependency&gt;()</code> methods gives you the ability to setup the mocks</li>
  <li>The <code class="language-plaintext highlighter-rouge">The&lt;TDependency&gt;()</code> method lets you access the mocks and verify expectations</li>
</ul>

<p>Test output:</p>

<p><img src="result3.png" alt="Unit Test Sessions" /></p>

<h2 id="installation">Installation</h2>

<p>LoFuUnit is distributed as <a href="https://www.nuget.org/packages?q=owners%3Ahlaueriksson+title%3ALoFuUnit">7 packages</a> via NuGet.
The code examples in this blog post used two of them.</p>

<p><code class="language-plaintext highlighter-rouge">LoFuUnit.NUnit</code>:</p>

<iframe src="https://nuget-install-tabs.azurewebsites.net/api/LoFuUnit.NUnit" style="border-style:none; width:750px; height:112px;"></iframe>

<p><code class="language-plaintext highlighter-rouge">LoFuUnit.AutoNSubstitute</code>:</p>

<iframe src="https://nuget-install-tabs.azurewebsites.net/api/LoFuUnit.AutoNSubstitute" style="border-style:none; width:750px; height:112px;"></iframe>

<p>You can view the code examples from this blog post at <a href="https://github.com/hlaueriksson/ConductOfCode">https://github.com/hlaueriksson/ConductOfCode</a></p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="BDD" /><category term="Testing" /><category term="C#" /><summary type="html"><![CDATA[Testing with Local Functions in .NET / C# with your favorite Unit Testing Framework]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/introducing-lofuunit/LoFuUnit.png" /><media:content medium="image" url="https://conductofcode.io/post/introducing-lofuunit/LoFuUnit.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing Jekyll URL Shortener</title><link href="https://conductofcode.io/post/introducing-jekyll-url-shortener/" rel="alternate" type="text/html" title="Introducing Jekyll URL Shortener" /><published>2018-11-01T07:00:00+01:00</published><updated>2018-11-29T19:00:00+01:00</updated><id>https://conductofcode.io/post/introducing-jekyll-url-shortener</id><content type="html" xml:base="https://conductofcode.io/post/introducing-jekyll-url-shortener/"><![CDATA[<p>I felt the need to create my own URL Shortener. I ended up with a template repository for making URL Shorteners with Jekyll and GitHub Pages.</p>

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Introducing Jekyll URL Shortener - A template repository for making URL Shorteners with <a href="https://twitter.com/hashtag/Jekyll?src=hash&amp;ref_src=twsrc%5Etfw">#Jekyll</a> and <a href="https://twitter.com/hashtag/GitHubPages?src=hash&amp;ref_src=twsrc%5Etfw">#GitHubPages</a><a href="https://t.co/u9iutTiG2O">https://t.co/u9iutTiG2O</a><a href="https://twitter.com/jekyllrb?ref_src=twsrc%5Etfw">@jekyllrb</a> <a href="https://twitter.com/github?ref_src=twsrc%5Etfw">@github</a></p>&mdash; Henrik Lau Eriksson (@hlaueriksson) <a href="https://twitter.com/hlaueriksson/status/1058097835206496256?ref_src=twsrc%5Etfw">November 1, 2018</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>The source code and documentation can be found here:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/jekyll-url-shortener">https://github.com/hlaueriksson/jekyll-url-shortener</a></li>
</ul>

<h2 id="what">What?</h2>

<blockquote>
  <p><a href="https://en.wikipedia.org/wiki/URL_shortening">URL shortening</a> is a technique on the World Wide Web in which a Uniform Resource Locator (URL) may be made substantially shorter and still direct to the required page.</p>
</blockquote>

<p>The <a href="https://github.com/hlaueriksson/jekyll-url-shortener">Jekyll URL Shortener</a> repository is a template for creating your very own URL Shortener:</p>

<blockquote>
  <p>✂️🔗 This is a template repository for making URL Shorteners with Jekyll and GitHub Pages. Create short URLs that can be easily shared, tweeted, or emailed to friends. Fork this repo to get started.</p>
</blockquote>

<h2 id="how">How?</h2>

<p>To create your own URL Shortener, do this:</p>

<ol>
  <li>Buy and configure a (short) domain name</li>
  <li>Fork or clone the <a href="https://github.com/hlaueriksson/jekyll-url-shortener">Jekyll URL Shortener</a> repository</li>
  <li>Configure the repository and code to your liking</li>
  <li>Create short links with Jekyll pages</li>
</ol>

<p>Here follows a description of how I created my own URL Shortener…</p>

<h3 id="1-domain-name">1. Domain Name</h3>

<p>I bought the domain name <a href="https://hlaueriksson.me"><code class="language-plaintext highlighter-rouge">hlaueriksson.me</code></a> from a Swedish <em>domain name registrar</em>.
I will use this as an <em>apex domain</em>, so I configured <code class="language-plaintext highlighter-rouge">A</code> records with my DNS provider:</p>

<p><img src="dns.png" alt="DNS" /></p>

<h3 id="2-fork--clone">2. Fork / Clone</h3>

<p>I cloned the <a href="https://github.com/hlaueriksson/jekyll-url-shortener">Jekyll URL Shortener</a> repository to <a href="https://github.com/hlaueriksson/hlaueriksson.me">https://github.com/hlaueriksson/hlaueriksson.me</a></p>

<h3 id="3-configure">3. Configure</h3>

<p>The <code class="language-plaintext highlighter-rouge">_config.yml</code> file, located in the root of the repository, contains configuration for Jekyll.</p>

<p>I modified this file to fit my needs:</p>

<script src="https://gist.github.com/hlaueriksson/0c605458ec7f2a107773484a697f3023.js?file=_config.yml"> </script>

<p>The <code class="language-plaintext highlighter-rouge">Settings</code> / <code class="language-plaintext highlighter-rouge">GitHub Pages</code> of the repository provides configuration for hosting the Jekyll site.</p>

<p>I modified these settings to fit my needs:</p>

<p><img src="github-pages.png" alt="GitHub Pages" /></p>

<h3 id="4-short-links">4. Short Links</h3>

<p>Short links are created as Jekyll pages in the root of the repository:</p>

<script src="https://gist.github.com/hlaueriksson/0c605458ec7f2a107773484a697f3023.js?file=repo.md_"> </script>

<ul>
  <li>Redirects from <a href="https://hlaueriksson.me/repo/">https://hlaueriksson.me/repo/</a> to <a href="https://github.com/hlaueriksson/hlaueriksson.me">https://github.com/hlaueriksson/hlaueriksson.me</a></li>
</ul>

<script src="https://gist.github.com/hlaueriksson/0c605458ec7f2a107773484a697f3023.js?file=jekyll-url-shortener.md_"> </script>

<ul>
  <li>Redirects from <a href="https://hlaueriksson.me/✂️🔗/">https://hlaueriksson.me/✂️🔗/</a> to <a href="https://hlaueriksson.github.io/jekyll-url-shortener/">https://hlaueriksson.github.io/jekyll-url-shortener/</a></li>
</ul>

<h2 id="why">Why?</h2>

<p>Why would you create your own URL Shortener?</p>

<p>With <code class="language-plaintext highlighter-rouge">Jekyll URL Shortener</code> you could:</p>

<ul>
  <li>Have a vanity or branded domain name</li>
  <li>Create neat custom slugs for the short links</li>
  <li>Create short links with emoji</li>
  <li>Track short links with Google Analytics</li>
</ul>

<h2 id="credit">Credit</h2>

<p>The <code class="language-plaintext highlighter-rouge">Jekyll URL Shortener</code> is made possible by:</p>

<ul>
  <li>Jekyll: <a href="https://jekyllrb.com">https://jekyllrb.com</a></li>
  <li>jekyll-theme-minimal: <a href="https://github.com/pages-themes/minimal">https://github.com/pages-themes/minimal</a></li>
  <li>jekyll-redirect-from: <a href="https://github.com/jekyll/jekyll-redirect-from">https://github.com/jekyll/jekyll-redirect-from</a></li>
  <li>GitHub Pages: <a href="https://pages.github.com">https://pages.github.com</a></li>
</ul>

<h2 id="disclaimer">Disclaimer</h2>

<p>The redirecting is done with the <a href="https://github.com/jekyll/jekyll-redirect-from"><code class="language-plaintext highlighter-rouge">jekyll-redirect-from</code></a> plugin.</p>

<blockquote>
  <p>Redirects are performed by serving an HTML file with an HTTP-REFRESH meta tag which points to your destination.</p>
</blockquote>

<p>So, the HTTP status codes <code class="language-plaintext highlighter-rouge">301</code> (permanent redirect), <code class="language-plaintext highlighter-rouge">302</code>, <code class="language-plaintext highlighter-rouge">303</code> or <code class="language-plaintext highlighter-rouge">307</code> (temporary redirect) are not used.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="Jekyll" /><category term="GitHub Pages" /><summary type="html"><![CDATA[Building a URL Shortener with Jekyll and GitHub Pages]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/introducing-jekyll-url-shortener/logo.png" /><media:content medium="image" url="https://conductofcode.io/post/introducing-jekyll-url-shortener/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Easy Approach to Requirements Syntax and the segue to Behavior Driven Development</title><link href="https://conductofcode.io/post/easy-approach-to-requirements-syntax-and-the-segue-to-behavior-driven-development/" rel="alternate" type="text/html" title="Easy Approach to Requirements Syntax and the segue to Behavior Driven Development" /><published>2017-07-31T22:00:00+02:00</published><updated>2017-08-15T14:00:00+02:00</updated><id>https://conductofcode.io/post/easy-approach-to-requirements-syntax-and-the-segue-to-behavior-driven-development</id><content type="html" xml:base="https://conductofcode.io/post/easy-approach-to-requirements-syntax-and-the-segue-to-behavior-driven-development/"><![CDATA[<p>I was attending a conference six months ago and listened to a talk about <a href="http://swetugg.se/swetugg-2017/speakers/jonas-gauffin#med-fokus-pa-kvalitet">quality</a>.
During the talk, I was introduced to EARS — Easy Approach to Requirements Syntax.
This way of writing requirements struck a chord with me, given my prior experience reading and writing requirement specifications.</p>

<p>When doing agile development, we write <em>User Stories</em> and define <em>Acceptance Criteria</em>.</p>

<blockquote>
  <p>As a <code class="language-plaintext highlighter-rouge">&lt;role&gt;</code>, I want <code class="language-plaintext highlighter-rouge">&lt;goal/desire&gt;</code> so that <code class="language-plaintext highlighter-rouge">&lt;benefit&gt;</code></p>
</blockquote>

<p>When doing BDD, we follow this format:</p>

<blockquote>
  <p>In order to <code class="language-plaintext highlighter-rouge">&lt;receive benefit&gt;</code>, as a <code class="language-plaintext highlighter-rouge">&lt;role&gt;</code>, I want <code class="language-plaintext highlighter-rouge">&lt;goal/desire&gt;</code></p>
</blockquote>

<p>It’s not always easy to go from user stories and acceptance criteria to start writing tests.</p>

<p>I think that with <em>Easy Approach to Requirements Syntax</em> in place, it will be easier to do <em>Behavior Driven Development</em>.</p>

<p>When doing Hypothesis Driven Development, we follow this format:</p>

<blockquote>
  <p>We believe <code class="language-plaintext highlighter-rouge">&lt;this capability&gt;</code></p>

  <p>Will result in <code class="language-plaintext highlighter-rouge">&lt;this outcome&gt;</code></p>

  <p>We will know we have succeeded when <code class="language-plaintext highlighter-rouge">&lt;we see a measurable signal&gt;</code></p>
</blockquote>

<p>So my hypothesis is:</p>

<blockquote>
  <p>I believe using <em>Easy Approach to Requirements Syntax</em></p>

  <p>Will result in easier implementation of <em>Behavior Driven Development</em></p>

  <p>I will know I have succeeded when business people can actually write the (SpecFlow) feature files themselves ☺</p>
</blockquote>

<h2 id="easy-approach-to-requirements-syntax">Easy Approach to Requirements Syntax</h2>

<p>EARS was created during a case study at Rolls-Royce on requirements for aircraft engine control systems.</p>

<p>They identified eight major problems with writing requirements in an unstructured natural language:</p>

<blockquote>
  <ul>
    <li>Ambiguity (a word or phrase has two or more different meanings).</li>
    <li>Vagueness (lack of precision, structure and/or detail).</li>
    <li>Complexity (compound requirements containing complex sub-clauses and/or several interrelated statements).</li>
    <li>Omission (missing requirements, particularly requirements to handle unwanted behavior).</li>
    <li>Duplication (repetition of requirements that are defining the same need).</li>
    <li>Wordiness (use of an unnecessary number of words).</li>
    <li>Inappropriate implementation (statements of how the system should be built, rather than what it should do).</li>
    <li>Untestability (requirements that cannot be proven true or false when the system is implemented).</li>
  </ul>
</blockquote>

<p>To overcome or reduce the effects of these problems they came up with a rule set with five simple templates.</p>

<p>Requirements are divided into five types:</p>

<ul>
  <li>Ubiquitous</li>
  <li>Event-driven</li>
  <li>State-driven</li>
  <li>Unwanted behaviors</li>
  <li>Optional features</li>
</ul>

<h3 id="ubiquitous">Ubiquitous</h3>

<blockquote>
  <p>The <code class="language-plaintext highlighter-rouge">&lt;system name&gt;</code> shall <code class="language-plaintext highlighter-rouge">&lt;system response&gt;</code></p>
</blockquote>

<h3 id="event-driven">Event-driven</h3>

<blockquote>
  <p>When <code class="language-plaintext highlighter-rouge">&lt;optional preconditions&gt;</code> <code class="language-plaintext highlighter-rouge">&lt;trigger&gt;</code>, the <code class="language-plaintext highlighter-rouge">&lt;system name&gt;</code> shall <code class="language-plaintext highlighter-rouge">&lt;system response&gt;</code></p>
</blockquote>

<h3 id="state-driven">State-driven</h3>

<blockquote>
  <p>While <code class="language-plaintext highlighter-rouge">&lt;in a specific state&gt;</code>, the <code class="language-plaintext highlighter-rouge">&lt;system name&gt;</code> shall <code class="language-plaintext highlighter-rouge">&lt;system response&gt;</code></p>
</blockquote>

<h3 id="unwanted-behaviors">Unwanted behaviors</h3>

<blockquote>
  <p>If <code class="language-plaintext highlighter-rouge">&lt;optional preconditions&gt;</code> <code class="language-plaintext highlighter-rouge">&lt;trigger&gt;</code>, then the <code class="language-plaintext highlighter-rouge">&lt;system name&gt;</code> shall <code class="language-plaintext highlighter-rouge">&lt;system response&gt;</code></p>
</blockquote>

<h3 id="optional-features">Optional features</h3>

<blockquote>
  <p>Where <code class="language-plaintext highlighter-rouge">&lt;feature is included&gt;</code>, the <code class="language-plaintext highlighter-rouge">&lt;system name&gt;</code> shall <code class="language-plaintext highlighter-rouge">&lt;system response&gt;</code></p>
</blockquote>

<h2 id="the-stack-class">The Stack Class</h2>

<p>Let’s put this to the test with the <a href="https://msdn.microsoft.com/en-us/library/3278tedw(v=vs.110).aspx"><code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> Class</a> as the example.</p>

<p>This is some of the documentation from MSDN:</p>

<blockquote>
  <p>Represents a variable size last-in-first-out (LIFO) collection of instances of the same specified type.</p>
</blockquote>

<blockquote>
  <p>The capacity of the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> is the number of elements that the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> can store. <code class="language-plaintext highlighter-rouge">Count</code> is the number of elements that are actually in the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code>.</p>
</blockquote>

<blockquote>
  <p>Three main operations can be performed on a <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> and its elements:</p>

  <ul>
    <li><code class="language-plaintext highlighter-rouge">Push</code> inserts an element at the top of the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code>.</li>
    <li><code class="language-plaintext highlighter-rouge">Pop</code> removes an element from the top of the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code>.</li>
    <li><code class="language-plaintext highlighter-rouge">Peek</code> returns an element that is at the top of the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> but does not remove it from the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code>.</li>
  </ul>
</blockquote>

<p>If we were to write a <em>User Story</em> in BDD format:</p>

<blockquote>
  <p>In order to store instances of the same specified type in last-in-first-out (LIFO) sequence</p>

  <p>As a developer</p>

  <p>I want to use a <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code></p>
</blockquote>

<p>If we were to write requirements with <em>EARS</em> templates:</p>

<h3 id="ubiquitous-1">Ubiquitous</h3>

<blockquote>
  <p>The <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall store instances of the same specified type in last-in-first-out (LIFO) order.</p>
</blockquote>

<blockquote>
  <p>The <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall return the number of elements contained when the property <code class="language-plaintext highlighter-rouge">Count</code> is invoked.</p>
</blockquote>

<h3 id="event-driven-1">Event-driven</h3>

<blockquote>
  <p>When the method <code class="language-plaintext highlighter-rouge">Push</code> is invoked, the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall insert the element at the top.</p>
</blockquote>

<blockquote>
  <p>When the method <code class="language-plaintext highlighter-rouge">Pop</code> is invoked, the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall remove and return the element at the top.</p>
</blockquote>

<blockquote>
  <p>When the method <code class="language-plaintext highlighter-rouge">Peek</code> is invoked, the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall return the element at the top without removing it.</p>
</blockquote>

<h3 id="state-driven-1">State-driven</h3>

<blockquote>
  <p>While an element is present, the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall return <code class="language-plaintext highlighter-rouge">true</code> when the method <code class="language-plaintext highlighter-rouge">Contains</code> is invoked.</p>
</blockquote>

<blockquote>
  <p>While an element is not present, the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall return <code class="language-plaintext highlighter-rouge">false</code> when the method <code class="language-plaintext highlighter-rouge">Contains</code> is invoked.</p>
</blockquote>

<h3 id="unwanted-behaviors-1">Unwanted behaviors</h3>

<blockquote>
  <p>If empty and the method <code class="language-plaintext highlighter-rouge">Pop</code> is invoked, then the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall throw <code class="language-plaintext highlighter-rouge">InvalidOperationException</code>.</p>
</blockquote>

<blockquote>
  <p>If empty and the method <code class="language-plaintext highlighter-rouge">Peek</code> is invoked, then the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall throw <code class="language-plaintext highlighter-rouge">InvalidOperationException</code>.</p>
</blockquote>

<h3 id="optional-features-1">Optional features</h3>

<blockquote>
  <p>Where instantiated with a specified collection, the <code class="language-plaintext highlighter-rouge">Stack&lt;T&gt;</code> shall be prepopulated with the elements of the collection.</p>
</blockquote>

<h2 id="behavior-driven-development">Behavior Driven Development</h2>

<p>Let’s take this to the next level with BDD and SpecFlow.</p>

<script src="https://gist.github.com/hlaueriksson/3bd543bc6466e3eb5ecd1ab87d952563.js?file=Stack.feature"> </script>

<ul>
  <li>Each requirement has its own scenario</li>
  <li>I’ve tagged the scenarios with the type of requirement for clarity</li>
</ul>

<script src="https://gist.github.com/hlaueriksson/3bd543bc6466e3eb5ecd1ab87d952563.js?file=StackSteps.cs"> </script>

<p>In my opinion, it was easy to write the tests.
I copy-and-pasted the requirement to the SpecFlow feature file and then I knew exactly how many scenarios I needed to implement.
I think the examples in the scenarios makes the requirements easier to understand and reason about.
Maybe this should be called <em>Requirements by Example</em>?</p>

<h2 id="the-bdd-cycle">The BDD Cycle</h2>

<p>When implementing the production code, we can use <em>The BDD Cycle</em> described in <a href="https://pragprog.com/book/achbd/the-rspec-book">The RSpec Book</a>.</p>

<p><img src="the-bdd-cycle.jpg" alt="The BDD Cycle" /></p>

<ul>
  <li>A photo of page 10 from my copy of The RSpec Book</li>
  <li>As a .NET developer, you can replace <em>Cucumber</em> with <em>SpecFlow</em> and <em>RSpec</em> with <em>Machine.Specifications</em></li>
</ul>

<p>The BDD Cycle introduces two levels of testing.
We can use <em>SpecFlow</em> to focus on the high-level behavior, the requirements.
And use <em>Machine.Specifications</em> to focus on more granular behavior, unit testing code in isolation.</p>

<h2 id="resources">Resources</h2>

<ul>
  <li>
    <p><a href="https://www.researchgate.net/publication/224079416_Easy_approach_to_requirements_syntax_EARS">Easy approach to requirements syntax (EARS)</a>
by Alistair Mavin et al. The six-page research paper.</p>
  </li>
  <li>
    <p><a href="https://aaltodoc.aalto.fi/bitstream/handle/123456789/12861/D5_uusitalo_eero_2012.pdf">EARS quick reference sheet</a>
[PDF] from Aalto University. A two-page summary.</p>
  </li>
  <li>
    <p><a href="https://www.iaria.org/conferences2013/filesICCGI13/ICCGI_2013_Tutorial_Terzakis.pdf">EARS: The Easy Approach to Requirements Syntax</a>
[PDF] by John Terzakis. A 66-page presentation on EARS and how it is used at Intel.</p>
  </li>
  <li>
    <p>The source code for the example in this blog post: <a href="https://github.com/hlaueriksson/ConductOfCode/tree/master/EARS/ConductOfCode">GitHub</a></p>
  </li>
  <li>
    <p><a href="https://github.com/techtalk/SpecFlow">SpecFlow</a></p>
  </li>
  <li>
    <p><a href="https://github.com/machine/machine.specifications">Machine.Specifications</a></p>
  </li>
</ul>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="Requirements" /><category term="SpecFlow" /><summary type="html"><![CDATA[I was attending a conference six months ago and listened to a talk about quality. During the talk, I was introduced to EARS — Easy Approach to Requirements Syntax. This way of writing requirements struck a chord with me, given my prior experience reading and writing requirement specifications.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/easy-approach-to-requirements-syntax-and-the-segue-to-behavior-driven-development/vs.png" /><media:content medium="image" url="https://conductofcode.io/post/easy-approach-to-requirements-syntax-and-the-segue-to-behavior-driven-development/vs.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Managing content for a JAMstack site with Netlify CMS</title><link href="https://conductofcode.io/post/managing-content-for-a-jamstack-site-with-netlify-cms/" rel="alternate" type="text/html" title="Managing content for a JAMstack site with Netlify CMS" /><published>2017-06-30T14:00:00+02:00</published><updated>2017-06-30T14:00:00+02:00</updated><id>https://conductofcode.io/post/managing-content-for-a-jamstack-site-with-netlify-cms</id><content type="html" xml:base="https://conductofcode.io/post/managing-content-for-a-jamstack-site-with-netlify-cms/"><![CDATA[<p>Content for the modern web development architecture:</p>

<blockquote>
  <p>Headless CMS = Content Management System for JAMstack sites</p>
</blockquote>

<p>This blog post covers:</p>

<blockquote>
  <p>Netlify CMS for a JAMstack site built with Hugo + jQuery + Azure Functions</p>
</blockquote>

<p>This blog post is part of a series:</p>

<ol>
  <li><a href="/post/building-a-jamstack-site-with-hugo-and-azure-functions/">Building a JAMstack site with Hugo and Azure Functions</a></li>
  <li>Managing content for a JAMstack site with Netlify CMS (this post)</li>
</ol>

<p><img src="jamstack-recipes.png" alt="JAMstack Recipes" /></p>

<p>The example used in this blog post is a site for <strong>jam recipes</strong>.</p>

<p>Example code:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/jamstack-cms">https://github.com/hlaueriksson/jamstack-cms</a></li>
</ul>

<p>Example site:</p>

<ul>
  <li><a href="http://jamstack-cms.netlify.com">http://jamstack-cms.netlify.com</a></li>
</ul>

<h2 id="jamstack">JAMstack</h2>

<p><a href="https://jamstack.org">JAMstack</a> is the modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.
The previous blog post covered how to <a href="/post/building-a-jamstack-site-with-hugo-and-azure-functions/">build a JAMstack site with Hugo and Azure Functions</a>.
This post will focus on how to add a Headless CMS to manage the content for the site.</p>

<h2 id="headless-cms">Headless CMS</h2>

<p>A Headless CMS gives non-technical users a simple way to add and edit the content of a JAMstack site.
By being headless, it decouples the content from the presentation.</p>

<blockquote>
  <p>A headless CMS doesn’t care where it’s serving its content to. It’s no longer attached to the frontend, and the content can be viewed on any platform.</p>
</blockquote>

<p>Read all about it over at: <a href="https://headlesscms.org">https://headlesscms.org</a></p>

<p>A Headless CMS can be:</p>

<ul>
  <li>Git-based</li>
  <li>API-driven</li>
</ul>

<p>In this blog post the focus is on <em>Netlify CMS</em>,
an open source, Git-based CMS for all static site generators.</p>

<blockquote>
  <p>With a git-based CMS you are pushing changes to git that then triggers a new build of your site.</p>
</blockquote>

<h2 id="netlify-cms">Netlify CMS</h2>

<blockquote>
  <p>An open-source CMS for your Git workflow</p>
</blockquote>

<p>Find out more at:</p>

<ul>
  <li><a href="https://www.netlifycms.org">https://www.netlifycms.org</a></li>
  <li><a href="https://github.com/netlify/netlify-cms">https://github.com/netlify/netlify-cms</a></li>
</ul>

<p>Why Netlify CMS?</p>

<ul>
  <li>Integrates with any build tool</li>
  <li>Plugs in to any static site generator</li>
</ul>

<h3 id="setup">Setup</h3>

<p>You can follow the <a href="https://github.com/netlify/netlify-cms/blob/master/docs/quick-start.md">Quick Start</a> to install and configure Netlify CMS.</p>

<p>Basically do five things:</p>

<ol>
  <li>Sign up for Netlify:
    <ul>
      <li><a href="https://app.netlify.com/signup">https://app.netlify.com/signup</a></li>
    </ul>
  </li>
  <li>New site from Git</li>
  <li>Register a new OAuth application in GitHub</li>
  <li>Install authentication provider</li>
  <li>Update the code</li>
</ol>

<h4 id="new-site-from-git">New site from Git</h4>

<p>Go here:</p>

<ul>
  <li><a href="https://app.netlify.com/start">https://app.netlify.com/start</a></li>
</ul>

<p>Then:</p>

<ol>
  <li>Select a git provider</li>
  <li>Select a repository</li>
  <li>Configure your build</li>
</ol>

<p><img src="netlify-create-a-new-site.png" alt="Create a new site" /></p>

<p>The build configuration for this site:</p>

<p><img src="netlify-continuous-deployment.png" alt="Continuous Deployment" /></p>

<ul>
  <li>Build command: <code class="language-plaintext highlighter-rouge">hugo -s src/site</code></li>
  <li>Publish directory: <code class="language-plaintext highlighter-rouge">src/site/public</code></li>
  <li>Build environment variables: <code class="language-plaintext highlighter-rouge">HUGO_VERSION = 0.21</code></li>
</ul>

<p>Refer to <a href="https://www.netlify.com/docs/continuous-deployment/#common-configuration-directives">Common configuration directives</a> when configuring other static site generators.</p>

<h4 id="register-a-new-oauth-application-in-github">Register a new OAuth application in GitHub</h4>

<p>Go here:</p>

<ul>
  <li><a href="https://github.com/settings/developers">https://github.com/settings/developers</a></li>
</ul>

<p>Then:</p>

<ul>
  <li>Register a new OAuth application</li>
</ul>

<p><img src="github-register-a-new-oauth-application.png" alt="Register a new OAuth application" /></p>

<ul>
  <li>Authorization callback URL: <code class="language-plaintext highlighter-rouge">https://api.netlify.com/auth/done</code></li>
</ul>

<p>Take note of:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Client ID</code></li>
  <li><code class="language-plaintext highlighter-rouge">Client Secret</code></li>
</ul>

<h4 id="install-authentication-provider">Install authentication provider</h4>

<p>Go here:</p>

<ul>
  <li><a href="https://app.netlify.com">https://app.netlify.com</a></li>
</ul>

<p>Then:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">&lt;Site&gt;</code> / Access / Authentication providers / Install provider</li>
</ul>

<p><img src="netlify-install-authentication-provider.png" alt="Install authentication provider" /></p>

<p>Copy from GitHub:</p>

<ul>
  <li>Key: <code class="language-plaintext highlighter-rouge">Client ID</code></li>
  <li>Secret: <code class="language-plaintext highlighter-rouge">Client Secret</code></li>
</ul>

<h3 id="code">Code</h3>

<p>The code for the site:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/jamstack-cms/tree/master/src/site">https://github.com/hlaueriksson/jamstack-cms/tree/master/src/site</a></li>
</ul>

<p>The source code in this example is a <a href="https://help.github.com/articles/duplicating-a-repository/">clone</a> of the Git repository from the previous blog post.</p>

<p>Some code has changed:</p>

<p><img src="winmerge.png" alt="WinMerge" /></p>

<p>Let’s talk about the highlighted files…</p>

<p>To add Netlify CMS to a Hugo site, two files should be added to the <code class="language-plaintext highlighter-rouge">/static/admin/</code> folder:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">index.html</code></li>
  <li><code class="language-plaintext highlighter-rouge">config.yml</code></li>
</ul>

<p><code class="language-plaintext highlighter-rouge">index.html</code>:</p>

<script src="https://gist.github.com/hlaueriksson/2a6a672b2749c7b1785acc5991f5ee20.js?file=index.html"> </script>

<ul>
  <li>Entry point for the Netlify CMS admin interface</li>
  <li>Scripts and styles from CDN</li>
  <li>This is a React app</li>
  <li>This is version <code class="language-plaintext highlighter-rouge">0.4</code></li>
</ul>

<p><code class="language-plaintext highlighter-rouge">config.yml</code>:</p>

<script src="https://gist.github.com/hlaueriksson/2a6a672b2749c7b1785acc5991f5ee20.js?file=config.yml"> </script>

<ul>
  <li>The backend is the GitHub repo</li>
  <li>The media and public folders suitable for Hugo. Images can be uploaded directly from the editor.</li>
  <li>Collections define the structure for content types and how the admin interface in Netlify CMS should work</li>
  <li>One content type for recipes is configured in this example</li>
  <li>The <code class="language-plaintext highlighter-rouge">fields</code> correspond to the <code class="language-plaintext highlighter-rouge">yaml</code>-formatted front matter in the generated markdown files</li>
  <li>The last field, <code class="language-plaintext highlighter-rouge">body</code>, is the content in generated markdown files</li>
  <li>You can enable the <a href="https://github.com/netlify/netlify-cms/blob/master/docs/editorial-workflow.md">Editorial Workflow</a> here</li>
</ul>

<p>Content:</p>

<script src="https://gist.github.com/hlaueriksson/2a6a672b2749c7b1785acc5991f5ee20.js?file=apple-jam.txt"> </script>

<ul>
  <li>The content type from the <code class="language-plaintext highlighter-rouge">config.yml</code> generates markdown files like this</li>
  <li>The <code class="language-plaintext highlighter-rouge">yaml</code>-formatted front matter correspond to the <code class="language-plaintext highlighter-rouge">fields</code></li>
  <li>The <code class="language-plaintext highlighter-rouge">body</code> field is the actual content</li>
</ul>

<p>The following files needed to be modified to support the new site and the markdown files generated by the Netlify CMS.</p>

<p><code class="language-plaintext highlighter-rouge">config.toml</code>:</p>

<script src="https://gist.github.com/hlaueriksson/2a6a672b2749c7b1785acc5991f5ee20.js?file=config.toml"> </script>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">baseURL</code> points to the new site hosted by Netlify</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">summary.html</code>:</p>

<script src="https://gist.github.com/hlaueriksson/2a6a672b2749c7b1785acc5991f5ee20.js?file=summary.html"> </script>

<ul>
  <li>Images can be uploaded directly from the editor to a dedicated folder in the Git repo</li>
  <li>The full URL to the image comes from the front matter</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">recipe.html</code>:</p>

<script src="https://gist.github.com/hlaueriksson/2a6a672b2749c7b1785acc5991f5ee20.js?file=recipe.html"> </script>

<ul>
  <li>The URL to the image was changed here too</li>
  <li>Front matter formatted with <code class="language-plaintext highlighter-rouge">yaml</code> and <code class="language-plaintext highlighter-rouge">toml</code> has a slightly different structure</li>
  <li>Access to the values of ingredients was changed</li>
</ul>

<h3 id="content-manager">Content Manager</h3>

<p>The Netlify CMS admin interface is accessed via the <code class="language-plaintext highlighter-rouge">/admin/</code> slug.</p>

<ul>
  <li><a href="http://jamstack-cms.netlify.com/admin/">http://jamstack-cms.netlify.com/admin/</a></li>
</ul>

<p>If you are a collaborator on the GitHub repo you can log in:</p>

<p><img src="netlify-cms-login-with-github.png" alt="Login with GitHub" /></p>

<p>After you authorize the application:</p>

<p><img src="github-authorize-application.png" alt="Authorize Application" /></p>

<p>You can view the content from the repo:</p>

<p><img src="netlify-cms-content-manager.png" alt="Content Manager" /></p>

<p>Add and edit the content from the repo:</p>

<p><img src="netlify-cms-edit.png" alt="Edit" /></p>

<h2 id="conclusion">Conclusion</h2>

<p>JAMstack sites are awesome. Headless CMSs adds even more awesomeness.</p>

<p><a href="https://www.netlify.com/blog/2017/03/16/smashing-magazine-just-got-10x-faster/">Smashing Magazine just got 10x faster</a> by using Hugo and Netlify CMS to move from a WordPress to a JAMstack site.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="Netlify" /><category term="Hugo" /><summary type="html"><![CDATA[Content for the modern web development architecture:]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/managing-content-for-a-jamstack-site-with-netlify-cms/vsc.png" /><media:content medium="image" url="https://conductofcode.io/post/managing-content-for-a-jamstack-site-with-netlify-cms/vsc.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Building a JAMstack site with Hugo and Azure Functions</title><link href="https://conductofcode.io/post/building-a-jamstack-site-with-hugo-and-azure-functions/" rel="alternate" type="text/html" title="Building a JAMstack site with Hugo and Azure Functions" /><published>2017-05-31T22:00:00+02:00</published><updated>2017-06-30T14:00:00+02:00</updated><id>https://conductofcode.io/post/building-a-jamstack-site-with-hugo-and-azure-functions</id><content type="html" xml:base="https://conductofcode.io/post/building-a-jamstack-site-with-hugo-and-azure-functions/"><![CDATA[<p>Modern web development architecture:</p>

<blockquote>
  <p>Static site generators + JavaScript + Serverless = JAMstack</p>
</blockquote>

<p>This blog post covers:</p>

<blockquote>
  <p>Hugo + jQuery + Azure Functions = JAMstack</p>
</blockquote>

<p>This blog post is part of a series:</p>

<ol>
  <li>Building a JAMstack site with Hugo and Azure Functions (this post)</li>
  <li><a href="/post/managing-content-for-a-jamstack-site-with-netlify-cms/">Managing content for a JAMstack site with Netlify CMS</a></li>
</ol>

<p><img src="jamstack-recipes.png" alt="JAMstack Recipes" /></p>

<p>The example used in this blog post is a site for <strong>jam recipes</strong>.</p>

<p>Example code:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/jamstack">https://github.com/hlaueriksson/jamstack</a></li>
</ul>

<p>Example site:</p>

<ul>
  <li><a href="https://hlaueriksson.github.io/jamstack/">https://hlaueriksson.github.io/jamstack/</a></li>
</ul>

<h2 id="jamstack">JAMstack</h2>

<blockquote>
  <p>Modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.</p>
</blockquote>

<p>Read all about it over at: <a href="https://jamstack.org">https://jamstack.org</a></p>

<p>Three things are needed:</p>

<ul>
  <li>JavaScript</li>
  <li>APIs</li>
  <li>Markup</li>
</ul>

<p>In this blog post the JavaScript is written with <em>jQuery</em>,
the APIs implemented with <em>Azure Functions</em>
and the markup generated with <em>Hugo</em>.</p>

<p>Why?</p>

<ul>
  <li>Better Performance</li>
  <li>Higher Security</li>
  <li>Cheaper, Easier Scaling</li>
  <li>Better Developer Experience</li>
</ul>

<p>Static site generators is
<a href="https://www.smashingmagazine.com/2015/11/modern-static-website-generators-next-big-thing/">The Next Big Thing</a>
and it is used
<a href="https://www.smashingmagazine.com/2016/08/using-a-static-site-generator-at-scale-lessons-learned/">At Scale</a>.</p>

<h2 id="hugo">Hugo</h2>

<blockquote>
  <p>A fast and modern static website engine</p>
</blockquote>

<p><a href="https://gohugo.io">Hugo</a> is a static site generator.</p>

<p>It’s the second most popular according to <a href="https://www.staticgen.com">https://www.staticgen.com</a></p>

<p>Why Hugo?</p>

<ul>
  <li>Extremely fast build times</li>
  <li>Runs on Windows and is easy to <a href="https://gohugo.io/overview/installing/">install</a></li>
</ul>

<p>Scaffold a Hugo site:</p>

<p><code class="language-plaintext highlighter-rouge">hugo new site .</code></p>

<p><img src="hugo-new-site.png" alt="hugo new site ." /></p>

<p>Add content:</p>

<p><code class="language-plaintext highlighter-rouge">hugo new recipe/apple-jam.md</code></p>

<p><img src="hugo-new.png" alt="hugo new recipe/apple-jam.md" /></p>

<h3 id="code">Code</h3>

<p>The code for the site:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/jamstack/tree/master/src/site">https://github.com/hlaueriksson/jamstack/tree/master/src/site</a></li>
</ul>

<p>Configuration for the Hugo site is done in <code class="language-plaintext highlighter-rouge">config.toml</code>:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=config.toml"> </script>

<ul>
  <li>Uses the <a href="https://github.com/toml-lang/toml">TOML</a> format, located in the root folder</li>
  <li>The <code class="language-plaintext highlighter-rouge">baseURL</code> points to where the site is hosted on GitHub Pages</li>
</ul>

<p>Data:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=api.toml"> </script>

<ul>
  <li>Uses the <a href="https://github.com/toml-lang/toml">TOML</a> format, located in the <code class="language-plaintext highlighter-rouge">data</code> folder</li>
  <li>This example is for the API URLs invoked by the JavaScript</li>
</ul>

<p>The HTML template for the header:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=header.html"> </script>

<ul>
  <li>HTML file located in the <code class="language-plaintext highlighter-rouge">layouts\partials</code> folder</li>
  <li>This example uses <a href="https://v4-alpha.getbootstrap.com/getting-started/introduction/#starter-template">Bootstrap</a> template with the <a href="https://v4-alpha.getbootstrap.com/examples/narrow-jumbotron/">Narrow jumbotron</a></li>
  <li>Custom CSS in <code class="language-plaintext highlighter-rouge">app.css</code>, Bootstrap stylesheets from CDN</li>
  <li>The <code class="language-plaintext highlighter-rouge">body</code> tag gets an <code class="language-plaintext highlighter-rouge">id</code> with the current page template, will be used in the JavaScript</li>
  <li>The navigation is populated by pages configured with <code class="language-plaintext highlighter-rouge">navigation = true</code> in the front matter</li>
</ul>

<p>The HTML template for the header:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=footer.html"> </script>

<ul>
  <li>HTML file located in the <code class="language-plaintext highlighter-rouge">layouts\partials</code> folder</li>
  <li>Custom JS in <code class="language-plaintext highlighter-rouge">app.js</code>, third-party scripts from CDN</li>
</ul>

<p>Content:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=apple-jam.txt"> </script>

<ul>
  <li>Uses the <a href="https://guides.github.com/features/mastering-markdown/">Markdown</a> format with <a href="https://gohugo.io/content/front-matter/">Front Matter</a></li>
  <li>This example is for the Apple Jam page</li>
  <li>The image and ingredients are stored as variables, available in templates via the <a href="https://gohugo.io/templates/variables/#param-method">Param method</a></li>
</ul>

<p>Page Templates:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=recipe.html"> </script>

<ul>
  <li>HTML file located in a <code class="language-plaintext highlighter-rouge">layouts</code> subfolder</li>
  <li>Reference the header and footer partials</li>
  <li>This example is for the recipe pages</li>
  <li>Data for the JavaScript is stored as attributes in a dedicated element</li>
  <li>The image and ingredients are accessed via the <a href="https://gohugo.io/templates/variables/#param-method">Param method</a></li>
  <li>The page markdown content is accessed with the <code class="language-plaintext highlighter-rouge">.Content</code> variable</li>
</ul>

<p>JavaScript:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=app.js"> </script>

<ul>
  <li>Located in the <code class="language-plaintext highlighter-rouge">static</code> folder</li>
  <li>This example uses <a href="https://jquery.com">jQuery</a></li>
  <li>The recipe page will <code class="language-plaintext highlighter-rouge">GET</code> ingredients from a Azure Function</li>
  <li>The submit page will <code class="language-plaintext highlighter-rouge">POST</code> recipes to a Azure Function</li>
</ul>

<p>Hugo has a theming system, so you don’t have to implement all templates yourself.</p>

<p>Hugo Themes:</p>

<ul>
  <li><a href="https://themes.gohugo.io">https://themes.gohugo.io</a></li>
</ul>

<h3 id="run-and-build">Run and Build</h3>

<p>Hugo provides its own webserver which builds and serves the site:</p>

<p><code class="language-plaintext highlighter-rouge">hugo server</code></p>

<p><img src="hugo-server.png" alt="hugo server" /></p>

<ul>
  <li>In this example you can then browse <code class="language-plaintext highlighter-rouge">http://localhost:1313/jamstack/</code></li>
</ul>

<p>Build the Hugo site:</p>

<p><code class="language-plaintext highlighter-rouge">hugo --destination ../../docs</code></p>

<p><img src="hugo-destination.png" alt="hugo --destination ../../docs" /></p>

<ul>
  <li>In this example the site is hosted by GitHub Pages from the <code class="language-plaintext highlighter-rouge">docs</code> folder in the git repo.</li>
</ul>

<p>Troubleshoot the site generation with:</p>

<p><code class="language-plaintext highlighter-rouge">hugo --verbose</code></p>

<h3 id="github-pages">GitHub Pages</h3>

<p>Get the site hosted on GitHub Pages by:</p>

<ol>
  <li>Pushing the code to <a href="https://github.com">GitHub</a></li>
  <li><a href="https://help.github.com/articles/configuring-a-publishing-source-for-github-pages/">Configuring a publishing source for GitHub Pages</a></li>
</ol>

<p>In this example the <code class="language-plaintext highlighter-rouge">docs</code> folder is used as publishing source:</p>

<p><img src="github-pages.png" alt="GitHub Pages" /></p>

<h2 id="azure-functions">Azure Functions</h2>

<p><a href="https://github.com/Azure/azure-functions-cli">Azure Functions Core Tools</a> is a command line tool for Azure Functions</p>

<blockquote>
  <p>The Azure Functions Core Tools provide a local development experience for creating, developing, testing, running, and debugging Azure Functions.</p>
</blockquote>

<p>Create a function app:</p>

<p><code class="language-plaintext highlighter-rouge">func init</code></p>

<p><img src="func-init.png" alt="func init" /></p>

<p>Create a function:</p>

<p><code class="language-plaintext highlighter-rouge">func function create</code></p>

<p><img src="func-function-create.png" alt="func function create" /></p>

<p><em>If you don’t like the terminal, take a look at <a href="https://blogs.msdn.microsoft.com/webdev/2017/05/10/azure-function-tools-for-visual-studio-2017/">Visual Studio 2017 Tools for Azure Functions</a></em></p>

<h3 id="code-1">Code</h3>

<p>The code for the API:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/jamstack/tree/master/src/api">https://github.com/hlaueriksson/jamstack/tree/master/src/api</a></li>
</ul>

<p>Configuration for a function is done in <code class="language-plaintext highlighter-rouge">function.json</code>:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=function.json"> </script>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">authLevel</code> can be set to <code class="language-plaintext highlighter-rouge">anonymous</code> in this example</li>
  <li>The <code class="language-plaintext highlighter-rouge">route</code> and <code class="language-plaintext highlighter-rouge">methods</code> are important to know when invoking the function from the JavaScript</li>
</ul>

<p>The actual function is implemented in <code class="language-plaintext highlighter-rouge">run.csx</code>:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=run.csx"> </script>

<ul>
  <li>Uses the <a href="http://scriptcs.net/">scriptcs</a> format</li>
  <li>This example will return hard coded ingredients for the given recipe</li>
</ul>

<h3 id="run">Run</h3>

<p>Run the functions locally:</p>

<p><code class="language-plaintext highlighter-rouge">func host start</code></p>

<p>When running the Hugo site against local functions, specify CORS origins:</p>

<p><code class="language-plaintext highlighter-rouge">func host start --cors http://localhost:1313</code></p>

<p><img src="func-host-start.png" alt="func host start --cors http://localhost:1313" /></p>

<h3 id="deployment">Deployment</h3>

<p>Get the functions hosted on Azure by:</p>

<ol>
  <li>Pushing the code to <a href="https://github.com/">GitHub</a>, <a href="https://bitbucket.org">Bitbucket</a> or <a href="https://www.visualstudio.com/team-services/">Visual Studio Team Services</a></li>
  <li>Log in to the <a href="https://portal.azure.com">Azure portal</a></li>
  <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function#create-a-function-app">Create a function app</a></li>
  <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-continuous-deployment#set-up-continuous-deployment">Set up continuous deployment</a></li>
</ol>

<p>In this example the Azure Functions code is located in the <code class="language-plaintext highlighter-rouge">\src\api\</code> folder in the git repo.</p>

<p>Therefor deploying with custom script is needed:</p>

<ul>
  <li><a href="https://github.com/projectkudu/kudu/wiki/Customizing-deployments">Customizing deployments</a></li>
  <li><a href="https://github.com/projectkudu/kudu/wiki/Deployment-hooks">Deployment hooks</a></li>
</ul>

<p><code class="language-plaintext highlighter-rouge">.deployment</code>:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=.deployment"> </script>

<ul>
  <li>Run <code class="language-plaintext highlighter-rouge">deploy.cmd</code> during deployment</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">deploy.cmd</code>:</p>

<script src="https://gist.github.com/hlaueriksson/1385d7774044e6d6fb3840b6912f7b47.js?file=deploy.cmd"> </script>

<ul>
  <li>Copy files from the <code class="language-plaintext highlighter-rouge">\src\api</code> folder to the repository root</li>
</ul>

<p>During deployment the logs look like this:</p>

<p><img src="azure-logs.png" alt="Azure Logs" /></p>

<h3 id="configuration">Configuration</h3>

<p>Before the Hugo site and the JavaScript can invoke the Azure Functions, Cross-Origin Resource Sharing (CORS) needs to be configured.</p>

<p>In this example these origins are allowed:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">https://hlaueriksson.github.io</code></li>
  <li><code class="language-plaintext highlighter-rouge">http://localhost:1313</code></li>
</ul>

<p><img src="azure-cors.png" alt="Azure CORS" /></p>

<p>Now the Hugo site can be configured to use these URLs:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">https://jamstack.azurewebsites.net/api/Ingredients/{recipe}</code></li>
  <li><code class="language-plaintext highlighter-rouge">https://jamstack.azurewebsites.net/api/Recipe</code></li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<ul>
  <li>JAMstack is the modern web development architecture</li>
  <li>Static site generators is a big thing right now</li>
  <li>Hugo is fast and awesome</li>
  <li>jQuery is still useful</li>
  <li>Serverless is the next big thing</li>
  <li>Azure Functions is awesome</li>
</ul>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="Hugo" /><category term="Azure" /><summary type="html"><![CDATA[Modern web development architecture:]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/building-a-jamstack-site-with-hugo-and-azure-functions/vsc.png" /><media:content medium="image" url="https://conductofcode.io/post/building-a-jamstack-site-with-hugo-and-azure-functions/vsc.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Serverless with Azure Functions</title><link href="https://conductofcode.io/post/serverless-with-azure-functions/" rel="alternate" type="text/html" title="Serverless with Azure Functions" /><published>2017-04-30T12:00:00+02:00</published><updated>2022-09-14T22:00:00+02:00</updated><id>https://conductofcode.io/post/serverless-with-azure-functions</id><content type="html" xml:base="https://conductofcode.io/post/serverless-with-azure-functions/"><![CDATA[<p>I set out to learn about Azure Functions and this is the knowledge I have gathered so far.</p>

<p>To have something to work with, I decided to migrate the ASP.NET Core Web API for <em>“My latest online activities”</em> to Azure Functions.</p>

<p>As background, refer to these related blog posts:</p>

<ul>
  <li><a href="/post/getting-started-with-react/">Getting started with React</a></li>
  <li><a href="/post/continuous-delivery-with-visual-studio-team-services/">Continuous Delivery with Visual Studio Team Services</a></li>
  <li><a href="/post/introducing-commandquery/">Introducing CommandQuery</a></li>
</ul>

<p>To get some basic understanding, read the introduction over at Microsoft Docs:</p>

<ul>
  <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-overview">An introduction to Azure Functions</a></li>
</ul>

<p>You can create your functions in the browser on the <a href="https://portal.azure.com">Azure Portal</a>, but I find it to be a bit cumbersome.
My approach is to use the Azure Functions CLI tool to scaffold a project, put it on GitHub and deploy to Azure Functions with continuous deployment.</p>

<h2 id="azure-functions-cli">Azure Functions CLI</h2>

<blockquote>
  <p>Command line tool for Azure Function</p>

  <p>The Azure Functions CLI provides a local development experience for creating, developing, testing, running, and debugging Azure Functions.</p>
</blockquote>

<p>Read the docs at:</p>

<ul>
  <li><a href="https://github.com/Azure/azure-functions-cli">https://github.com/Azure/azure-functions-cli</a></li>
</ul>

<p>Install:</p>

<p><code class="language-plaintext highlighter-rouge">npm i -g azure-functions-cli</code></p>

<p><img src="npm.png" alt="npm i -g azure-functions-cli" /></p>

<blockquote>
  <p>Install globally</p>
</blockquote>

<p>Create Function App:</p>

<p><code class="language-plaintext highlighter-rouge">func init</code></p>

<p><img src="func-init.png" alt="func init" /></p>

<blockquote>
  <p>Create a new Function App in the current folder. Initializes git repo.</p>
</blockquote>

<p>Create Function:</p>

<p><code class="language-plaintext highlighter-rouge">func function create</code></p>

<p><img src="func-function-create.png" alt="func function create" /></p>

<blockquote>
  <p>Create a new Function from a template, using the Yeoman generator</p>
</blockquote>

<p>Run:</p>

<p><code class="language-plaintext highlighter-rouge">func host start</code></p>

<p><img src="func-host-start.png" alt="func host start" /></p>

<blockquote>
  <p>Launches the functions runtime host</p>
</blockquote>

<p>So that is what I did when I created the <code class="language-plaintext highlighter-rouge">latest-functions</code> project. I’ll come back to that later.
First let’s talk about my <code class="language-plaintext highlighter-rouge">CommandQuery</code> package.</p>

<h2 id="commandquery">CommandQuery</h2>

<blockquote>
  <p>Command Query Separation (CQS) for ASP.NET Core and Azure Functions</p>
</blockquote>

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">CommandQuery now has support for both <a href="https://twitter.com/hashtag/AspNetCore?src=hash">#AspNetCore</a> and <a href="https://twitter.com/hashtag/AzureFunctions?src=hash">#AzureFunctions</a><a href="https://t.co/qd8QHljnfx">https://t.co/qd8QHljnfx</a><a href="https://twitter.com/hashtag/CQS?src=hash">#CQS</a></p>&mdash; Henrik Lau Eriksson (@hlaueriksson) <a href="https://twitter.com/hlaueriksson/status/858662702713098240">April 30, 2017</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>Remember the background:</p>

<ul>
  <li><a href="/post/introducing-commandquery/">Introducing CommandQuery</a></li>
</ul>

<p>To migrate the ASP.NET Core Web API project to a Azure Functions app, I first needed to extend the <code class="language-plaintext highlighter-rouge">CommandQuery</code> solution.</p>

<p>As a result I ended up with three packages on NuGet:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">CommandQuery</code>
    <ul>
      <li>Common base functionality</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">CommandQuery.AspNetCore</code>
    <ul>
      <li>Command Query Separation for ASP.NET Core</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">CommandQuery.AzureFunctions</code>
    <ul>
      <li>Command Query Separation for Azure Functions</li>
    </ul>
  </li>
</ul>

<p>In this blog post I will cover the <code class="language-plaintext highlighter-rouge">CommandQuery.AzureFunctions</code> package:</p>

<blockquote>
  <p>Provides generic function support for commands and queries with HTTPTriggers</p>
</blockquote>

<p>To get more information about the project, read the documentation over at the GitHub repository.</p>

<p>Get started:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/CommandQuery/blob/master/CommandQuery.AzureFunctions.md">CommandQuery.AzureFunctions</a></li>
</ul>

<p>Sample code:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/CommandQuery/tree/master/samples">samples</a></li>
</ul>

<p>When I was writing the code specific to Azure Functions, I needed to add dependencies.
It makes sense to depend on the same assembly versions as the Azure Functions hosting environment use.
Therefore, I ended up creating a project to gather that information.</p>

<h2 id="azurefunctionsinfo">AzureFunctionsInfo</h2>

<blockquote>
  <p>⚡️ Information gathered on Azure Functions by executing Azure Functions ⚡️</p>
</blockquote>

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">I created a project to get information about available Assemblies and Types in <a href="https://twitter.com/hashtag/AzureFunctions?src=hash">#AzureFunctions</a><a href="https://t.co/L9aSd7NZ2h">https://t.co/L9aSd7NZ2h</a><a href="https://twitter.com/AzureFunctions">@AzureFunctions</a></p>&mdash; Henrik Lau Eriksson (@hlaueriksson) <a href="https://twitter.com/hlaueriksson/status/858659003622203392">April 30, 2017</a></blockquote>
<script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<p>I basically wanted to get information about available <code class="language-plaintext highlighter-rouge">Assemblies</code> and <code class="language-plaintext highlighter-rouge">Types</code> in the Azure Functions hosting environment.</p>

<p>The code and all the information gathered can be viewed at:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/AzureFunctionsInfo">https://github.com/hlaueriksson/AzureFunctionsInfo</a></li>
</ul>

<p>For example, this is some important information I found out:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">"Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"</code>
    <ul>
      <li>Depend on <a href="https://www.nuget.org/packages/Newtonsoft.Json/9.0.1">https://www.nuget.org/packages/Newtonsoft.Json/9.0.1</a></li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">"System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"</code>
    <ul>
      <li>Depend on <a href="https://www.nuget.org/packages/System.Net.Http/4.0.0">https://www.nuget.org/packages/System.Net.Http/4.0.0</a></li>
    </ul>
  </li>
</ul>

<p>The type <code class="language-plaintext highlighter-rouge">TraceWriter</code> comes from:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
  </span><span class="nl">"Type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Microsoft.Azure.WebJobs.Host.TraceWriter"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"Assembly"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Microsoft.Azure.WebJobs.Host, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<ul>
  <li>Depend on <a href="https://www.nuget.org/packages/Microsoft.Azure.WebJobs/2.0.0">https://www.nuget.org/packages/Microsoft.Azure.WebJobs/2.0.0</a></li>
</ul>

<h2 id="latest-functions">latest-functions</h2>

<p>Okay, so now it is time to cover the actual Azure Functions app I created.
The code was migrated from an existing ASP.NET Core Web API project.</p>

<p>Remember the background:</p>

<ul>
  <li><a href="/post/getting-started-with-react/">Getting started with React</a></li>
</ul>

<p>The app has one query function to get data on my latest:</p>

<ul>
  <li>Blog post</li>
  <li>GitHub repo and commit</li>
  <li>Instagram photo</li>
</ul>

<p>The source code is available at:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/latest-functions">https://github.com/hlaueriksson/latest-functions</a></li>
</ul>

<p>The project was created with the <em>Azure Functions CLI</em> tool:</p>

<ul>
  <li>Language: <code class="language-plaintext highlighter-rouge">C#</code>
    <ul>
      <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-csharp">Azure Functions C# developer reference</a></li>
    </ul>
  </li>
  <li>Template: <code class="language-plaintext highlighter-rouge">HttpTrigger</code>
    <ul>
      <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook#httptrigger">HTTP trigger</a></li>
    </ul>
  </li>
  <li>Name: <code class="language-plaintext highlighter-rouge">Query</code></li>
</ul>

<p>After the scaffolding, the generated code needed to be modified.</p>

<p>This is the end result:</p>

<p><code class="language-plaintext highlighter-rouge">function.json</code></p>

<blockquote>
  <p>Defines the function bindings and other configuration settings</p>
</blockquote>

<script src="https://gist.github.com/hlaueriksson/7ceeded33ebe530c3456a03ba15ee489.js?file=function.json"> </script>

<ul>
  <li>authLevel set to <code class="language-plaintext highlighter-rouge">anonymous</code>
    <ul>
      <li>No API key is required</li>
    </ul>
  </li>
  <li>route <code class="language-plaintext highlighter-rouge">query/{queryName}</code> added
    <ul>
      <li>How to customize the route: <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook#customizing-the-http-endpoint">Customizing the HTTP endpoint</a></li>
    </ul>
  </li>
  <li>method <code class="language-plaintext highlighter-rouge">post</code> added
    <ul>
      <li>Array of the HTTP methods to which the function will respond</li>
    </ul>
  </li>
</ul>

<p><code class="language-plaintext highlighter-rouge">project.json</code></p>

<blockquote>
  <p>To use NuGet packages in a C# function, upload a <em>project.json</em> file to the function’s folder in the function app’s file system.</p>
</blockquote>

<script src="https://gist.github.com/hlaueriksson/7ceeded33ebe530c3456a03ba15ee489.js?file=project.json"> </script>

<ul>
  <li>Only the .NET Framework 4.6 is supported, specify <code class="language-plaintext highlighter-rouge">net46</code></li>
  <li><code class="language-plaintext highlighter-rouge">CommandQuery.AzureFunctions</code>, version <code class="language-plaintext highlighter-rouge">0.2.0</code>
    <ul>
      <li>This will make the use of queries and query handlers possible in the function</li>
    </ul>
  </li>
</ul>

<p><code class="language-plaintext highlighter-rouge">bin</code> folder</p>

<blockquote>
  <p>If you need to reference a private assembly, you can upload the assembly file into a <code class="language-plaintext highlighter-rouge">bin</code> folder relative to your function and reference it by using the file name (e.g. <code class="language-plaintext highlighter-rouge">#r "MyAssembly.dll"</code>).</p>
</blockquote>

<p><img src="latest-functions-query-bin.png" alt="bin" /></p>

<ul>
  <li>The queries and query handlers used in this function are located in <code class="language-plaintext highlighter-rouge">Latest.dll</code></li>
  <li>Code: <a href="https://github.com/hlaueriksson/latest-functions/tree/v1.0/src/Latest">Latest</a></li>
</ul>

<p>Make sure that private assemblies are built with <code class="language-plaintext highlighter-rouge">&lt;TargetFramework&gt;net46&lt;/TargetFramework&gt;</code>.</p>

<p><code class="language-plaintext highlighter-rouge">run.csx</code></p>

<p>This is the code for the actual function. Written in <em>scriptcs</em>, you can enjoy a relaxed C# scripting syntax.</p>

<script src="https://gist.github.com/hlaueriksson/7ceeded33ebe530c3456a03ba15ee489.js?file=run.csx"> </script>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">#r "Latest.dll"</code> directive reference the query assembly from the <code class="language-plaintext highlighter-rouge">bin</code> folder</li>
  <li>Import the namespaces <code class="language-plaintext highlighter-rouge">System.Reflection</code> and <code class="language-plaintext highlighter-rouge">CommandQuery.AzureFunctions</code></li>
  <li>Create a static instance of <code class="language-plaintext highlighter-rouge">QueryFunction</code> and inject a <code class="language-plaintext highlighter-rouge">QueryProcessor</code> with the query <code class="language-plaintext highlighter-rouge">Assembly</code>. This will make IoC container find the correct query handlers for the queries.</li>
  <li>Add the <code class="language-plaintext highlighter-rouge">string queryName</code> argument to the function signature so the corresponding <code class="language-plaintext highlighter-rouge">route</code> will work</li>
  <li>Let the <code class="language-plaintext highlighter-rouge">QueryFunction</code> handle the query and return the result</li>
</ul>

<p>When the code is done, only four things remains to get it running in the cloud:</p>

<ol>
  <li>Push to <a href="https://github.com/">GitHub</a>, <a href="https://bitbucket.org">Bitbucket</a> or <a href="https://www.visualstudio.com/team-services/">Visual Studio Team Services</a></li>
  <li>Log in to the <a href="https://portal.azure.com">Azure portal</a></li>
  <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function#create-a-function-app">Create a function app</a></li>
  <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-continuous-deployment#set-up-continuous-deployment">Set up continuous deployment</a></li>
</ol>

<p>The end result of all this can be viewed at:</p>

<ul>
  <li><a href="http://henrik.laueriksson.com/latest/">http://henrik.laueriksson.com/latest/</a></li>
</ul>

<p>The code for the SPA that uses the function:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/latest/tree/react">https://github.com/hlaueriksson/latest</a></li>
</ul>

<h2 id="testing">Testing</h2>

<p>While building your functions, you want to test early and often.</p>

<p>Run the functions locally with the command:</p>

<p><code class="language-plaintext highlighter-rouge">func host start</code></p>

<p>If you need to specific CORS origins use something like:</p>

<p><code class="language-plaintext highlighter-rouge">func host start --cors http://localhost:3000</code></p>

<p>When the functions are running locally you can manually test them with tools like <em>Postman</em> or <em>curl</em>.</p>

<p>Advice from Microsoft:</p>

<ul>
  <li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-test-a-function">Strategies for testing your code in Azure Functions</a></li>
</ul>

<h3 id="postman">Postman</h3>

<p><img src="postman.png" alt="Postman" /></p>

<p>The Postman collection for this function:</p>

<ul>
  <li><a href="latest-functions.postman_collection.json">latest-functions.postman_collection.json</a>
    <ul>
      <li>With both local and cloud endpoints</li>
    </ul>
  </li>
</ul>

<h3 id="curl">curl</h3>

<p>Commands for this function hitting the cloud endpoints:</p>

<p><code class="language-plaintext highlighter-rouge">curl -X POST http://latest-functions.azurewebsites.net/api/query/BlogQuery -H "content-type: application/json" -d "{}"</code></p>

<p><code class="language-plaintext highlighter-rouge">curl -X POST http://latest-functions.azurewebsites.net/api/query/GitHubQuery -H "content-type: application/json" -d "{'Username': 'hlaueriksson'}"</code></p>

<p><code class="language-plaintext highlighter-rouge">curl -X POST http://latest-functions.azurewebsites.net/api/query/InstagramQuery -H "content-type: application/json" -d "{}"</code></p>

<h3 id="resources">Resources</h3>

<p>Other people are testing the functions with code:</p>

<ul>
  <li><a href="https://blog.kloud.com.au/2016/09/05/testing-azure-functions-in-emulated-environment-with-scriptcs/">Testing Azure Functions in Emulated Environment with ScriptCs</a></li>
  <li><a href="https://blog.kloud.com.au/2017/01/20/testing-precompiled-azure-functions/">Testing Precompiled Azure Functions</a></li>
  <li><a href="https://mobilefirstcloudfirst.net/2017/01/building-testing-deploying-precompiled-azure-functions/">Building, testing and deploying precompiled Azure Functions</a></li>
</ul>

<p>If you are using <code class="language-plaintext highlighter-rouge">CommandQuery</code> together with Azure Functions you can unit test your command and query handlers.</p>

<p>For example like this:</p>

<ul>
  <li><a href="https://github.com/hlaueriksson/latest-functions/tree/v1.0/src/Latest/Latest.Specs/Queries">Latest.Specs/Queries</a></li>
</ul>

<p><em>(Yeah, I know! Not really unit testing, but you get the point)</em></p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="Azure" /><category term="C#" /><summary type="html"><![CDATA[I set out to learn about Azure Functions and this is the knowledge I have gathered so far.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/serverless-with-azure-functions/vsc.png" /><media:content medium="image" url="https://conductofcode.io/post/serverless-with-azure-functions/vsc.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Secure and explore ASP.NET Core Web APIs</title><link href="https://conductofcode.io/post/secure-and-explore-aspnet-core-web-apis/" rel="alternate" type="text/html" title="Secure and explore ASP.NET Core Web APIs" /><published>2017-03-31T23:00:00+02:00</published><updated>2017-11-02T21:00:00+01:00</updated><id>https://conductofcode.io/post/secure-and-explore-aspnet-core-web-apis</id><content type="html" xml:base="https://conductofcode.io/post/secure-and-explore-aspnet-core-web-apis/"><![CDATA[<p>How to create a ASP.NET Core Web API, secure it with <a href="https://jwt.io">JSON Web Tokens</a> and explore it with <a href="http://swagger.io/swagger-ui/">Swagger UI</a> and <a href="https://www.getpostman.com">Postman</a>.</p>

<p>You can view the example code in this post at <a href="https://github.com/hlaueriksson/ConductOfCode">https://github.com/hlaueriksson/ConductOfCode</a></p>

<h2 id="aspnet-core-web-api">ASP.NET Core Web API</h2>

<p>I installed the new Visual Studio 2017 and created a new ASP.NET Core Web Application.</p>

<p><img src="vs-new-project.png" alt="New ASP.NET Core Web Application" /></p>

<p>Then I added these dependencies:</p>

<ul>
  <li>Swagger with <a href="https://www.nuget.org/packages/Swashbuckle.AspNetCore/">Swashbuckle.AspNetCore</a></li>
  <li>JSON Web Tokens (JWT) with <a href="https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer/">Microsoft.AspNetCore.Authentication.JwtBearer</a></li>
</ul>

<p>The subject in this blog post is the <code class="language-plaintext highlighter-rouge">StackController</code>:</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=StackController.cs"> </script>

<ul>
  <li>
    <p>The controller provides a REST interface for an in-memory stack. It’s the same example code I have used in a <a href="/post/reuse-specflow-features-to-test-both-via-api-and-browser/">previous</a> blog post.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">[Authorize]</code> attribute specifies that the actions in the controller requires authorization. It will be handled with JSON Web Tokens. The configuration for this will be done in the <code class="language-plaintext highlighter-rouge">Startup</code> class.</p>
  </li>
  <li>
    <p>The actions are decorated with <code class="language-plaintext highlighter-rouge">SwaggerResponse</code> attributes. This makes Swashbuckle understand the types returned for different status codes.</p>
  </li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">appsettings.json</code> file has some custom configuration for the JWT authentication:</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=appsettings.json"> </script>

<ul>
  <li>
    <p>In this example we will use three things when issuing tokens; <code class="language-plaintext highlighter-rouge">Audience</code>, <code class="language-plaintext highlighter-rouge">Issuer</code> and the <code class="language-plaintext highlighter-rouge">SigningKey</code></p>
  </li>
  <li>
    <p>The values for <code class="language-plaintext highlighter-rouge">Audience</code> and <code class="language-plaintext highlighter-rouge">Issuer</code> can be an arbitrary string. They will be used as claims and the tokens that are issued will contain them.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">SigningKey</code> is used when generating the hashed signature for the token. The key must be kept secret. You probably want to use the <a href="https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets">Secret Manager</a> to secure the key.</p>
  </li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">TokenOptions</code> class is the type safe representation of the configuration in the appsettings:</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=TokenOptions.cs"> </script>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">Type</code> defaults to <code class="language-plaintext highlighter-rouge">Bearer</code>, which is the schema used by JWT.</p>
  </li>
  <li>
    <p>The expiration of the tokens defaults to one hour.</p>
  </li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">TokenOptions</code> will be used in two places in the codebase. Therefor I extracted some convenience methods into <code class="language-plaintext highlighter-rouge">TokenOptionsExtensions</code>:</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=TokenOptionsExtensions.cs"> </script>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">GetExpiration</code> returns a <code class="language-plaintext highlighter-rouge">DateTime</code> (UTC) indicating when the issued token should expire.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">GetSigningCredentials</code> returns an object that will be used for generating the token signature. <code class="language-plaintext highlighter-rouge">HmacSha256</code> is the algorithm used.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">GetSymmetricSecurityKey</code> returns an object that wraps the value of the <code class="language-plaintext highlighter-rouge">SigningKey</code> as a byte array.</p>
  </li>
</ul>

<blockquote>
  <p>The <code class="language-plaintext highlighter-rouge">Startup</code> class configures the request pipeline that handles all requests made to the application.</p>
</blockquote>

<p>Swagger, SwaggerUI and JwtBearerAuthentication is configured here:</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=Startup.cs"> </script>

<p>ConfigureServices:</p>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">AddOptions</code> method adds services required for using options.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">Configure&lt;TokenOptions&gt;</code> method registers a configuration instance which <code class="language-plaintext highlighter-rouge">TokenOptions</code> will bind against. The <code class="language-plaintext highlighter-rouge">TokenOptions</code> from <code class="language-plaintext highlighter-rouge">appsettings.json</code> will be accessible and available for dependency injection.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">AddSwaggerGen</code> method registers the Swagger generator.</p>
  </li>
</ul>

<p>Configure:</p>

<ul>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">UseSwagger</code> method exposes the generated Swagger as JSON endpoint. It will be available under the route <code class="language-plaintext highlighter-rouge">/swagger/v1/swagger.json</code>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">UseSwaggerUI</code> method exposes Swagger UI, the auto-generated interactive documentation. It will be available under the route <code class="language-plaintext highlighter-rouge">/swagger</code>.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">InjectOnCompleteJavaScript</code> method injects JavaScript to invoke when the Swagger UI has successfully loaded. I will get back to this later.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">UseStaticFiles</code> method enables static file serving. The injected JavaScript for the Swagger UI is served from the <code class="language-plaintext highlighter-rouge">wwwroot</code> folder.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">UseJwtBearerAuthentication</code> method adds JWT bearer token middleware to the web application pipeline.
<code class="language-plaintext highlighter-rouge">Audience</code> and <code class="language-plaintext highlighter-rouge">Issuer</code> will be used to validate the tokens.
The <code class="language-plaintext highlighter-rouge">SigningKey</code> for token signatures is specified here.
The authorization to the <code class="language-plaintext highlighter-rouge">StackController</code> will now be handled with JWT.</p>
  </li>
</ul>

<p>Read more about Swashbuckle/Swagger here: <a href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore">https://github.com/domaindrivendev/Swashbuckle.AspNetCore</a></p>

<p>To issue tokens, let’s introduce the <code class="language-plaintext highlighter-rouge">AuthenticationController</code>:</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=AuthenticationController.cs"> </script>

<ul>
  <li>
    <p>An <code class="language-plaintext highlighter-rouge">IOptions&lt;TokenOptions&gt;</code> object is injected to the constructor. The configuration is used when tokens are issues.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">JwtSecurityToken</code> class is used to represent a JSON Web Token.</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">JwtSecurityTokenHandler</code> class writes a JWT as a JSON Compact serialized format string.</p>
  </li>
  <li>
    <p>Actual authentication is out of the scope of this blog post. You may want to look at <a href="http://docs.identityserver.io/en/release/">IdentityServer4</a>.</p>
  </li>
  <li>
    <p>You probably want to require SSL/HTTPS for the API.</p>
  </li>
</ul>

<p>The response from the <code class="language-plaintext highlighter-rouge">Token</code> action looks like this:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
  </span><span class="nl">"token_type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Bearer"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"access_token"</span><span class="p">:</span><span class="w"> </span><span class="s2">"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTA5ODkyNzUsImlzcyI6IkNvbmR1Y3RPZkNvZGUiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjUwNDgwIn0.iSP0Go20rzg69yxERldCCl4MRpCfC1JwcJTstkcc_Ss"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"expires_in"</span><span class="p">:</span><span class="w"> </span><span class="mi">3600</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Audience</code>, <code class="language-plaintext highlighter-rouge">Issuer</code> and <code class="language-plaintext highlighter-rouge">Expiration</code> are included in the JWT payload:</p>

<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
  </span><span class="nl">"exp"</span><span class="p">:</span><span class="w"> </span><span class="mi">1490989275</span><span class="p">,</span><span class="w">
  </span><span class="nl">"iss"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ConductOfCode"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"aud"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://localhost:50480"</span><span class="w">
</span><span class="p">}</span></code></pre></figure>

<p>If you copy the value of the <code class="language-plaintext highlighter-rouge">access_token</code>, you can use <a href="https://jwt.io">https://jwt.io</a> to view the decoded content of the JWT:</p>

<p><img src="jwt-io.png" alt="jwt.io" /></p>

<p>When accessing the <code class="language-plaintext highlighter-rouge">StackController</code>, a JWT should be sent in the HTTP Authorization header:</p>

<figure class="highlight"><pre><code class="language-txt" data-lang="txt">Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTA5ODkyNzUsImlzcyI6IkNvbmR1Y3RPZkNvZGUiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjUwNDgwIn0.iSP0Go20rzg69yxERldCCl4MRpCfC1JwcJTstkcc_Ss</code></pre></figure>

<p>Read more about JWT here: <a href="https://jwt.io/introduction/">https://jwt.io/introduction/</a></p>

<p>The request and response classes:</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=Token.cs"> </script>

<h2 id="swagger-ui">Swagger UI</h2>

<p>We can explore the API and the <code class="language-plaintext highlighter-rouge">StackController</code> with Swagger UI.</p>

<p>The Swagger UI in this example is available at <code class="language-plaintext highlighter-rouge">http://localhost:50480/swagger/</code></p>

<p>The Swagger specification file looks like this: <a href="swagger.json">swagger.json</a></p>

<p>Because the API is using JwtBearerAuthentication, we will now get a <code class="language-plaintext highlighter-rouge">401</code> <code class="language-plaintext highlighter-rouge">Unauthorized</code> if we don’t provide the correct HTTP Authorization header.</p>

<p>To fix this we can inject some JavaScript to Swagger UI with Swashbuckle. I was reading <a href="http://stevemichelotti.com/customize-authentication-header-in-swaggerui-using-swashbuckle/">Customize Authentication Header in SwaggerUI using Swashbuckle</a> by Steve Michelotti before I was able to do this myself.</p>

<p>There are two approaches and two scripts located in the <code class="language-plaintext highlighter-rouge">wwwroot</code> folder of the project:</p>

<p><img src="vs-wwwroot.png" alt="wwwroot" /></p>

<h3 id="authorization1js">authorization1.js</h3>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=authorization1.js"> </script>

<ol>
  <li>
    <p>JQuery is used to post to the <code class="language-plaintext highlighter-rouge">AuthenticationController</code> and get a valid JWT</p>
  </li>
  <li>
    <p>When the response is returned, the <code class="language-plaintext highlighter-rouge">access_token</code> is added to the authorization header</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">StackController</code> actions should now return responses with status codes <code class="language-plaintext highlighter-rouge">200</code></p>
  </li>
</ol>

<p>Inject the script to Swagger UI in <code class="language-plaintext highlighter-rouge">Startup.cs</code>:</p>

<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="n">app</span><span class="p">.</span><span class="nf">UseSwaggerUI</span><span class="p">(</span><span class="n">c</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="n">c</span><span class="p">.</span><span class="nf">SwaggerEndpoint</span><span class="p">(</span><span class="s">"/swagger/v1/swagger.json"</span><span class="p">,</span> <span class="s">"ConductOfCode"</span><span class="p">);</span>
    <span class="n">c</span><span class="p">.</span><span class="nf">InjectOnCompleteJavaScript</span><span class="p">(</span><span class="s">"/swagger-ui/authorization1.js"</span><span class="p">);</span>
<span class="p">});</span></code></pre></figure>

<p>The result looks like this:</p>

<p><img src="swagger-ui-authorization1.png" alt="authorization1.js" /></p>

<ul>
  <li>
    <p>Enter a username and password, click the <em>Get token</em> button to set the authorization header</p>
  </li>
  <li>
    <p>The <em>Get token</em> button only needs to be clicked once per page load</p>
  </li>
</ul>

<h3 id="authorization2js">authorization2.js</h3>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=authorization2.js"> </script>

<ol>
  <li>
    <p>CryptoJS is used to generate a valid JWT</p>

    <ul>
      <li>The JWT payload and the <code class="language-plaintext highlighter-rouge">SigningKey</code> must be known</li>
    </ul>
  </li>
  <li>
    <p>The generated token is added to the authorization header</p>
  </li>
  <li>
    <p>The <code class="language-plaintext highlighter-rouge">StackController</code> actions should now return responses with status codes <code class="language-plaintext highlighter-rouge">200</code></p>
  </li>
</ol>

<p>Inject the scripts to Swagger UI in <code class="language-plaintext highlighter-rouge">Startup.cs</code>:</p>

<figure class="highlight"><pre><code class="language-cs" data-lang="cs"><span class="n">app</span><span class="p">.</span><span class="nf">UseSwaggerUI</span><span class="p">(</span><span class="n">c</span> <span class="p">=&gt;</span>
<span class="p">{</span>
    <span class="n">c</span><span class="p">.</span><span class="nf">SwaggerEndpoint</span><span class="p">(</span><span class="s">"/swagger/v1/swagger.json"</span><span class="p">,</span> <span class="s">"ConductOfCode"</span><span class="p">);</span>
    <span class="n">c</span><span class="p">.</span><span class="nf">InjectOnCompleteJavaScript</span><span class="p">(</span><span class="s">"https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"</span><span class="p">);</span> <span class="c1">// https://cdnjs.com/libraries/crypto-js</span>
    <span class="n">c</span><span class="p">.</span><span class="nf">InjectOnCompleteJavaScript</span><span class="p">(</span><span class="s">"/swagger-ui/authorization2.js"</span><span class="p">);</span>
<span class="p">});</span></code></pre></figure>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">crypto-js</code> script is injected from a CDN.</li>
</ul>

<p>The result looks like this:</p>

<p><img src="swagger-ui-authorization2.png" alt="authorization2.js" /></p>

<ul>
  <li>Enter audience, issuer, and signing key. A token is generated and the authorization header is set every time the <em>Try it out!</em> button for an action is clicked.</li>
</ul>

<h2 id="postman">Postman</h2>

<p>We can explore the API and the <code class="language-plaintext highlighter-rouge">StackController</code> with Postman.</p>

<p>Download:
<a href="https://www.getpostman.com">https://www.getpostman.com</a></p>

<p>Import the Swagger specification file:</p>

<p><img src="postman-import.png" alt="Import" /></p>

<p>Then the API is available in a collection:</p>

<p><img src="postman-collection.png" alt="Collection" /></p>

<p>Because the API is using JwtBearerAuthentication, we will now get a <code class="language-plaintext highlighter-rouge">401</code> <code class="language-plaintext highlighter-rouge">Unauthorized</code> if we don’t provide the correct HTTP Authorization header.</p>

<p>There are two approaches to fix this.</p>

<h3 id="tests">Tests</h3>

<p>The <code class="language-plaintext highlighter-rouge">Token</code> action in the <code class="language-plaintext highlighter-rouge">AuthenticationController</code> issues tokens.</p>

<p>Add some JavaScript in the <strong>Tests</strong> tab:</p>

<p><img src="postman-tests.png" alt="Tests" /></p>

<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">responseBody</span><span class="p">);</span>
<span class="nx">postman</span><span class="p">.</span><span class="nx">setGlobalVariable</span><span class="p">(</span><span class="dl">"</span><span class="s2">Authorization</span><span class="dl">"</span><span class="p">,</span> <span class="nx">data</span><span class="p">.</span><span class="nx">token_type</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"> </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">data</span><span class="p">.</span><span class="nx">access_token</span><span class="p">);</span></code></pre></figure>

<ul>
  <li>
    <p>When the response is returned, the access_token is stored in the global variable <code class="language-plaintext highlighter-rouge">Authorization</code></p>
  </li>
  <li>
    <p>The request to the <code class="language-plaintext highlighter-rouge">Token</code> action only needs to be sent once per token lifetime (one hour)</p>
  </li>
</ul>

<p>Add Authorization to all actions in the <strong>Headers</strong> tab:</p>

<p><img src="postman-headers.png" alt="Headers" /></p>

<figure class="highlight"><pre><code class="language-txt" data-lang="txt">Authorization:{{Authorization}}</code></pre></figure>

<ul>
  <li>The token is accessed via the global variable <code class="language-plaintext highlighter-rouge">{{Authorization}}</code></li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">StackController</code> actions should now return responses with status codes <code class="language-plaintext highlighter-rouge">200</code>.</p>

<h3 id="pre-request-script">Pre-request Script</h3>

<p>We can add some JavaScript to Postman that generates a valid JWT.
I was reading <a href="https://developer.dansksupermarked.dk/v1/api/guides/jwt-authentication-in-postman/">JWT Authentication in Postman</a> before I was able to do this myself.</p>

<script src="https://gist.github.com/hlaueriksson/0144c69bb6c78a8ecb8a8874a7aa1a29.js?file=authorization3.js"> </script>

<ol>
  <li>
    <p>CryptoJS is used to generate a valid JWT</p>

    <ul>
      <li>The JWT payload and the <code class="language-plaintext highlighter-rouge">SigningKey</code> must be known</li>
    </ul>
  </li>
  <li>
    <p>The generated token is stored in the global variable <code class="language-plaintext highlighter-rouge">Authorization</code></p>
  </li>
</ol>

<p>Add the content of the <code class="language-plaintext highlighter-rouge">authorization3.js</code> file to global variable <code class="language-plaintext highlighter-rouge">authorize</code>:</p>

<p><img src="postman-globals.png" alt="Globals" /></p>

<p>Create an environment and add variables:</p>

<p><img src="postman-environment.png" alt="Environment" /></p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Audience</code>: <code class="language-plaintext highlighter-rouge">http://localhost:50480</code></li>
  <li><code class="language-plaintext highlighter-rouge">Issuer</code>: <code class="language-plaintext highlighter-rouge">ConductOfCode</code></li>
  <li><code class="language-plaintext highlighter-rouge">SigningKey</code>: <code class="language-plaintext highlighter-rouge">cc4435685b40b2e9ddcb357fd79423b2d8e293b897d86f5336cb61c5fd31c9a3</code></li>
</ul>

<p>Add JavaScript to all actions in the <strong>Pre-request Script</strong> tab:</p>

<p><img src="postman-pre-request-script.png" alt="Pre-request Script" /></p>

<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="nb">eval</span><span class="p">(</span><span class="nx">postman</span><span class="p">.</span><span class="nx">getGlobalVariable</span><span class="p">(</span><span class="dl">'</span><span class="s1">authorize</span><span class="dl">'</span><span class="p">));</span>
<span class="nx">authorize</span><span class="p">();</span></code></pre></figure>

<ul>
  <li>
    <p>The JavaScript is accessed from the global variable <code class="language-plaintext highlighter-rouge">authorize</code> and evaluated.</p>
  </li>
  <li>
    <p>The function <code class="language-plaintext highlighter-rouge">authorize</code> is executed and the token is generated.</p>
  </li>
</ul>

<p>The <code class="language-plaintext highlighter-rouge">StackController</code> actions should now return responses with status codes <code class="language-plaintext highlighter-rouge">200</code>.</p>

<p>The collection can be exported:</p>

<p><img src="postman-export.png" alt="Export" /></p>

<ul>
  <li>Perfect for version control</li>
</ul>

<p>The export file looks like this: <a href="ConductOfCode.postman_collection.json">ConductOfCode.postman_collection.json</a></p>

<h3 id="troubleshooting">Troubleshooting</h3>

<p>If you are having problems with JavaScript in Postman,
read <a href="http://blog.getpostman.com/2014/01/27/enabling-chrome-developer-tools-inside-postman/">Enabling Chrome Developer Tools inside Postman</a>.</p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="JWT" /><category term="Swagger" /><category term="Postman" /><category term="C#" /><summary type="html"><![CDATA[How to create a ASP.NET Core Web API, secure it with JSON Web Tokens and explore it with Swagger UI and Postman.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/secure-and-explore-aspnet-core-web-apis/vs.png" /><media:content medium="image" url="https://conductofcode.io/post/secure-and-explore-aspnet-core-web-apis/vs.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Automocking and the Dependency Inversion Principle</title><link href="https://conductofcode.io/post/automocking-and-the-dependency-inversion-principle/" rel="alternate" type="text/html" title="Automocking and the Dependency Inversion Principle" /><published>2017-02-28T21:00:00+01:00</published><updated>2017-02-28T21:00:00+01:00</updated><id>https://conductofcode.io/post/automocking-and-the-dependency-inversion-principle</id><content type="html" xml:base="https://conductofcode.io/post/automocking-and-the-dependency-inversion-principle/"><![CDATA[<p>I had reason to revisit the <a href="/post/automocked-base-class-for-nunit-tests/">automocked base class</a> from a previous blog post.
I am working with another code base and have new opportunities for automocking.
We have a lot of <em>internal</em> classes.
Approximately 30% of the classes are marked as internal.
The old approach did not work anymore.</p>

<p>With an internal subject, I got this error:</p>

<p><img src="CS0060.png" alt="CS0060" /></p>

<p><code class="language-plaintext highlighter-rouge">Inconsistent accessibility: base class 'WithSubject&lt;HelloWorld&gt;' is less accessible than class 'When_GetMessage'</code></p>

<h2 id="the-dependency-inversion-principle">The Dependency Inversion Principle</h2>

<p>The D in SOLID stands for the <em>Dependency Inversion Principle</em>:</p>

<blockquote>
  <p>A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.</p>
</blockquote>

<p>In other words:</p>

<blockquote>
  <p>Depend on abstractions, not on concretions.</p>
</blockquote>

<p>One way to enforce this between projects in C# is to make classes <code class="language-plaintext highlighter-rouge">internal</code>.</p>

<h2 id="the-internal-access-modifier">The internal access modifier</h2>

<p>The <a href="https://msdn.microsoft.com/en-us/library/7c5ka91b.aspx"><code class="language-plaintext highlighter-rouge">internal</code></a> access modifier:</p>

<blockquote>
  <p>Internal types or members are accessible only within files in the same assembly</p>
</blockquote>

<p>This is useful:</p>

<blockquote>
  <p>A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code.</p>
</blockquote>

<p>How can the unit tests access the internal classes then?</p>

<p>The <a href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx"><code class="language-plaintext highlighter-rouge">[InternalsVisibleTo]</code></a> attribute:</p>

<blockquote>
  <p>types that are ordinarily visible only within the current assembly are visible to a specified assembly.</p>
</blockquote>

<p>We will add the attribute to the AssemblyInfo file in the project under test, to make the unit test project a friend assembly.</p>

<p>We will use an IoC container to configure the creation of the internal classes.
The clients will depend on public interfaces and the IoC container.</p>

<h2 id="withfakes">WithFakes</h2>

<p>My favorite framework for testing is still <a href="https://github.com/machine/machine.specifications">Machine.Specifications</a> in combination with <a href="https://github.com/machine/machine.fakes">Machine.Fakes</a> for automocking support.</p>

<p>At work, we use:</p>

<ul>
  <li><a href="https://xunit.github.io/">xUnit.net</a></li>
  <li><a href="https://github.com/moq/moq4">Moq</a></li>
</ul>

<p>I will mimic the <a href="https://github.com/machine/machine.fakes#withfakes">Machine.Fakes</a> <code class="language-plaintext highlighter-rouge">WithFakes</code> base class:</p>

<ul>
  <li>
    <p>The test fixture will inherit from <code class="language-plaintext highlighter-rouge">WithFakes</code></p>
  </li>
  <li>
    <p>Use <code class="language-plaintext highlighter-rouge">The&lt;TFake&gt;()</code> method for creating fakes</p>
  </li>
</ul>

<p>My implementation will use:</p>

<ul>
  <li><a href="https://xunit.github.io/">xUnit.net</a></li>
  <li><a href="https://github.com/moq/moq4">Moq</a></li>
  <li><a href="https://github.com/tkellogg/Moq.AutoMocker">Moq.AutoMocker</a></li>
</ul>

<h2 id="code">Code</h2>

<p>You can get the example code at <a href="https://github.com/hlaueriksson/ConductOfCode">https://github.com/hlaueriksson/ConductOfCode</a></p>

<p><strong>WithFakes</strong></p>

<script src="https://gist.github.com/hlaueriksson/fceb24a6d9fb591519a5988be25dc191.js?file=WithFakes.cs"> </script>

<p>The <code class="language-plaintext highlighter-rouge">Subject&lt;TSubject&gt;()</code> method gives access the class under test.
This is how the error <code class="language-plaintext highlighter-rouge">Inconsistent accessibility: base class 'WithSubject&lt;HelloWorld&gt;' is less accessible than class 'When_GetMessage'</code> is solved.</p>

<p>The <code class="language-plaintext highlighter-rouge">The&lt;TFake&gt;()</code> method gives access to the injected dependencies from the subject.</p>

<p>The <code class="language-plaintext highlighter-rouge">With&lt;TFake&gt;()</code> methods can be used to inject real or fake objects into the subject.</p>

<p><strong>The subject</strong></p>

<script src="https://gist.github.com/hlaueriksson/fceb24a6d9fb591519a5988be25dc191.js?file=HelloWorld.cs"> </script>

<p>The interfaces are <code class="language-plaintext highlighter-rouge">public</code>, the concrete classes are <code class="language-plaintext highlighter-rouge">internal</code>.</p>

<script src="https://gist.github.com/hlaueriksson/fceb24a6d9fb591519a5988be25dc191.js?file=HelloWorldRegistry.cs"> </script>

<p>The creation of internal classes is configured with <a href="https://github.com/structuremap/structuremap">StructureMap</a>, the IoC container we are using.</p>

<p>The <code class="language-plaintext highlighter-rouge">AssemblyInfo.cs</code> is also modified to make the subject accessible for the unit tests:</p>

<p><code class="language-plaintext highlighter-rouge">[assembly: InternalsVisibleTo("ConductOfCode.Tests")]</code>.</p>

<p><strong>The client</strong></p>

<script src="https://gist.github.com/hlaueriksson/fceb24a6d9fb591519a5988be25dc191.js?file=Program.cs"> </script>

<p>The client depends on interfaces and uses the IoC container to create concrete classes.</p>

<p><img src="ConductOfCode.exe.png" alt="ConductOfCode.exe" /></p>

<script src="https://gist.github.com/hlaueriksson/fceb24a6d9fb591519a5988be25dc191.js?file=IoC.cs"> </script>

<p>The IoC container scans the assemblies for registries with configuration.</p>

<p><strong>The tests</strong></p>

<script src="https://gist.github.com/hlaueriksson/fceb24a6d9fb591519a5988be25dc191.js?file=When_GetMessage.cs"> </script>

<p>The <code class="language-plaintext highlighter-rouge">Subject</code> property gives access to the automocked instance via the <code class="language-plaintext highlighter-rouge">Subject&lt;TSubject&gt;()</code> method from the base class.</p>

<p>The <code class="language-plaintext highlighter-rouge">With&lt;TFake&gt;()</code> methods can be used to inject and setup mocks.</p>

<p>The <code class="language-plaintext highlighter-rouge">The&lt;TFake&gt;()</code> method is used for setup and verification of mocks.</p>

<p><strong>The unit test sessions</strong></p>

<p><img src="unit-test-sessions.png" alt="Unit Test Sessions" /></p>]]></content><author><name>{&quot;twitter&quot;=&gt;&quot;hlaueriksson&quot;}</name></author><category term="xUnit" /><category term="Testing" /><category term="C#" /><summary type="html"><![CDATA[I had reason to revisit the automocked base class from a previous blog post. I am working with another code base and have new opportunities for automocking. We have a lot of internal classes. Approximately 30% of the classes are marked as internal. The old approach did not work anymore.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://conductofcode.io/post/automocking-and-the-dependency-inversion-principle/vs.png" /><media:content medium="image" url="https://conductofcode.io/post/automocking-and-the-dependency-inversion-principle/vs.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>