<?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>Forem: Duncan Faulkner</title>
    <description>The latest articles on Forem by Duncan Faulkner (@duncanfaulkner).</description>
    <link>https://forem.com/duncanfaulkner</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%2Fuser%2Fprofile_image%2F252191%2Fb3d864a7-0c0b-43bd-98ae-0b1b1762b3b4.png</url>
      <title>Forem: Duncan Faulkner</title>
      <link>https://forem.com/duncanfaulkner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/duncanfaulkner"/>
    <language>en</language>
    <item>
      <title>Introduction to Vitest and Angular</title>
      <dc:creator>Duncan Faulkner</dc:creator>
      <pubDate>Sun, 13 Oct 2024 21:49:59 +0000</pubDate>
      <link>https://forem.com/duncanfaulkner/introduction-to-vitest-and-angular-1j3a</link>
      <guid>https://forem.com/duncanfaulkner/introduction-to-vitest-and-angular-1j3a</guid>
      <description>&lt;p&gt;The Angular team deprecated Karma a few versions ago and are currently working on ways to provide an alternative 3rd party unit testing frameworks. Currently the options talked about so far are Web Test Runner (likely to be the default), this is a browser based unit test runner similar in many ways to Karma. The other option being discussed is Jest, this can be installed now but can be a little tricky sometimes to get set up and some known issues when Angular is set up to use ES builds (the default in Angular 18 onward). &lt;/p&gt;

&lt;p&gt;The Angular team are looking at using the CLI for the installation process of these unit testing frameworks, similar to when selecting a CSS framework when creating a new project. This is all still very early on in the development cycle and may be a little way off before it becomes developer preview (currently still experimental) and no mention (as yet) of how this would work with an existing project.&lt;/p&gt;

&lt;p&gt;Now that newer versions of Angular use Vite as a development build server and the default in Angular 18, it is now possible to use Vitest in our Angular projects. The installation process is straight forward to set up and feels less problematic than setting up Jest from my recent experience. The great news here is that Vitest has a similar syntax to Karma and Jest, so the learning curve should be fairly small.&lt;/p&gt;

&lt;p&gt;In this post I'm going to walk through setting up and configuring Vitest in an Angular 18 application and replacing Karma . I won't be writing unit tests in this post, I'll leave that for another post, this post is about setting up Angular to use &lt;code&gt;Vitest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm going to start a new project for this post but this will also work on an existing project.&lt;/p&gt;

&lt;p&gt;In a directory type the following in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng new my-vitest-app  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-vitest-app &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new Angular application called &lt;code&gt;my-vitest-app&lt;/code&gt;, it'll change into that directory and then run &lt;code&gt;npm install&lt;/code&gt; with our application created we can now remove &lt;code&gt;Karma&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From the terminal, type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm uninstall karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We don't need to uninstall &lt;code&gt;@types/jasmine&lt;/code&gt; and &lt;code&gt;jasmine-core&lt;/code&gt; as  Vitest uses Jasmine under the hood, we can use &lt;code&gt;it&lt;/code&gt; and &lt;code&gt;describe&lt;/code&gt; from Jasmine so we don't need to import anything in our test files. It is possible to use &lt;code&gt;it&lt;/code&gt; and &lt;code&gt;describe&lt;/code&gt; from Vitest but in doing so we won't be able to use functions like &lt;code&gt;fakeAysnc&lt;/code&gt; in our unit tests.&lt;/p&gt;

&lt;p&gt;The easiest way to get Vitest installed in our project is to use a plugin and AnalogJS has just what we need to setup and configure Vitest for us.&lt;/p&gt;

&lt;p&gt;From the terminal type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @analogjs/platform &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Followed by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ng g @analogjs/platform:setup-vitest &lt;span class="nt"&gt;--project&lt;/span&gt; my-vitest-app        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once complete the following files will be generated:&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;// vite.config.mts&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;reference types="vitest" /&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;angular&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;@analogjs/vite-plugin-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;defineConfig&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;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;mode&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nf"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;globals&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;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsdom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;setupFiles&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;src/test-setup.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;include&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;**/*.spec.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;reporters&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;default&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;define&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;import.meta.vitest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;vite.config.mts&lt;/code&gt; will be in the root of the project, this sets up the configuration for Vitest, what environment to use, the default is &lt;code&gt;jsdom&lt;/code&gt;, you can change this to &lt;code&gt;happy-dom&lt;/code&gt; (you will need to install &lt;code&gt;happy-dom&lt;/code&gt;). The &lt;code&gt;test-setup.ts&lt;/code&gt; will be in the &lt;code&gt;src&lt;/code&gt; directory and this sets up the test environment.&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@analogjs/vitest-angular/setup-zone&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;BrowserDynamicTestingModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;platformBrowserDynamicTesting&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;@angular/platform-browser-dynamic/testing&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;getTestBed&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/testing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;getTestBed&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;initTestEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;BrowserDynamicTestingModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;platformBrowserDynamicTesting&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;If you are using a&lt;code&gt;zoneless&lt;/code&gt; application then the &lt;code&gt;test-setup.ts&lt;/code&gt; will be slightly different:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@analogjs/vitest-angular/setup-snapshots&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;BrowserDynamicTestingModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;platformBrowserDynamicTesting&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;@angular/platform-browser-dynamic/testing&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;getTestBed&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/testing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;getTestBed&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;initTestEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;BrowserDynamicTestingModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;platformBrowserDynamicTesting&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;In &lt;code&gt;angular.json&lt;/code&gt; the &lt;code&gt;test&lt;/code&gt; section will be replaced with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"builder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@analogjs/vitest-angular:test"&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally the &lt;code&gt;tsconfig.spec.json&lt;/code&gt; will be update to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./tsconfig.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./out-tsc/spec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"jasmine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"vitest/globals"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;added&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2016"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;added&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.spec.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*.d.ts"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"src/test-setup.ts"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;added&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run Vitest tests we need to change the scripts section, in our applications &lt;code&gt;package.json&lt;/code&gt; file add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;scripts&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest"&lt;/span&gt;&lt;span class="w"&gt;   
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;npm run test&lt;/code&gt; will run all of our test files our project.&lt;/p&gt;

&lt;p&gt;If you don't want to install Volta you can skip this section.&lt;/p&gt;

&lt;p&gt;To run &lt;code&gt;Vitest&lt;/code&gt; from the terminal we need to install Vitest, we have a couple of options, globally using &lt;code&gt;npm i -g vitest&lt;/code&gt;, I tend to use Volta, this is a tool chain manager, similar to Node Version Manager (NVM) but Volta handles other JavaScript tooling other than just Node. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you currently have a version of node installed, you will need to uninstall this first before install Volta, once Volta is installed we can install multiple versions of node without removing the previous versions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To install Volta head over to &lt;code&gt;https://volta.sh/&lt;/code&gt; and get the appropriate installer package for your operating system, I'm using Ubuntu and all we need for this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install volta&lt;/span&gt;
curl https://get.volta.sh | bash
&lt;span class="c"&gt;# install node&lt;/span&gt;
volta &lt;span class="nb"&gt;install &lt;/span&gt;node@20.15.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As a side note, one of the nice features of Volta, is the ability to pin the version of node we are using to our &lt;code&gt;package.json&lt;/code&gt; file, meaning that Volta will always select the correct version of Node, this is real handy when working in a team of developers, to pin a version of Node to our &lt;code&gt;package.json&lt;/code&gt; file run &lt;code&gt;volta pin node@20.15.0&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With &lt;code&gt;volta&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt; installed we can now install Vitest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;volta &lt;span class="nb"&gt;install &lt;/span&gt;vitest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Vitest installed we can run &lt;code&gt;volta ls&lt;/code&gt; this will show a list of the tooling that we have installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# example listing from Volta&lt;/span&gt;
⚡️ Currently active tools:

    Node: v20.15.1 &lt;span class="o"&gt;(&lt;/span&gt;default&lt;span class="o"&gt;)&lt;/span&gt;
    Tool binaries available:
        vitest &lt;span class="o"&gt;(&lt;/span&gt;current @ /home/repo/vitest-app/package.json&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;With everything installed we can now run our unit tests, if we want to run a selection of tests (or a specific test) then we need to use the terminal and pass in an additional parameter, this parameter will run any test file that contains this parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run a range of unit tests&lt;/span&gt;
vitest dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also specify a file, this will only run a unit test that matches the file name, note that this doesn't support regex or glob patterns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run a specific unit test&lt;/span&gt;
vitest app.component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will run the unit tests and watch for changes, to run the unit test once and not watch for changes we can change the command to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# run unit test(s) once then stop&lt;/span&gt;
vitest run &lt;span class="o"&gt;[&lt;/span&gt;optionally specify an additional parameter]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to run our unit tests in a CI environment we don't need for them to be in watch mode, so add a &lt;code&gt;test:ci&lt;/code&gt; to the script section of the &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;scripts&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"test:ci"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest run"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to set up our build pipelines to run our tests, setting up build pipelines is out of scope for this post, so I will assume you know how to do this, if not they are plenty of posts on how to do this.&lt;/p&gt;

&lt;p&gt;The next part I want to cover is code coverage, so we've written our unit tests for our various features in our project, but have we written enough? Have we covered the important parts that need testing? This is where code coverage comes to the rescue. Code Coverage tell us how much of our feature is covered by unit tests, whether we've missed a path, for example we've covered the &lt;code&gt;if&lt;/code&gt; condition but not the &lt;code&gt;else&lt;/code&gt; condition. &lt;/p&gt;

&lt;p&gt;Let's add a new script to the scripts section of our &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;scripts&lt;/span&gt;&lt;span class="w"&gt;    
&lt;/span&gt;&lt;span class="nl"&gt;"coverage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"vitest run --coverage"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this we can run &lt;code&gt;npm run coverage&lt;/code&gt; locally and will create a &lt;code&gt;coverage&lt;/code&gt; directory for us in the root of the project and we'll get a table of files along with their code coverage:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;% Stmts&lt;/th&gt;
&lt;th&gt;% Branch&lt;/th&gt;
&lt;th&gt;% Funcs&lt;/th&gt;
&lt;th&gt;% Lines&lt;/th&gt;
&lt;th&gt;Uncovered Line #s&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All files&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;app.component.ts&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When we run this it might prompt to install a supporting package this can be either &lt;code&gt;coverage-v8&lt;/code&gt; (the default) or  &lt;code&gt;coverage-instanbul&lt;/code&gt; package, if not we can install them manually using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For v8&lt;/span&gt;
npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @vitest/coverage-v8

&lt;span class="c"&gt;# For istanbul&lt;/span&gt;
npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @vitest/coverage-istanbul
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can set the &lt;code&gt;provider&lt;/code&gt; type in the &lt;code&gt;coverage&lt;/code&gt; section in the &lt;code&gt;vite.config.mts&lt;/code&gt; file:&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;mode&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;globals&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;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsdom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;setupFiles&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="s2"&gt;src/test-setup.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;include&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="s2"&gt;**/*.spec.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;reporters&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="s2"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;coverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;v8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;reporter&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="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;html&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;span class="na"&gt;define&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="s2"&gt;import.meta.vitest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&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;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run &lt;code&gt;code coverage&lt;/code&gt; in our CI environment we need to adjust our &lt;code&gt;test:ci&lt;/code&gt; script to include a reporter, here I've used &lt;code&gt;junit&lt;/code&gt; and &lt;code&gt;junit.xml&lt;/code&gt; and there is a handy plugin for &lt;code&gt;Azure Devops&lt;/code&gt; to read the &lt;code&gt;junit.xml&lt;/code&gt; file which will import the file and create a nice dashboard for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;script:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;scripts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"test:ci"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest run --reporter=default --reporter=junit --outputFile=reports/junit.xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;Azure devops&lt;/code&gt; we can add the &lt;code&gt;PublishTestResults&lt;/code&gt; task in our build pipelines and would have the task run after our unit tests have completed. &lt;/p&gt;

&lt;p&gt;When we run our unit tests the results will be displayed in the terminal (unless running in a CI environment), but if you prefer to see the results in a browser this is also possible, first we need to install the ui tooling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @vitest/ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to match the version of &lt;code&gt;@vitest/ui&lt;/code&gt; to the same version of &lt;code&gt;vitest&lt;/code&gt; installed on your system, once installed we can start it by running &lt;code&gt;vitest --ui&lt;/code&gt; from the terminal, if we add the &lt;code&gt;html&lt;/code&gt; to the &lt;code&gt;reporters&lt;/code&gt; array in our &lt;code&gt;vite.config.ts&lt;/code&gt; file, this will create an &lt;code&gt;html&lt;/code&gt; directory with all the files.&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;mode&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;globals&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;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsdom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;setupFiles&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="s2"&gt;src/test-setup.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;include&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="s2"&gt;**/*.spec.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;reporters&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="s2"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// add html into this array.&lt;/span&gt;
      &lt;span class="na"&gt;coverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;v8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;reporter&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="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;html&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;span class="na"&gt;define&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="s2"&gt;import.meta.vitest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&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;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post we looked at installing and setting up Vitest, a unit test runner in for Angular applications based on Vite, we also added code coverage to our test runs to see how much code coverage our unit tests cover, we also learnt how we can set this up in our CI in Azure Devops. &lt;/p&gt;

</description>
      <category>typescript</category>
      <category>testing</category>
      <category>softwaredevelopment</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Using Mat-Icon Component – Part Two</title>
      <dc:creator>Duncan Faulkner</dc:creator>
      <pubDate>Mon, 27 Jan 2020 13:27:00 +0000</pubDate>
      <link>https://forem.com/duncanfaulkner/using-mat-icon-component-part-two-3fe8</link>
      <guid>https://forem.com/duncanfaulkner/using-mat-icon-component-part-two-3fe8</guid>
      <description>&lt;h2&gt;
  
  
  Blog Post #002
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Duncan Faulkner – January 2020
&lt;/h2&gt;

&lt;p&gt;I hadn’t intended to write about this just yet, but I got a chance to investigate this sooner than I had thought. I was refactoring part of a project that was using the Mat-Icon component, with an icon.module.ts file as I’d discussed in the previous post.&lt;/p&gt;

&lt;p&gt;I wanted to see if I could improve on the code and reduce the amount of repeated code by iterating over a file and registering the icons.&lt;/p&gt;

&lt;p&gt;I started with a JSON file and populated it with some image names and added the HttpClientModule to use an http.get() method to read the JSON file. All good so far, the file is reading and looping with image names being returned and passed into the matIconRegistery.addSvgIcon() method.&lt;/p&gt;

&lt;p&gt;I thought I might get some issues, but it all seemed to work fine, except the application was erroring, the issue was that the application was loading before the call to the JSON file had returned with the results, so even though I was getting images and registering icons, the app had already tried to use the icons and they weren’t there at that point, and the images were being returned after the app had started.&lt;/p&gt;

&lt;p&gt;OK, so may be this is a timing issue and it doesn’t work in the icon.module.ts file, so I moved code to the app.component.ts file. Nope, the results were the same. This was not the result I was expecting and it was a little odd because the icon.module.ts file was loading images before.&lt;/p&gt;

&lt;p&gt;I’m going to revisit this at a later date, as I would like to understand what the issue is and why it was behaving the way it did, my guess is it has something to do with the http.get() request and the timing around that.&lt;/p&gt;

&lt;p&gt;But as I needed to get this refactoring completed I needed to look for another solution.&lt;/p&gt;

&lt;p&gt;After a bit of research I found an answer and that was to create a service to handle the iterating and registering of icons. Instead of a JSON file to store a list of images the solution was an enum, with a key value structure.&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;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Icons&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;power&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;power&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;save&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;save&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep things simple I’ve made the key and the image name the same.&lt;/p&gt;

&lt;p&gt;The service is quite simple:&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;// imports&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;Icons&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;../image.enum&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;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&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;IconService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;matIconRegistry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MatIconRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;sanitizer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Domsanitizer&lt;/span&gt;
&lt;span class="p"&gt;){}&lt;/span&gt;

&lt;span class="nf"&gt;registerIcons&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="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Icons&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assets/images/icons&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="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;matIconRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSvgIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="nx"&gt;icon&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;sanitizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bypassSecurityTrustResourceUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.svg`&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And on the app.component.ts file call the registerIcons() function.&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;// imports&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;IconService&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;./icon.service&lt;/span&gt;&lt;span class="dl"&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;AppComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;iconService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IconService&lt;/span&gt;&lt;span class="p"&gt;)&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;iconService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerIcons&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;And that’s it, not what I had in mind when I started this, but it does deliver what I wanted to do, and that was to reduce the amount of code to register icons. Though I guess the enum could get pretty lengthy if there are a lot of images.&lt;/p&gt;

&lt;p&gt;I have to thank Stefanos Kouroupis -dev.to – for his article and code on this as I wouldn’t have thought about using a service for this and this has changed my thinking. I wanted to include here it as a follow up to my previous post for completeness, you can see his full article here &lt;a href="https://dev.to/elasticrash/using-custom-made-svg-icons-through-the-angular-material-library-2pif"&gt;https://dev.to/elasticrash/using-custom-made-svg-icons-through-the-angular-material-library-2pif&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I will add a github repo of the code in a day or two.&lt;/p&gt;

&lt;p&gt;Original article published at: &lt;a href="https://anglebrackets.io/index.php/2020/01/25/using-mat-icon-component-part-two/" rel="noopener noreferrer"&gt;https://anglebrackets.io/index.php/2020/01/25/using-mat-icon-component-part-two/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>angularmaterial</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Angular Materials Mat-Icon component</title>
      <dc:creator>Duncan Faulkner</dc:creator>
      <pubDate>Thu, 14 Nov 2019 18:34:22 +0000</pubDate>
      <link>https://forem.com/duncanfaulkner/angular-materials-mat-icon-component-mff</link>
      <guid>https://forem.com/duncanfaulkner/angular-materials-mat-icon-component-mff</guid>
      <description>&lt;h3&gt;
  
  
  Using local SVG images.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Blog post #001
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Duncan Faulkner - October 2019
&lt;/h4&gt;

&lt;p&gt;When developing an Angular application with Angular Material, there comes a point when we need to add icons on our components, or buttons etc... Angular Material has the Mat-Icon component for doing this. This component works with web fonts like Font-Awesome for instance, simply by adding the name of the image required and an image is displayed. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;For example:&lt;/em&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;mat-icon&amp;gt;home&amp;lt;/mat-icon&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;Requires Angular application and Angular Material is installed/configured and a reference to a web font like Font-Awesome library is all set up&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But what about if you have custom icons that are not part of a web font? And would like to makes changes to the icon, for example: change the colour on hover or on a specific condition at run time?&lt;/p&gt;

&lt;p&gt;In a recent project I had a bespoke set of SVG icons, the Angular web application was to be installed on a server that didn't have access to the internet, so the images had to be local. I wanted to use the Mat-Icon component out of the box &lt;em&gt;(in an early version of the project I had a custom icon component)&lt;/em&gt;. I still wanted to be able to change the colours of the icons at various stages throughout the application based on certain conditions as well as on hover. This post covers how I achieved that.&lt;/p&gt;

&lt;h3&gt;
  
  
  SVG Icons
&lt;/h3&gt;

&lt;p&gt;There are a number of different ways to register an icon with the Mat-Icon component, this post discusses  &lt;code&gt;addSvgIcon&lt;/code&gt;, the others are &lt;code&gt;addSvgIconInNamespace, addSvgIconLiteral or addSvgIconLiteralInNamespace&lt;/code&gt; and are all methods of &lt;code&gt;MatIconRegistry&lt;/code&gt; and I might cover these in more detail in a future post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up an Angular project
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; &lt;em&gt;In this post, I'm not going to step through the creation of an Angular application as there are so many already online. Plus I tend to create Nx workspaces for all my Angular projects as I prefer this project layout. I plan to do a blog post on this very soon, for the moment though see &lt;a href="https://nx.dev/angular/getting-started/what-is-nx" rel="noopener noreferrer"&gt;Getting started with Narwhal's Nx Workspaces&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the newly created Angular project, create a &lt;code&gt;shared directory&lt;/code&gt; and add a new file named &lt;code&gt;material.module.ts&lt;/code&gt;. I like to separate Angular Material imports into their own module, I also create a separate module for other 3rd party components, just makes it easier to import later, especially using the Nx workspace layout and feature folders.&lt;/p&gt;

&lt;p&gt;In the material.module.ts&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;// Material Module example.&lt;/span&gt;
&lt;span class="c1"&gt;// All other Angular Material component imports here&lt;/span&gt;
&lt;span class="c1"&gt;// but the important ones are...&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;MatIconModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MatIconRegistry&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/material/icon&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;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;declarations&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="c1"&gt;// Other material imports removed for brevity,&lt;/span&gt;
    &lt;span class="nx"&gt;MatIconModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// Other material exports removed for brevity,&lt;/span&gt;
    &lt;span class="nx"&gt;MatIconModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MatIconRegistry&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;entryComponents&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;MatIconRegistry&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;MaterialModule&lt;/span&gt;  &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MatIconModule is the module for the component, and the MatIconRegistry is a service to register and display icons. Add a reference to the  &lt;code&gt;material.module.ts&lt;/code&gt; in the &lt;code&gt;app.module.ts&lt;/code&gt;. Don't forget to export it as well, otherwise it won't be available and Angular will not know anything about the Angular Material components.&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;// Include the material module in app.module.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;BrowserModule&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/platform-browser&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;NgModule&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="k"&gt;import&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="nx"&gt;AppComponent&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;./app.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="p"&gt;{&lt;/span&gt;  &lt;span class="nx"&gt;BrowserAnimationsModule&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/platform-browser/animations&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;MaterialModule&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;./shared/material.module&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;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&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;BrowserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nx"&gt;BrowserAnimationsModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="nx"&gt;MaterialModule&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="na"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppComponent&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;AppModule&lt;/span&gt;  &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have the Angular Material components set up and configured we need to register the icons, before we can use them. For the moment we are just going to add these to the &lt;code&gt;app.component.ts&lt;/code&gt; to get up and running, we'll look at a better method later on.&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;// First Example&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-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;templateUrl&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.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&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;./app.component.scss&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;matIconRegistry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MatIconRegistery&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;matIconRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSvgIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&lt;/span&gt;&lt;span class="dl"&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;assets/img/icon/home.svg&lt;/span&gt;&lt;span class="dl"&gt;'&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;matIconRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSvgIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="dl"&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;assets/img/icon/add.svg&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="c1"&gt;// or we could do this, and chain the addsvgIcon methods.&lt;/span&gt;
    &lt;span class="c1"&gt;// we'll use this method going forward in this post&lt;/span&gt;
    &lt;span class="c1"&gt;// {&lt;/span&gt;
    &lt;span class="c1"&gt;//      this.matIconRegistry.addSvgIcon('home','assets/img/icon/home.svg')&lt;/span&gt;
    &lt;span class="c1"&gt;//      .addSvgIcon('add','assets/img/icon/add.svg');&lt;/span&gt;
    &lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this to the &lt;code&gt;app.component.html&lt;/code&gt; page, we'll discuss this in more detail in a bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- First HTML example --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mat-icon&lt;/span&gt; &lt;span class="na"&gt;svgIcon=&lt;/span&gt;&lt;span class="s"&gt;"home"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/mat-icon&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mat-icon&lt;/span&gt; &lt;span class="na"&gt;svgIcon=&lt;/span&gt;&lt;span class="s"&gt;"add"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/mat-icon&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point we are not going to see much in the browser as we have an issue with the image URL. If you open the browsers console section, you will see the following error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Error: unsafe value used in a resource URL context&lt;/code&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what does this error mean? A brief explanation from the Angular Material website says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To prevent an Cross Site Scripting (XSS), SVG URL's and HTML strings passed to MatIconRegistry must be marked as trusted by the Angular's DomSanitizer service. Icons are fetched via XmlHttpRequest and must have their URL's on the same domain as the containing page or configured to allow cross-domain access.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So lets add the DomSanitizer and fix this issue.&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;// Second Example - with the DomSanitizer&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-root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;templateUrl&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.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&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;./app.component.scss&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;domSanitizer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DomSanitizer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;matIconRegistry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MatIconRegistery&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;matIconRegistry&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSvgIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domSanitizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bypassSecurityTrustResourceUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assets/img/icon/home.svg&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="nf"&gt;addSvgIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;'&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;domSanitizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bypassSecurityTrustResourceUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assets/img/icon/add.svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// add other icons here....;&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;The call to &lt;code&gt;bypassSecurityTrustResourceUrl&lt;/code&gt; takes a URL as a parameter and sanitizes it so that an attacker cannot inject a 'JavaScript:` URL for example, see official documentation on &lt;a href="https://angular.io/api/platform-browser/DomSanitizer#description" rel="noopener noreferrer"&gt;DomSanitizer&lt;/a&gt;. &lt;br&gt;
Now that we have this in place we should now see two icons in the browser.&lt;/p&gt;

&lt;p&gt;If we have a lot of icons to add this means lots of typing and lots of repetitive code, so lets refactor this some more. Start by removing all of this code (including the constructor) from the app.component.ts. This shouldn't really be in the app.component.ts file. Lets create another new module in the shared directory and call it &lt;code&gt;icon.module.ts&lt;/code&gt; and then add the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;typescript&lt;br&gt;
// Third Example - icon module&lt;br&gt;
import  {  NgModule  }  from  '@angular/core';&lt;br&gt;
import  {  DomSanitizer,  SafeResourceUrl  }  from  '@angular/platform-browser';&lt;br&gt;
import  {  MaterialModule  }  from  '../shared/material.module';&lt;br&gt;
import  {  MatIconRegistry  }  from  '@angular/material/icon';&lt;br&gt;
@NgModule({&lt;br&gt;
declarations:  [],&lt;br&gt;
imports:  [MaterialModule],&lt;br&gt;
exports:  [],&lt;br&gt;
providers:  []&lt;br&gt;
})&lt;br&gt;
export  class  IconModule  {&lt;br&gt;
private  path:  string  =  '../../assets/images'; // change this &lt;br&gt;
constructor(&lt;br&gt;
private  domSanitizer:  DomSanitizer,&lt;br&gt;
public  matIconRegistry:  MatIconRegistry&lt;br&gt;
)  {&lt;br&gt;
this.matIconRegistry&lt;br&gt;
.addSvgIcon('home',  this.setPath(&lt;/code&gt;${this.path}/home.svg&lt;code&gt;))&lt;br&gt;
.addSvgIcon('add',  this.setPath(&lt;/code&gt;${this.path}/file-plus.svg&lt;code&gt;));&lt;br&gt;
}&lt;br&gt;
private  setPath(url:  string):  SafeResourceUrl  {&lt;br&gt;
    return  this.domSanitizer.bypassSecurityTrustResourceUrl(url);&lt;br&gt;
    }&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
Overall, that's not too bad, we are only writing out the domSanitizer code once in the &lt;code&gt;private&lt;/code&gt; method but more importantly, all the code is out of the &lt;code&gt;app.component.ts&lt;/code&gt; file and is now a self contained module. If there are a lot of icons to add then this file will get a bit long, but the typing has gotten shorter (well, a little shorter at least). You could change the &lt;code&gt;constructor&lt;/code&gt;to iterate through a &lt;code&gt;.json&lt;/code&gt; file of image names, the path wouldn't change and could be a &lt;code&gt;const&lt;/code&gt;, which would only mean maintaining a &lt;code&gt;.json&lt;/code&gt; file with any new images. I might look at doing that in a follow up post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Don't forget to add this new icon.module.ts to the app.module.ts otherwise it won't work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Mat-Icon component
&lt;/h2&gt;

&lt;p&gt;So how do we use the mat-icon component? As seen earlier in this post we add the following code to our app.components.html page.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`html&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;br&gt;
This is a very simple example is showing how to put a &lt;code&gt;home&lt;/code&gt; and an &lt;code&gt;add&lt;/code&gt; icon on a page/component. This is not too dissimilar to how we would use this component with web fonts, but we are now using the &lt;code&gt;svgIcon&lt;/code&gt; input property. The value we give to this input is the first parameter used in our call to register the &lt;code&gt;.addSvgIcon('home', ...)&lt;/code&gt; in this case &lt;code&gt;home&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we have an icon in place, how do we change the colour of the icon when someone hovers over it for example. &lt;/p&gt;

&lt;h2&gt;
  
  
  Change the  icon colour
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A Home icon&lt;/strong&gt;.&lt;br&gt;
Example icon copy this into a file with the SVG extension.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;code&gt;svg&lt;br&gt;
&amp;lt;svg version="1.1" width="24" height="24" viewBox="0 0 24 24"&amp;gt;&amp;lt;path d="M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z" fill="#00FFFF" /&amp;gt;&amp;lt;/svg&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
In the above XML, I've removed all the namespaces etc... The main part here is the &lt;code&gt;fill="#00FFFF"&lt;/code&gt; this sets the colour for the image, in this case to AquaMarine. &lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;fill="#00..."&lt;/code&gt; property is not there and you want a different colour to the default black, then you can add it to the path as above, it's optional.&lt;/p&gt;

&lt;p&gt;I usually add the &lt;code&gt;fill&lt;/code&gt; property and set it to white and then change them in SCSS as and when required (but because this example had a white the background I used another colour). &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`html&lt;br&gt;
!&amp;lt;-- Second HTML example --&amp;gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!&amp;amp;lt;-- other code omitted for brevity --&amp;amp;gt; 
&amp;lt;a&amp;gt;

&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;br&gt;
Add a class to the mat-icon html tag, as above and then add the SCSS, for the class. So when a user hovers over the button the colour of the icon changes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;scss&lt;br&gt;
.btn-icon  {&lt;br&gt;
    &amp;amp;:hover  {&lt;br&gt;
        path {&lt;br&gt;
            fill:  rgba(#00ffff,  1);&lt;br&gt;
            }&lt;br&gt;
        }&lt;br&gt;
    }&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Note&lt;/strong&gt; One thing I did forget to add to the app.component.ts above, was the following line: &lt;br&gt;
&lt;code&gt;encapsulation:  ViewEncapsulation.None&lt;/code&gt;, without this then the hover affect doesn't work. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;typescript&lt;br&gt;
@Component({&lt;br&gt;
selector:  'mat-icon-demo-root',&lt;br&gt;
templateUrl:  './app.component.html',&lt;br&gt;
styleUrls:  ['./app.component.scss'],&lt;br&gt;
encapsulation:  ViewEncapsulation.None,&lt;br&gt;
})&lt;br&gt;
export  class  AppComponent  {&lt;br&gt;
    title  =  'mat-icon-demo';&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
Enjoy! &lt;/p&gt;

&lt;p&gt;There is a github repo for this blog post at:&lt;br&gt;
&lt;a href="https://github.com/Anglebrackets-io/mat-icon-demo" rel="noopener noreferrer"&gt;https://github.com/Anglebrackets-io/mat-icon-demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>angularmaterial</category>
      <category>typescript</category>
      <category>svg</category>
    </item>
  </channel>
</rss>
