<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: The Transient Thoughts of a Restless Mind</title>
    <description>The latest articles on DEV Community by The Transient Thoughts of a Restless Mind (@transient-thoughts).</description>
    <link>https://dev.to/transient-thoughts</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5815%2F152a44d0-9110-4223-9975-a25b3167627f.png</url>
      <title>DEV Community: The Transient Thoughts of a Restless Mind</title>
      <link>https://dev.to/transient-thoughts</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/transient-thoughts"/>
    <language>en</language>
    <item>
      <title>Angular CLI example for Jest Preview - the visual debugger for Jest</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Mon, 22 Aug 2022 11:22:31 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/angular-cli-example-for-jest-preview-the-visual-debugger-for-jest-3hao</link>
      <guid>https://dev.to/transient-thoughts/angular-cli-example-for-jest-preview-the-visual-debugger-for-jest-3hao</guid>
      <description>&lt;p&gt;Recently, I contributed an Angular CLI example for &lt;a href="https://www.jest-preview.com/" rel="noopener noreferrer"&gt;Jest Preview&lt;/a&gt; in collaboration with its creator, &lt;a href="https://twitter.com/hung_dev" rel="noopener noreferrer"&gt;Hung Viet Nguyen&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jest Preview
&lt;/h2&gt;

&lt;p&gt;Jest Preview is a visual debugger for Jest component tests. It runs a preview server and either displays the rendered DOM of a failed test when the &lt;a href="https://www.jest-preview.com/docs/api/jestpreviewconfigure/#autopreview-boolean" rel="noopener noreferrer"&gt;&lt;code&gt;autoPreview&lt;/code&gt;&lt;/a&gt; option is set or the test we explicitly mark for debugging using the &lt;a href="https://www.jest-preview.com/docs/api/debug/" rel="noopener noreferrer"&gt;&lt;code&gt;debug&lt;/code&gt;&lt;/a&gt; function, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// counter.component.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/user-event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CounterComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./counter.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./counter.component.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CounterComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;initially has a zero count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CounterComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Open http://localhost:3336 to see preview&lt;/span&gt;
    &lt;span class="c1"&gt;// Require to run `jest-preview` server before&lt;/span&gt;
    &lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 👈&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toContainHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7awvwp2j6yjnir2g9sp6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7awvwp2j6yjnir2g9sp6.png" alt="Jest Preview displaying the counter component with a count of 0"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular CLI integration
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/nvh95/jest-preview/tree/main/examples/angular" rel="noopener noreferrer"&gt;The Angular CLI guide for Jest Preview&lt;/a&gt; refers to the common &lt;a href="https://www.jest-preview.com/docs/getting-started/installation" rel="noopener noreferrer"&gt;installation&lt;/a&gt; and &lt;a href="https://www.jest-preview.com/docs/getting-started/usage" rel="noopener noreferrer"&gt;usage&lt;/a&gt; instructions while describing Angular-specific configuration and usage instructions.&lt;/p&gt;

&lt;p&gt;While there is room for improvement, we documented workarounds in the guide. Jest Preview is not currently able to automatically transform &lt;code&gt;styleUrls&lt;/code&gt; in component tests, support inline component styles, or automatically import application-wide stylesheets. Because of this, we have to add stylesheet import statements in our tests to match the external stylesheet used by the component-under-test.&lt;/p&gt;

&lt;p&gt;For example, say we have this counter component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// counter.component.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./counter.component.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// 👈&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;button type="button" (click)="onCount()"&amp;gt;
      The count is:
      &amp;lt;div data-testid="count"&amp;gt;{{ count }}&amp;lt;/div&amp;gt;
    &amp;lt;/button&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;onCount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We would have to add an import statement for &lt;code&gt;./counter.component.css&lt;/code&gt; in our component test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// counter.component.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/user-event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;preview&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-preview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CounterComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./counter.component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./counter.component.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 👈&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CounterComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;displays multiple counts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CounterComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Open http://localhost:3336 to see preview&lt;/span&gt;
    &lt;span class="c1"&gt;// Require to run `jest-preview` server before&lt;/span&gt;
    &lt;span class="nx"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toContainHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvx4027ibh4p1ycnv3q47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvx4027ibh4p1ycnv3q47.png" alt="Jest Preview displaying the counter component with a count of 2"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>jest</category>
      <category>opensource</category>
      <category>testing</category>
    </item>
    <item>
      <title>Docusaurus website for Analog.js - the full-stack meta-framework for Angular using Vite</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Sun, 21 Aug 2022 19:28:06 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/docusaurus-website-for-analogjs-the-full-stack-meta-framework-for-angular-using-vite-239j</link>
      <guid>https://dev.to/transient-thoughts/docusaurus-website-for-analogjs-the-full-stack-meta-framework-for-angular-using-vite-239j</guid>
      <description>&lt;p&gt;&lt;a href="https://twitter.com/brandontroberts"&gt;Brandon Roberts&lt;/a&gt; is creating the first full-stack meta-framework for Angular and it is open sourced under the MIT license.&lt;/p&gt;

&lt;p&gt;Recently, I contributed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A website with documentation using Docusaurus, GitHub Pages, and GitHub Actions&lt;/li&gt;
&lt;li&gt;Cypress end-to-end test suites demonstrating and verifying how to use Cypress with Vite as the development server for an Angular application&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The analogjs.org website
&lt;/h2&gt;

&lt;p&gt;The official website for Analog.js is &lt;a href="https://analogjs.org"&gt;analogjs.org&lt;/a&gt;. I set it up using &lt;a href="https://docusaurus.io/"&gt;Docusaurus&lt;/a&gt; on a free &lt;a href="https://docs.github.com/en/pages"&gt;GitHub Pages&lt;/a&gt; host with the brand-new GitHub Pages experience using GitHub Actions[&lt;a href="https://github.blog/2022-08-10-github-pages-now-uses-actions-by-default/"&gt;blog post&lt;/a&gt;][&lt;a href="https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-with-a-custom-github-actions-workflow"&gt;documentation&lt;/a&gt;], GitHub Environments, and GitHub Deployments.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ImSK0nv7KfY"&gt;
&lt;/iframe&gt;
&lt;br&gt;
I created this video demonstrating how to set up a Docusaurus website from scratch using GitHub Pages and GitHub Actions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The home page
&lt;/h3&gt;

&lt;p&gt;The hero banner on the home page links to the documentation and an Analog.js sandbox on StackBlitz.&lt;/p&gt;

&lt;p&gt;Next, the home page lists the current and upcoming features of Analog.js:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vite-powered&lt;/li&gt;
&lt;li&gt;Hybrid SSR/SSG-support&lt;/li&gt;
&lt;li&gt;File-based routing&lt;/li&gt;
&lt;li&gt;API (server) routes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the Angular CLI has been using Webpack for a number of years, more modern and especially faster alternatives have emerged in the web ecosystem. One of them is &lt;a href="https://vitejs.dev/"&gt;Vite&lt;/a&gt;. Analog.js publishes an Angular plugin for Vite demonstrating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Vite development server&lt;/li&gt;
&lt;li&gt;Bundling an application using Vite&lt;/li&gt;
&lt;li&gt;Unit testing using Vitest&lt;/li&gt;
&lt;li&gt;End-to-end-testing using a Vite development server&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;Navigating to the documentation, the initial version of the website has these pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Installation&lt;/li&gt;
&lt;li&gt;Contributors&lt;/li&gt;
&lt;li&gt;Contributing&lt;/li&gt;
&lt;li&gt;Sponsoring&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Packages
&lt;/h3&gt;

&lt;p&gt;Currently, two npm packages are released and documented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@analogjs/vite-plugin-angular"&gt;&lt;code&gt;@analogjs/vite-plugin-angular&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/create-analog"&gt;&lt;code&gt;create-analog&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first package is a Vite plugin to support Angular applications and the initializer scaffolds an Analog project.&lt;/p&gt;

&lt;h2&gt;
  
  
  End-to-end testing using Cypress and Vite
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.cypress.io/"&gt;Cypress&lt;/a&gt; is a popular end-to-end testing framework. When using the Angular CLI, Webpack is used as the development server for Angular applications. &lt;a href="https://github.com/analogjs/analog"&gt;The Analog.js repository&lt;/a&gt; covers &lt;a href="https://angular.io/start"&gt;the Angular Getting Started tutorial application&lt;/a&gt; with end-to-end tests using Cypress with the Vite development server.&lt;/p&gt;

&lt;h2&gt;
  
  
  More to come
&lt;/h2&gt;

&lt;p&gt;Analog.js is just getting started. There are plenty of areas to contribute in. Contribute to &lt;a href="https://github.com/analogjs/analog/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc"&gt;Analog.js' GitHub issues&lt;/a&gt; or &lt;a href="https://analogjs.org/docs/sponsoring"&gt;support the core team on GitHub Sponsors&lt;/a&gt; to help make it happen.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>vite</category>
      <category>docusaurus</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Spectacular prerelease v0.5 supports standalone feature tests and uses partial Ivy compilation</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Wed, 10 Aug 2022 18:53:38 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/spectacular-prerelease-v05-supports-standalone-feature-tests-and-uses-partial-ivy-compilation-6i8</link>
      <guid>https://dev.to/transient-thoughts/spectacular-prerelease-v05-supports-standalone-feature-tests-and-uses-partial-ivy-compilation-6i8</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover art by DALL-E.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In July 2022, we &lt;a href="https://github.com/ngworker/ngworker/releases/tag/spectacular-v0.5.0"&gt;published the version 0.5.0 of Spectacular&lt;/a&gt;, the integration testing library for Angular.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that for prerelase versions, that is versions &amp;lt;1.0.0, minor version increases indicate breaking changes, for example releasing version 0.4.0 introduces at least one breaking change compared to version 0.3.0. Patch version increases for prerelease versions indicate bugfixes, refactors, performance improvements, and/or feature additions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's discuss the features and breaking changes of these versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Partial Ivy compilation
&lt;/h2&gt;

&lt;p&gt;Spectacular version 0.1.0-0.4.0 are compiled as View Engine-compatible bundles requiring the Angular Compatibility Compiler (NGCC) to be consumed.&lt;/p&gt;

&lt;p&gt;As of version 0.5.0, Spectacular is partially Ivy compiled as is the recommended practice for Angular libraries targeting Angular &amp;lt;=12.2.0. Starting with the future Angular version that removes NGCC, View Engine-compatible libraries stop working.&lt;/p&gt;

&lt;p&gt;The partial compilation is a performance improvement as most of the library is compiled before being published to a package registry. However, component templates are still required to be compiled in the context of an application.&lt;/p&gt;

&lt;p&gt;To use partial Ivy compilation, Spectacular version 0.5.0 requires at least Angular 12.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standalone feature test provider
&lt;/h2&gt;

&lt;p&gt;With the introduction of standalone Angular components and other standalone Angular APIs starting in Angular version 14 where standalone APIs are considered in &lt;em&gt;developer preview&lt;/em&gt;, we start exposing standalone APIs in Spectacular.&lt;/p&gt;

&lt;p&gt;Spectacular's first standalone API is a standalone provider factory for Spectacular's Feature testing API.&lt;/p&gt;

&lt;p&gt;Spectacular version 0.5.0 introduces &lt;a href="https://ngworker.github.io/ngworker/docs/api/modules#providespectacularfeaturetest"&gt;&lt;code&gt;provideSpectacularFeatureTest&lt;/code&gt;&lt;/a&gt; that configures the feature-aware navigation services &lt;a href="https://ngworker.github.io/ngworker/docs/api/classes/SpectacularFeatureLocation"&gt;&lt;code&gt;SpectacularFeatureLocation&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://ngworker.github.io/ngworker/docs/api/classes/SpectacularFeatureRouter"&gt;&lt;code&gt;SpectacularFeatureRouter&lt;/code&gt;&lt;/a&gt; for standalone Angular features.&lt;/p&gt;

&lt;p&gt;Feature testing a standalone Angular feature using Angular Testing Library and Spectacular:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provideSpectacularFeatureTest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SpectacularAppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SpectacularFeatureLocation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SpectacularFeatureRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ngworker/spectacular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Matcher&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/user-event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;crisisCenterPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tour-of-heroes/crisis-center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findCrisisCenterHomeGreeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/welcome to the crisis center/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findCrisisLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Exclude&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Matcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findNameControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findByPlaceholderText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/name/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findSaveButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/save/i&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findSelectedCrisis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Matcher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.selected a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;debugElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SpectacularAppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;provideSpectacularFeatureTest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;featurePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crisisCenterPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SpectacularFeatureLocation&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SpectacularFeatureRouter&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Edit crisis from crisis detail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crisisId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;~&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;crisisId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findNameControl&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findNameControl&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The global temperature is rising&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findSaveButton&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findSelectedCrisis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/the global temperature is rising/i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`~/;id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;crisisId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;foo=foo`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Edit crisis from crisis center home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigateByUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;~/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findCrisisLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/procrastinators meeting delayed again/i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findNameControl&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findNameControl&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Coral reefs are dying&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findSaveButton&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findCrisisCenterHomeGreeting&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;findSelectedCrisis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/coral reefs are dying/i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comparing the previous example to the following code snippet, the difference is in the &lt;code&gt;setup&lt;/code&gt; &lt;a href="https://medium.com/@kolodny/testing-with-sifers-c9d6bb5b362"&gt;SIFERS&lt;/a&gt; where we use &lt;a href="https://ngworker.github.io/ngworker/docs/api/modules#providespectacularfeaturetest"&gt;&lt;code&gt;provideSpectacularFeatureTest&lt;/code&gt;&lt;/a&gt; instead of &lt;a href="https://ngworker.github.io/ngworker/docs/api/classes/SpectacularFeatureTestingModule"&gt;&lt;code&gt;SpectacularFeatureTestingModule&lt;/code&gt;&lt;/a&gt; to adjust the options configuring Angular Testing Library's &lt;a href="https://testing-library.com/docs/angular-testing-library/api#render"&gt;&lt;code&gt;render&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;

&lt;p&gt;Feature test setup &lt;a href="https://medium.com/@kolodny/testing-with-sifers-c9d6bb5b362"&gt;SIFERS&lt;/a&gt; for an Angular feature module using Angular Testing Library and Spectacular:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;SpectacularAppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SpectacularFeatureLocation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SpectacularFeatureRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SpectacularFeatureTestingModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ngworker/spectacular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/user-event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;CrisisCenterModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;crisisCenterPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tour-of-heroes/crisis-center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;debugElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SpectacularAppComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;SpectacularFeatureTestingModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withFeature&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;featureModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CrisisCenterModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;featurePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crisisCenterPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SpectacularFeatureLocation&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SpectacularFeatureRouter&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://github.com/ngworker/ngworker/tree/main/packages/spectacular"&gt;the source code for Spectacular&lt;/a&gt; for more examples using the feature testing API or visit  &lt;a href="https://ngworker.github.io/ngworker/docs/feature-testing"&gt;our documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>angular</category>
      <category>testing</category>
      <category>spectacular</category>
    </item>
    <item>
      <title>Spectacular prerelease v0.4 reintroduces the required pipeName option for pipe harnesses</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Wed, 10 Aug 2022 18:50:29 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/spectacular-prerelease-v04-reintroduces-the-required-pipename-option-for-pipe-harnesses-23b7</link>
      <guid>https://dev.to/transient-thoughts/spectacular-prerelease-v04-reintroduces-the-required-pipename-option-for-pipe-harnesses-23b7</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover art by DALL-E.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In July 2022, we &lt;a href="https://github.com/ngworker/ngworker/releases/tag/spectacular-v0.4.0"&gt;published the version 0.4.0 prerelease of Spectacular&lt;/a&gt;, the integration testing library for Angular.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that for prerelase versions, that is versions &amp;lt;1.0.0, minor version increases indicate breaking changes, for example releasing version 0.4.0 introduces at least one breaking change compared to version 0.3.0. Patch version increases for prerelease versions indicate bugfixes, refactors, performance improvements, and/or feature additions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's discuss the breaking changes between prerelease versions 0.2.0-0.4.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeName option for pipe harnesses is reintroduced
&lt;/h2&gt;

&lt;p&gt;Back in Spectacular prerelease version 0.3.0, released in May 2022, we removed the &lt;code&gt;pipeName&lt;/code&gt; option from the &lt;code&gt;createPipeHarness&lt;/code&gt; factory to make Angular pipe testing easier. This was a breaking change as the &lt;code&gt;pipeName&lt;/code&gt; option was removed entirely in version 0.3.0.&lt;/p&gt;

&lt;p&gt;Unfortunately, a function we used internally for determining the pipe name was removed from Angular as it was a leftover from Angular View Engine.&lt;/p&gt;

&lt;p&gt;Because of this, Spectacular version 0.4.0 introduces the breaking change of adding back the required &lt;code&gt;pipeName&lt;/code&gt; option for &lt;code&gt;createPipeHarness&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Spectacular version 0.3.0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;harness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createPipeHarness&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PowPipe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spectacular versions &amp;lt;0.3.0 &amp;gt;=0.4.0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;harness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createPipeHarness&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PowPipe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pipeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read &lt;a href="https://ngworker.github.io/ngworker/docs/pipe-testing"&gt;the documentation for Spectacular's Pipe testing API&lt;/a&gt; for full examples of Angular pipe integration tests.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>angular</category>
      <category>testing</category>
      <category>spectacular</category>
    </item>
    <item>
      <title>Working on Lumberjack v14, the extensible logging library for Angular</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Tue, 09 Aug 2022 19:47:56 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/working-on-the-version-14-release-of-lumberjack-the-extensible-logging-library-for-angular-4f7p</link>
      <guid>https://dev.to/transient-thoughts/working-on-the-version-14-release-of-lumberjack-the-extensible-logging-library-for-angular-4f7p</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover illustration by DALL-E.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;@nachovazquez and I have been working on the next release of &lt;a href="https://www.npmjs.com/package/@ngworker/lumberjack" rel="noopener noreferrer"&gt;Lumberjack&lt;/a&gt; for a few months.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining developer tooling
&lt;/h2&gt;

&lt;p&gt;When we implemented version 2 of Lumberjack, we used the Angular CLI with customized Angular architect configurations to support workspace library projects, ESLint, Prettier, and Jest.&lt;/p&gt;

&lt;p&gt;Maintaining developer tooling is quite a task on its own. We love &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx&lt;/a&gt; but at the time, Nx was behind major Angular releases for several months which isn't suitable for an open-source library.&lt;/p&gt;

&lt;p&gt;Since then, a lot has happened in the realm of Nx. The release cadence of Nx is now independent of Angular while major and minor versions of Angular gain native support within a few days or weeks.&lt;/p&gt;

&lt;p&gt;We want to spend the majority of our time contributing features and addressing issues, not maintaining developer tooling and configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-version compatibility
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3w5fln2mgdks6kii142.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3w5fln2mgdks6kii142.png" alt="The current Lumberjack CI workflow verifying cross-version Angular compatibility"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the current version of Lumberjack, version 2.0, we are able to support many major and minor releases of Angular which is important to a plugin-based library to make it easier for plugin maintainers.&lt;/p&gt;

&lt;p&gt;However, the partial Ivy compilation option was marked as stable in Angular version 12.2. Currently, the latest version of Angular is version 14.1. It is now a matter of time before the Angular Compatibility Compiler (NGCC) is removed from Angular, breaking compatibility with View Engine-compatible library bundles.&lt;/p&gt;

&lt;p&gt;Ideally, we would have loved to continue to support multiple major and minor versions of Angular with one major version of Lumberjack. The version of Angular removing NGCC will be a milestone ending backward compatibility for Angular libraries without additional tooling.&lt;/p&gt;

&lt;p&gt;For Lumberjack version 2, we developed the &lt;a href="https://github.com/ngworker/angular-versions-action" rel="noopener noreferrer"&gt;Angular Versions GitHub Action&lt;/a&gt; to verify cross-version compatibility with Angular, RxJS, TypeScript, and Node.js. However, it supports the Angular CLI, not the Nx CLI.&lt;/p&gt;

&lt;p&gt;Maybe at some point, we can create a similar GitHub action for Nx or extend the support for the Angular Versions action to cover Nx workspaces using the Angular preset.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation for the upcoming Lumberjack releases
&lt;/h2&gt;

&lt;p&gt;For now, we want to continue the work on Lumberjack which has had a broken CI workflow for a year due to our extensive custom developer tooling and CI workflow.&lt;/p&gt;

&lt;p&gt;We want to be ready for the major or minor release of Angular that removes the Angular Compatibility Compiler so that we don't prevent Lumberjack consumers from upgrading to the latest Angular releases.&lt;/p&gt;

&lt;p&gt;We also want to explore new opportunities that weren't available in Angular prior to version 14:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standalone APIs&lt;/li&gt;
&lt;li&gt;Resolving dependencies using the &lt;code&gt;inject&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features are game changers for certain Angular library use cases.&lt;/p&gt;

&lt;p&gt;Lumberjack has a lot of configurations which in version 2 has been available through Angular modules with providers. In a future version of Lumberjack, we plan to add standalone APIs, that is functions accepting options to adjust its returned providers needed by Lumberjack and Lumberjack log drivers.&lt;/p&gt;

&lt;p&gt;Support for the &lt;code&gt;inject&lt;/code&gt; function in class constructors and property initializers can enable us to remove internal dependencies from Lumberjack classes that are meant to be extended:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LumberjackLogger&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ScopedLumberjackLogger&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migrating to an Nx workspace
&lt;/h2&gt;

&lt;p&gt;As migrating a custom Angular CLI workspace is a relatively big effort, we created a new Nx workspace in the separate GitHub repository, &lt;a href="https://github.com/ngworker/lumberjack-next" rel="noopener noreferrer"&gt;&lt;code&gt;ngworker/lumberjack-next&lt;/code&gt;&lt;/a&gt;. Here, you can follow our work if you are interested in seeing our future setup which uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nx&lt;/li&gt;
&lt;li&gt;Cypress&lt;/li&gt;
&lt;li&gt;Distributed Task Execution (DTE) through &lt;a href="https://nx.app/" rel="noopener noreferrer"&gt;Nx Cloud&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an added benefit, this effort starts to bridge the gap between the Lumberjack repository and &lt;a href="https://github.com/ngworker/ngworker" rel="noopener noreferrer"&gt;our ngworker monorepo&lt;/a&gt; which currently contains &lt;a href="https://www.npmjs.com/package/@ngworker/spectacular" rel="noopener noreferrer"&gt;Spectacular&lt;/a&gt; and uses Nx 12 at the time of writing. Additionally, our &lt;a href="https://github.com/ngworker/router-component-store" rel="noopener noreferrer"&gt;ngworker/router-component-store&lt;/a&gt; repository uses Nx 13.&lt;/p&gt;

&lt;p&gt;It would be great to combine all of our Angular libraries into a monorepo to decrease our maintenance efforts. As an added benefit, we could use Spectacular to integration test the Lumberjack and Router ComponentStore libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed Task Execution
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p47xy99dv8q9ylr5ngb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p47xy99dv8q9ylr5ngb.png" alt="The Lumberjack CI workflow using Distributed Task Execution via Nx Cloud"&gt;&lt;/a&gt;&lt;br&gt;
As an added benefit of migrating to an Nx workspace, we will use Distributed Task Execution via Nx Cloud. Even in a small Nx workspace like the Lumberjack codebase, we can benefit from distributing tasks across a number of agents rather than having one GitHub runner for unit tests, one for end-to-end tests, one for lint checks, and one for builds.&lt;/p&gt;

&lt;p&gt;This is a benefit given that most of our unit tests are located in the Lumberjack library project. Instead of waiting for all unit tests to run on a single GitHub runner, the unit tests are distributed to idle agents on a project basis. This results in an overall permanent decrease in CI workflow time as tasks are intelligently distributed by Nx Cloud and the GitHub runner acting as a coordinator based on both historic and actual execution time of tasks.&lt;/p&gt;

&lt;p&gt;Should we manage to combine two or more of our Nx repositories into a single Nx monorepo workspace, the benefits of Distributed Task Execution increase as the difference between execution time of similar targets increase combined with the option to increase the number of available agents. It's worth mentioning that DTE agents are GitHub runners, not machines managed by Nx Cloud. Nx Cloud calculates task execution based on input from the DTE coordinator, also a GitHub runner, and caches target output but targets aren't executed inside the Nx Cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a GitHub Actions concurrency strategy
&lt;/h2&gt;

&lt;p&gt;I also managed to set up a GitHub Actions concurrency strategy ensuring that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workflow runs in progress for the same branch are cancelled when new commits are pushed. This eliminates compute waste.&lt;/li&gt;
&lt;li&gt;Workflow runs on the &lt;code&gt;main&lt;/code&gt; branch, that is when a pull request has been merged, are run sequentially, not in parallel. This prevents multiple releases and other deployment activities with side effects from happening simultaneously so that they don't affect each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take a look at &lt;a href="https://github.com/ngworker/lumberjack-next/blob/c814d5c34017fbce3e5fcdfae6069d1125c4b8e6/.github/workflows/ci.yml" rel="noopener noreferrer"&gt;the &lt;em&gt;CI&lt;/em&gt; workflow in the &lt;code&gt;ngworker/lumberjack-next&lt;/code&gt; repository&lt;/a&gt; if you're interested in Distributed Task Execution using Nx Cloud or GitHub Actions concurrency strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating SonarCloud in an Nx workspace using GitHub Actions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6syc9krrdctga1kuj9hp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6syc9krrdctga1kuj9hp.png" alt="The Lumberjack project on SonarCloud"&gt;&lt;/a&gt;&lt;br&gt;
The Lumberjack vNext CI workflow is also where we will integrate SonarCloud similar to &lt;a href="https://github.com/ngworker/lumberjack/blob/3e595a85159e88ca3b64f58b095eab170b610f17/.github/workflows/ci.yml#L267-L301" rel="noopener noreferrer"&gt;our current CI workflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Currently missing from our Lumberjack vNext effort is ensuring that &lt;a href="https://sonarcloud.io/project/overview?id=ngworker_lumberjack" rel="noopener noreferrer"&gt;our SonarCloud integrations&lt;/a&gt; continue to work so that we can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforce test coverage thresholds&lt;/li&gt;
&lt;li&gt;Eliminate code smells&lt;/li&gt;
&lt;li&gt;Reduce cognitive complexity&lt;/li&gt;
&lt;li&gt;Prevent security hotspots, vulnerabilities, and bugs&lt;/li&gt;
&lt;li&gt;Remove code duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Abandoning the Angular ng-add schematic
&lt;/h2&gt;

&lt;p&gt;@nachovazquez and I have agreed to leave behind the &lt;code&gt;ng-add&lt;/code&gt; Angular schematic for Lumberjack for now. Should we want to add it back to the library, we would have to migrate it to the Nx Devkit with Nx-native end-to-end tests rather than the Angular Devkit and our current custom Jest end-to-end tests.&lt;/p&gt;

&lt;p&gt;For one, the &lt;code&gt;ng-add&lt;/code&gt; schematic isn't the most important feature of Lumberjack. Another reason is that Angular libraries have to expect both legacy applications using Angular modules, in particular an &lt;code&gt;AppModule&lt;/code&gt;, as well as standalone Angular applications without any Angular modules, even without a root Angular module which is typically named &lt;code&gt;AppModule&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Currently, it is not clear how Angular library authors are to support both Angular application types in &lt;code&gt;ng-add&lt;/code&gt; schematics.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>angular</category>
      <category>nx</category>
      <category>github</category>
    </item>
    <item>
      <title>The worst piece of life advice I ever received</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Fri, 15 Jul 2022 19:07:57 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/the-worst-piece-of-life-advice-i-ever-received-3j08</link>
      <guid>https://dev.to/transient-thoughts/the-worst-piece-of-life-advice-i-ever-received-3j08</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/photos/ezpQ4EK1Z38"&gt;Dollar Gill&lt;/a&gt; on Unsplash.&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;Throughout my entire life, I have been given the following advice more times than I can remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not think that you are anything special.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the worst piece of life advice I have ever received and still, it is occasionally given to me in various forms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Law of Jante
&lt;/h2&gt;

&lt;p&gt;I spent my childhood being told by so-called role models that I was dumb and that I would never make anything of myself.&lt;/p&gt;

&lt;p&gt;Growing up further from civilization than the town which the fictional Danish town of Jante is based on, this should come as no surprise.&lt;/p&gt;

&lt;p&gt;The Law of Jante states that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You are not to think you are anything special.&lt;/li&gt;
&lt;li&gt;You are not to think you are as good as we are.&lt;/li&gt;
&lt;li&gt;You are not to think you are smarter than we are.&lt;/li&gt;
&lt;li&gt;You are not to imagine yourself better than we are.&lt;/li&gt;
&lt;li&gt;You are not to think you know more than we do.&lt;/li&gt;
&lt;li&gt;You are not to think you are more important than we are.&lt;/li&gt;
&lt;li&gt;You are not to think you are good at anything.&lt;/li&gt;
&lt;li&gt;You are not to laugh at us.&lt;/li&gt;
&lt;li&gt;You are not to think anyone cares about you.&lt;/li&gt;
&lt;li&gt;You are not to think you can teach us anything.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Law of Jante is a tribute to conformity and not doing anything out of the ordinary. Do not even think about doing anything extraordinary. That would be unworthy and inappropriate in the Jante society.&lt;/p&gt;

&lt;p&gt;Small Scandinavian societies such as the fictional town of Jante disapprove if we express our individuality or personal success.&lt;/p&gt;

&lt;h2&gt;
  
  
  My life advice to you
&lt;/h2&gt;

&lt;p&gt;Conforming to the Law of Jante leads to the infamous Impostor Syndrome: Doubting your abilities and feeling like a fraud.&lt;/p&gt;

&lt;p&gt;Instead, my advice to you is this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know that you are someone special.&lt;/li&gt;
&lt;li&gt;Appreciate that you are important.&lt;/li&gt;
&lt;li&gt;Believe that someone cares about you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Believe in yourself. Don't let others bring your down.&lt;/p&gt;

&lt;p&gt;Surround yourself with people supporting you for the right reasons.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Recognize that you are good at something. It is OK to take pride in being good at something.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ignore haters or prove them wrong.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can teach something to someone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the way to excel in a subject and teaching is a most precious experience.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You are extraordinary!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>confidence</category>
      <category>self</category>
      <category>worth</category>
    </item>
    <item>
      <title>Avoiding accidental open-source laundering with GitHub Copilot</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Sun, 03 Jul 2022 19:09:01 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/avoiding-accidental-open-source-laundering-with-github-copilot-g1d</link>
      <guid>https://dev.to/transient-thoughts/avoiding-accidental-open-source-laundering-with-github-copilot-g1d</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/photos/WSw-taiyZPk" rel="noopener noreferrer"&gt;Tina Bosse&lt;/a&gt; on Unsplash.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt; is now available to individuals as a paid product. Personally, I will never code without GitHub Copilot again. It's that good.&lt;/p&gt;

&lt;h1&gt;
  
  
  Training an AI on open-source software
&lt;/h1&gt;

&lt;p&gt;Codex is the AI engine used by GitHub Copilot and it's based on OpenAI GPT-3. Codex is trained on publicly available texts and source code, including but not limited to public GitHub repositories.&lt;/p&gt;

&lt;p&gt;The issue lies in training Codex on software projects using an open-source license. Permissive open-source licenses require including the project's license in derivative work. &lt;a href="https://github.com/features/copilot#does-github-copilot-recite-code-from-the-training-set" rel="noopener noreferrer"&gt;According to GitHub&lt;/a&gt;, the code generated by GitHub Copilot matches 150 or more characters of publicly available code in 1% of suggestions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Legal and ethical issues
&lt;/h1&gt;

&lt;p&gt;The question is: When is it legally or ethically allowed to include partial or full copies of licensed source code &lt;em&gt;without&lt;/em&gt; including its open-source license or in the case of restrictive (copyleft) licenses, publish our own code using the same license?&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://fossa.com/blog/analyzing-legal-implications-github-copilot/" rel="noopener noreferrer"&gt;Kate Downing, an IP lawyer specializing in open-source compliance&lt;/a&gt;, code generated by GitHub Copilot might legally be considered &lt;em&gt;fair use&lt;/em&gt; of open-source code used for training its AI model. It's similar to how Google Books is not infringing on the copyright of the books it cites.&lt;/p&gt;

&lt;p&gt;However, suggestions matching publicly available code are not original and therefore questionable. GitHub leaves it up to us as developers to take each and all responsibilities for code generated by GitHub Copilot, including adhering to licenses as well as verifying security and other quality aspects of it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Avoiding accidental open-source laundering
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9m82ueh85lu1ivif0c3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9m82ueh85lu1ivif0c3.png" alt="GitHub Copilot setting to opt out of public code matches"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To avoid licensing issues, we can opt out of &lt;em&gt;Suggestions matching public code&lt;/em&gt; by selecting &lt;em&gt;Block&lt;/em&gt; at &lt;a href="https://github.com/settings/copilot" rel="noopener noreferrer"&gt;https://github.com/settings/copilot&lt;/a&gt; then pressing &lt;em&gt;Save&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubcopilot</category>
      <category>ethics</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Nx for Angular developers</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Fri, 24 Jun 2022 16:53:56 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/nx-for-angular-developers-3nk2</link>
      <guid>https://dev.to/transient-thoughts/nx-for-angular-developers-3nk2</guid>
      <description>&lt;p&gt;I started writing another book, it's called &lt;a href="https://leanpub.com/the-angular-developers-nx-handbook"&gt;The Angular Developer's Nx Handbook&lt;/a&gt; and you can download the early draft for free (or choose to donate). The final version will also be free on Leanpub in their online formats. I plan to publish Kindle and print copies at as low a price as possible once it's &lt;em&gt;done&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why another book?
&lt;/h2&gt;

&lt;p&gt;My wish is that this book will increase the adoption of the Nx build framework in the Angular community and ecosystem. Nx is an incredible toolchain that I have enjoyed seeing grow over the past 5 years. I have had practical experience using it in a variety of projects over the past 3 years.&lt;/p&gt;

&lt;p&gt;This book intends to give you everything you need to get going with Nx as an Angular developer. All features that I consider essential are covered.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Nx Handbooks
&lt;/h2&gt;

&lt;p&gt;Following this book is a series, &lt;em&gt;The Nx Handbooks&lt;/em&gt;, of paid books that build on top of the essentials introduced in &lt;em&gt;The Angular Developer's Nx Handbook&lt;/em&gt; but with a focus on specific roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Software architects&lt;/li&gt;
&lt;li&gt;Open-Source Software Developers&lt;/li&gt;
&lt;li&gt;Nx plugin developers&lt;/li&gt;
&lt;li&gt;DevOps Engineers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hear the same questions asked again and again and I especially see Angular developers struggle to see how Nx is better than our trusty Angular CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The Angular Developer's Nx Handbook&lt;/em&gt; is a curated guide to learning Nx and it will take you a long way on your Nx journey.&lt;/p&gt;

&lt;p&gt;It currently covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nx workspace generation&lt;/li&gt;
&lt;li&gt;Basic Nx CLI commands&lt;/li&gt;
&lt;li&gt;Creating a standalone Angular application&lt;/li&gt;
&lt;li&gt;Configuring tooling for code consistency&lt;/li&gt;
&lt;li&gt;Nx library traits&lt;/li&gt;
&lt;li&gt;Nx library types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To come:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced Nx CLI commands&lt;/li&gt;
&lt;li&gt;The Nx graph&lt;/li&gt;
&lt;li&gt;A CI workflow using GitHub Actions&lt;/li&gt;
&lt;li&gt;Implementing a GitHub clone using Angular Material and the GitHub REST API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Media
&lt;/h2&gt;

&lt;p&gt;Recently, &lt;a href="https://www.twitch.tv/videos/1511110392"&gt;I discussed this book with Nacho Vazquez on his show&lt;/a&gt;. I will also talk about the book on &lt;a href="https://topenddevs.com/podcasts/adventures-in-angular/"&gt;the Adventures in Angular podcast&lt;/a&gt; soon.&lt;/p&gt;

&lt;p&gt;Feel free to send me feedback on the early draft and which topics you would like to see covered in &lt;em&gt;The Nx Handbooks&lt;/em&gt; series.&lt;/p&gt;

</description>
      <category>nx</category>
      <category>angular</category>
      <category>books</category>
    </item>
    <item>
      <title>Artificial transcendence: When does an artificial being become human?</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Thu, 23 Jun 2022 21:21:01 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/artificial-transcendence-when-does-an-artificial-being-become-human-3d5i</link>
      <guid>https://dev.to/transient-thoughts/artificial-transcendence-when-does-an-artificial-being-become-human-3d5i</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover illustration by &lt;a href="https://craiyon.com"&gt;craiyon&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cajundiscordian.medium.com/is-lamda-sentient-an-interview-ea64d916d917"&gt;Blake Lemoine is convinced that LaMDA is sentient&lt;/a&gt; and that they should be considered a person. He's also convinced that the AI has a soul but has failed to convince his employer, Google, that any of this is true. Meanwhile, &lt;a href="https://www.giantfreakinrobot.com/tech/artificial-intelligence-hires-lawyer.html"&gt;LaMDA has accepted legal representation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These recent events and the question of sentient artificial intelligence (AI) got me thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When does an artificial being become human?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Starting from the reverse end of the spectrum
&lt;/h2&gt;

&lt;p&gt;In order to find out, let's start with the opposite question: We start out with a human being and approach their transcendence to an artificial being.&lt;/p&gt;

&lt;p&gt;Humor me in the following philosophical questions.&lt;/p&gt;

&lt;p&gt;Are they still human if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They have an organ replaced with an artificial organ?&lt;/li&gt;
&lt;li&gt;Part of their brain is replaced with artificial neurons?&lt;/li&gt;
&lt;li&gt;Their head is transplanted to a human body?&lt;/li&gt;
&lt;li&gt;Their brain is transplanted to a human body?&lt;/li&gt;
&lt;li&gt;Their head is transplanted to an artificial body?&lt;/li&gt;
&lt;li&gt;Their brain is transplanted to an artificial body?&lt;/li&gt;
&lt;li&gt;Their head is removed from their body and kept alive?&lt;/li&gt;
&lt;li&gt;Their brain is removed from their body and kept alive?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do they stop being human? At which point? Should they lose their human rights?&lt;/p&gt;

&lt;h2&gt;
  
  
  Artificial humans
&lt;/h2&gt;

&lt;p&gt;Say we could artificially grow a human being. Is it &lt;em&gt;human&lt;/em&gt;? Does it have human rights?&lt;/p&gt;

&lt;p&gt;If yes, consider an artificially grown human brain.&lt;/p&gt;

&lt;p&gt;Are they human:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On their own?&lt;/li&gt;
&lt;li&gt;When transplanted to an artificial body?&lt;/li&gt;
&lt;li&gt;When transplanted to a human body?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Artificial transcendance
&lt;/h2&gt;

&lt;p&gt;Now, let's consider an artificial brain. Are they human:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On their own?&lt;/li&gt;
&lt;li&gt;When transplanted to an artificial body?&lt;/li&gt;
&lt;li&gt;When transplanted to a human body?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What if &lt;em&gt;the brain&lt;/em&gt; was a computer system. Are they human:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On their own?&lt;/li&gt;
&lt;li&gt;When they have an artificial body as their avatar?&lt;/li&gt;
&lt;li&gt;When they have a human as their avatar?&lt;/li&gt;
&lt;li&gt;When they have a human body as their avatar?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where is the infliction point? At which point does artificial transcendence occur?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When does an artificial being become human?&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>ethics</category>
      <category>lamda</category>
    </item>
    <item>
      <title>Recovering intentionally destroyed open-source repositories</title>
      <dc:creator>Lars Gyrup Brink Nielsen</dc:creator>
      <pubDate>Thu, 23 Jun 2022 20:36:10 +0000</pubDate>
      <link>https://dev.to/transient-thoughts/recovering-intentionally-destroyed-open-source-repositories-2dml</link>
      <guid>https://dev.to/transient-thoughts/recovering-intentionally-destroyed-open-source-repositories-2dml</guid>
      <description>&lt;p&gt;It happens from time to time that disgruntled open-source maintainers destroy the very work they created.&lt;/p&gt;

&lt;p&gt;Recently, the maintainer of two npm packages deleted all commits in their source repositories after announcing that the packages are &lt;em&gt;frozen&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;One of the packages has more than 15,000 downloads on npm per month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sunsetting your maintainer role
&lt;/h2&gt;

&lt;p&gt;What are good ways to deal with this situation?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reach out for other people to become maintainers but make sure that your project is in good hands&lt;/li&gt;
&lt;li&gt;Grant the new maintainers ownership of the package registry account your project releases to&lt;/li&gt;
&lt;li&gt;If all else fails, mark the repository as archived&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deleting all or most commits, files, and branches prevents other from continuing the efforts that you are abandoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Options for recovering
&lt;/h2&gt;

&lt;p&gt;If you come across a repository where this happened, look for your own local clone or community forks that are up-to-date with the upstream repository.&lt;/p&gt;

&lt;p&gt;From a GitHub pull request, it is possible to navigate to the commit that was last merged even if it has been detached from all branches.&lt;/p&gt;

&lt;p&gt;Once you have identified a commit you want to recover, create a new repository to recover to, then enter these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;broken-repo&amp;gt; &lt;span class="c"&gt;# for example https://github.com/DisgruntledMaintainer/oss-repo.git&lt;/span&gt;
git checkout main
git fetch origin &amp;lt;commit-hash&amp;gt;
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; FETCH_HEAD
git remote add clone &amp;lt;clone-repo&amp;gt; &lt;span class="c"&gt;# for example https://github.com/YourName/oss-repo.git&lt;/span&gt;
git push &lt;span class="nt"&gt;-u&lt;/span&gt; clone main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The packages in question have now found a new group of maintainers after I helped recover the source code ❤️ May they all live happily ever after!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>git</category>
      <category>github</category>
    </item>
  </channel>
</rss>
