<?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: Uzair Shamim</title>
    <description>The latest articles on DEV Community by Uzair Shamim (@pureooze).</description>
    <link>https://dev.to/pureooze</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%2F29976%2Fb009e230-d258-4727-ab1f-f3cec8091c90.png</url>
      <title>DEV Community: Uzair Shamim</title>
      <link>https://dev.to/pureooze</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pureooze"/>
    <language>en</language>
    <item>
      <title>Memory Bank: Labels In HTML</title>
      <dc:creator>Uzair Shamim</dc:creator>
      <pubDate>Sun, 12 Oct 2025 01:32:49 +0000</pubDate>
      <link>https://dev.to/pureooze/memory-bank-labels-in-html-4kbf</link>
      <guid>https://dev.to/pureooze/memory-bank-labels-in-html-4kbf</guid>
      <description>&lt;p&gt;What is the right way to label something in HTML?&lt;/p&gt;

&lt;p&gt;This came up in something I was working on recently. I always forget the best practices for labeling so I wanted to write this blog post to help me remember... and as a quick reference when I inevitably forget 😉.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Accessible Names
&lt;/h2&gt;

&lt;p&gt;Some elements provide a default accessible name that can be used by screen readers to provide a label for a given element. For example in a button the value between the open and close tags is the default accessible name.&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="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;this is a close button&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes the default accessible name is inaccurate and a separate label needs to be provided to give users accurate context. In these situations labels can help.&lt;/p&gt;

&lt;p&gt;Imagine if the  in the code above needed to have X as its text. This is not very informative to screen reader users and we need a better way to indicate what this button does. There are also many elements that do not have default accessible names, so we may need to provide labels for them as well.&lt;/p&gt;

&lt;p&gt;Full post here: &lt;a href="https://pureooze.com/blog/posts/2025-10-07-memory-bank-labels-in-html/" rel="noopener noreferrer"&gt;https://pureooze.com/blog/posts/2025-10-07-memory-bank-labels-in-html/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>html</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Navigating Technical Debt</title>
      <dc:creator>Uzair Shamim</dc:creator>
      <pubDate>Sat, 04 May 2024 02:06:34 +0000</pubDate>
      <link>https://dev.to/pureooze/navigating-technical-debt-3o2f</link>
      <guid>https://dev.to/pureooze/navigating-technical-debt-3o2f</guid>
      <description>&lt;p&gt;We don't spend enough time doing maintenance! We have too much legacy code! We only build new features and never cleanup the old things we made! We have too much technical debt!&lt;br&gt;
Sound familiar? If you have been involved in any meaningful software development project – especially one that is large – you will have heard complaints like this. &lt;br&gt;
It's a topic that many software developers (including yours truly) are passionate about.&lt;/p&gt;

&lt;p&gt;I would be willing to bet that if you surveyed random developers at a conference, you would find that the majority of them consider technical debt to be a significant problem in their organization.&lt;br&gt;
I would also be willing to bet that they could not agree on &lt;strong&gt;what the problem is&lt;/strong&gt; and &lt;strong&gt;how to address it&lt;/strong&gt;.&lt;br&gt;
The issue is further complicated by the fact that many businesses seem to not care about tech debt.&lt;/p&gt;

&lt;p&gt;In this post I want to explore the idea of technical debt. What is it? Can we measure it? What can we do about it?&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Technical Debt?
&lt;/h2&gt;

&lt;p&gt;The term is used to describe things from "we don't use the shiny new framework" to "this code is not written in the style I like" and even "I inherited the code from someone else".&lt;br&gt;
Let's start by looking at Ward Cunningham's original definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Shipping first-time code is like going into debt. A little debt speeds development so long as it is paid back promptly with refactoring. &lt;br&gt;
The danger occurs when the debt is not repaid. &lt;br&gt;
Every minute spent on code that is not quite right for the programming task of the moment counts as interest on that debt.&lt;br&gt;
Entire engineering organizations can be brought to a stand-still under the debt load of an unfactored implementation, object-oriented or otherwise. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;- Ward Cunningham&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This definition focuses on technical debt being a trade-off &lt;strong&gt;when developing new features&lt;/strong&gt; and that &lt;strong&gt;it is not always bad&lt;/strong&gt; as long as its addressed promptly. &lt;br&gt;
The problem though is that unlike financial debt, who is responsible for making sure an organization can handle more technical debt?&lt;br&gt;
Can an organization be "technical debt" bankrupt? &lt;br&gt;
When organizations start thinking of this in terms of "debt" they quickly realize that there don't &lt;em&gt;seem&lt;/em&gt; to be any consequences of the debt, so they ignore it.&lt;/p&gt;

&lt;p&gt;Steve Freeman (whose work I first encountered in the wonderful book &lt;a href="https://github.com/sf105/goos-code"&gt;Growing Object-Oriented Software, Guided by Tests&lt;/a&gt;) describes technical debt as an &lt;a href="https://higherorderlogic.com/programming/2023/10/06/bad-code-isnt-technical-debt-its-an-unhedged-call-option.html"&gt;"Unhedged Call Option"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This definition highlights the &lt;strong&gt;unpredictability of cost&lt;/strong&gt;.&lt;br&gt;
Unlike debt – where we know what the interest rate will be – options could be infinitely more costly than doing the work in the first place.&lt;br&gt;
I like this definition because it brings forth this idea that the cost can become due suddenly and without warning, and we need to understand where to focus our efforts because the "debt" is a disaster waiting to happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lensing To Understand Technical Debt
&lt;/h2&gt;

&lt;p&gt;Michael Feathers has a great post – &lt;a href="https://michaelfeathers.substack.com/p/lensing-to-understand"&gt;Lensing to Understand&lt;/a&gt; – about how we change our focus to understand a system.&lt;br&gt;
We focus on the high level system to identify potentially interesting areas and then drill down into details to investigate them.&lt;br&gt;
Once we have a better understanding, we zoom back out to see how it affects the system as a whole.&lt;br&gt;
The idea of "lensing" is really important when it comes to understanding technical debt.&lt;/p&gt;

&lt;p&gt;In previous attempts of tacking technical debt, I have made the mistake of &lt;em&gt;starting&lt;/em&gt; with a focus on very specific parts of a system.&lt;br&gt;
Starting with a systems view and then drilling down into the details may be a better way to understand the system.&lt;br&gt;
Where do people encounter the most issues?&lt;br&gt;
Are some parts of the system riskier than others?&lt;br&gt;
What parts of the system are most likely to change in the future?&lt;/p&gt;

&lt;p&gt;These are the kinds of questions we need to be asking.&lt;br&gt;
Too often we focus on bits of code and forget the context of the systems it's used in – which is extremely important.&lt;/p&gt;

&lt;p&gt;So how do we identify risks in our codebase?&lt;br&gt;
Adam Tornhill has a great talk on &lt;a href="https://www.youtube.com/watch?v=w9YhmMPLQ4U"&gt;"Prioritizing Technical Debt"&lt;/a&gt; where he talks about how we can use metrics to identify risks in our codebase.&lt;br&gt;
If we have a way to find out &lt;strong&gt;where to focus our efforts&lt;/strong&gt; we can get a lot more value out of the work we do – &lt;strong&gt;allowing us to ship quicker and build high quality features&lt;/strong&gt;.&lt;br&gt;
I really liked this talk and I recommend watching it.&lt;/p&gt;

&lt;p&gt;Adam has a few metrics that he uses to identify risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;File Hotspots&lt;/strong&gt;: Files that are changed frequently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method Hotspots&lt;/strong&gt;: Methods in hotspot files that are changed frequently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Files that are hard for humans to understand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we find places that meet all three of these criteria we have a high risk area that we should focus on.&lt;/p&gt;




&lt;p&gt;Read the full version of this post on my blog: &lt;a href="https://pureooze.com/blog/posts/2024-03-29-navigating-technical-debt/"&gt;https://pureooze.com/blog/posts/2024-03-29-navigating-technical-debt/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>python</category>
      <category>git</category>
      <category>technicaldebt</category>
    </item>
    <item>
      <title>A Simple List Render Optimization For React 🏎</title>
      <dc:creator>Uzair Shamim</dc:creator>
      <pubDate>Sat, 22 Sep 2018 14:13:03 +0000</pubDate>
      <link>https://dev.to/pureooze/a-simple-list-render-optimization-for-react--5715</link>
      <guid>https://dev.to/pureooze/a-simple-list-render-optimization-for-react--5715</guid>
      <description>&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/photos/NhepANBDBKo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;George Brynzan&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/speed?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yesterday I was watching a talk by Ben Ilegbodu at React Alicante called Help! My React App is Slowwwww! in which Ben discussed some optimizations developers can make to help improve performance of React applications. He goes over many of the potential bottlenecks that may arise such as unnecessary DOM updates, reconciliation and unnecessary object creation. It’s a really interesting talk and I encourage you to watch it (link below) but what I found most interesting was his first point about unnecessary DOM updates.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/LBzJFcZsPBQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;When trying to optimize performance we look for actions that are slower than the majority of other actions and try to minimize the amount of times we perform these actions. It turns out updating the DOM is a very time consuming operation. It is in fact so time consuming that React has a process called reconciliation that exists to try and avoid unnecessary updates.&lt;/p&gt;

&lt;p&gt;Unfortunately as Ben shows in his talk — and as I will show in this post — there are still situations where reconciliation will not be able to help us. However we don’t need to lose hope because there are some simple tweaks we can make to address the issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 🔑 to Lists
&lt;/h2&gt;

&lt;p&gt;This is a really handy trick you can use to optimize the rendering of list items in React. Suppose you have a page that displays a list of items and is defined as follows (click the button to see the code on codesandbox):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/r4y5lj0qxn" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodesandbox.io%2Fstatic%2Fimg%2Fplay-codesandbox.svg" alt="Edit r4y5lj0qxn" width="165" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the button is clicked, it will add an item to the list. This will then trigger an update to the DOM to display our new item along with all the old items. If we look at the DOM inspector while clicking the button we see the following (orange indicates the node is updating):&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/02oJsIemKwQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;See how all the list items are updated? If we think about this for a moment this doesn’t actually seem like an ideal update. Why can’t we just insert the new node without having to update all the other nodes? The reason for this has to do with how we are using the map function in the List component.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;See how we are setting the key for each list item as the index? The problem here is that React uses the key to determine if the item has actually changed. Unfortunately since the insertion we are doing happens at the start of the list, the indexes of all items in the list are increased by one. This causes React to think there has been a change to all the nodes and so it updates them all.&lt;/p&gt;

&lt;p&gt;To work around this we need to modify the map function to use the unique id of each item instead of the index in the array:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And now when we click the button we see that the new nodes are being added without updating the old ones:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KjWehU2HlQk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So what’s the lesson?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Always use a unique key when creating lists in React (and the index is not considered unique)!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🚨 Now there is one thing to address and that is the situation where you do not have a truly unique id in your arrays. The ideal solution is to find some unique key which may be derived by combining some values in the object together. However in certain cases — like an array of strings — this cannot be possible or guaranteed, then you must rely on the index to be the key. 🚨&lt;/p&gt;

&lt;p&gt;So there you have it, a simple trick to optimize list rendering in React! 🎉&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you liked this post be sure to &lt;a href="https://dev.to/pureooze"&gt;follow this blog&lt;/a&gt; and &lt;a href="https://twitter.com/pureooze" rel="noopener noreferrer"&gt;follow me on twitter&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.: Looking to contribute to an open source project? Come contribute to Saka, we could use the help! You can find the project here: &lt;a href="https://github.com/lusakasa/saka" rel="noopener noreferrer"&gt;https://github.com/lusakasa/saka&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Integration Testing Browser Extensions with Jest</title>
      <dc:creator>Uzair Shamim</dc:creator>
      <pubDate>Sat, 18 Aug 2018 02:44:53 +0000</pubDate>
      <link>https://dev.to/pureooze/integration-testing-browser-extensions-withjest-3ajk</link>
      <guid>https://dev.to/pureooze/integration-testing-browser-extensions-withjest-3ajk</guid>
      <description>&lt;p&gt;Previously I wrote about how &lt;a href="https://github.com/lusakasa/saka" rel="noopener noreferrer"&gt;I became the maintainer of Saka&lt;/a&gt;, an open source browser extension that allows users to search through and load open tabs, browsing history and bookmarks. &lt;a href="https://dev.to/pureooze/unit-testing-browser-extensions-39a5"&gt;I talked about how I came up with a solution for unit testing the extension&lt;/a&gt; to give me confidence with code changes. I also mentioned that there were issues with integration testing that I ran into which made it difficult to test components that relied on browser APIs.&lt;/p&gt;

&lt;p&gt;Today I am happy to report that I have found a way to perform integration testing on extensions and want to share it with you in this post. But before we go down that particular rabbit hole lets first discuss integration testing and why it is useful for validating software.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Testing Trophy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F33h90vh6zoyuzqh8a3an.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F33h90vh6zoyuzqh8a3an.jpg" alt="The Testing Trophy" width="450" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.kentcdodds.com/write-tests-not-too-many-mostly-integration-5e8c7fff591c" rel="noopener noreferrer"&gt;Kent C. Dodds has written about something he calls the 'Testing Trophy'&lt;/a&gt;. If you have heard of &lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html" rel="noopener noreferrer"&gt;the testing pyramid&lt;/a&gt; before this is a similar concept - it's a visualization of how you should prioritize the different types of testing in applications. The title of Kent's post says it all:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write tests. Not too many. Mostly integration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why does he say this? Kent notes the problem with unit tests is that they only prove individual units work as expected- they do not prove that the units can work together as a whole. Integration testing on the other hand proves that all the components in our project can actually work together as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Need For Integration Testing
&lt;/h2&gt;

&lt;p&gt;Let's leave the world of software and look at a real world example. Suppose we wanted to build a sink for a bathroom. There are 4components to this sink: the faucet, the basin, the drainage system and the water line. Since the drain and water line come with the building we only need to worry about adding the faucet and the basin.&lt;br&gt;
We go to the store and pick a faucet and basin that we like. We bring them on site and assemble each individually. We confirm that the faucet and basin each work as expected and that they have no defects. Finally we assemble the full sink - hooking up the faucet to the water line and the basin to the drainage. After all our labor we are excited to see our sink in action so we turn on the faucet and what happens? Well…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F33q6ia3zfmxpb6fg0dff.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F33q6ia3zfmxpb6fg0dff.gif" alt="Source: X Unit Tests, 0 Integration Tests" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oops! While we did check to see that the faucet and basin work on their own we forgot to check if the two were actually compatible. This is why integration testing is valuable — it proves that different components, modules and libraries work together as expected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.kentcdodds.com/write-tests-not-too-many-mostly-integration-5e8c7fff591c" rel="noopener noreferrer"&gt;Kent C. Dodds — Write tests. Not too many. Mostly integration.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://natooktesting.wordpress.com/2017/08/24/x-unit-tests-0-integration-tests/" rel="noopener noreferrer"&gt;Ulrika Malmgren — X Unit Tests, 0 Integration Tests&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;Since writing my last post I have managed to get Jest working with Preact, the framework used to create Saka. Jest is a modern testing framework that can run in Node or JSDOM. I will also be using the dom-testing-library to perform the rendering and assertions on my components.&lt;/p&gt;

&lt;p&gt;Just keep in mind that while my specific solutions will be tailored for Preact, they will still work for other frameworks — especially React — with slight modifications for framework specific libraries.&lt;/p&gt;

&lt;p&gt;There is an example Preact extension with Jest setup for reference here: &lt;a href="https://github.com/pureooze/extension-testing-example" rel="noopener noreferrer"&gt;https://github.com/pureooze/extension-testing-example&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You don’t need to install the preact packages if you use a different framework&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First you need to install the required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; babel-jest babel-plugin-transform-class-properties babel-plugin-transform-react-jsx babel-preset-env babel-preset-react jest sinon-chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you are using Preact you need to also run the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; preact-compat preact-render-to-string preact-test-utils preact-testing-library
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note that just like in the previous post we will be using sinon-chrome to mock all browser APIs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring Jest
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;For Preact only, not required for React.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With Jest installed you now need to create a config to tell jest how to deal with parsing Preact. If you use another framework like React you don’t need to do this. Create a jest.config.js file in the root directory of your project with the following contents:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Notice the transform property is telling Jest to apply a custom transformer on all JSX files. To make it work we also need to create a jest.transform.js file:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Create The Commands
&lt;/h2&gt;

&lt;p&gt;Add the following npm scripts to your package.json so that jest can be run from the command line:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Create The First Test
&lt;/h2&gt;

&lt;p&gt;Jest is smart enough to scan your project and run any files it finds with the .test.js extension. Create a new file called Main.test.js in the tests directory of your project with the following contents where the import Main is the component you want to test:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Once the file is created, open a terminal in the root of your project and run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn &lt;span class="nb"&gt;test&lt;/span&gt;:watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see jest output something similar to this (assuming the test you created passed):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9l3a9ve1n1qddfapry4h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9l3a9ve1n1qddfapry4h.png" alt="Snapshots successfully taken" width="412" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congrats! Jest has successfully run and created a snapshot for the test. Jest has created a &lt;em&gt;&lt;strong&gt;snapshots&lt;/strong&gt;&lt;/em&gt; directory where all the snapshots are stored. If you open one of them you will see something like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The next time the test runs, Jest will compare the existing snapshot to the snapshot it takes at runtime and notify you if a difference is detected.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Integration testing is valuable when we want to assert the compatibility of the components we create. As Kent C. Dodds writes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write tests. Not too many. Mostly integration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can use Jest to achieve this for modern Javascript projects and browser extensions are no different. With the help of sinon-chrome you can mock out any extension APIs that are used by your components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;If you liked this post be sure to &lt;a href="https://dev.to/pureooze"&gt;follow this blog&lt;/a&gt; and &lt;a href="https://twitter.com/pureooze" rel="noopener noreferrer"&gt;follow me on twitter&lt;/a&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;P.S.: Looking to contribute to an open source project? Come contribute to Saka, we could use the help! You can find the project here: &lt;a href="https://github.com/lusakasa/saka" rel="noopener noreferrer"&gt;https://github.com/lusakasa/saka&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>chrome</category>
      <category>jest</category>
    </item>
    <item>
      <title>Unit Testing Browser Extensions</title>
      <dc:creator>Uzair Shamim</dc:creator>
      <pubDate>Fri, 25 May 2018 05:19:29 +0000</pubDate>
      <link>https://dev.to/pureooze/unit-testing-browser-extensions-39a5</link>
      <guid>https://dev.to/pureooze/unit-testing-browser-extensions-39a5</guid>
      <description>&lt;p&gt;In April I became the maintainer of &lt;a href="https://github.com/lusakasa/saka" rel="noopener noreferrer"&gt;Saka&lt;/a&gt;, a browser extension that allows users to search through their tabs, bookmarks and history. The original goal of Saka was to provide an elegant tab search but this soon evolved to include recently closed tabs, bookmarks and history when the original maintainer &lt;a href="https://github.com/eejdoowad" rel="noopener noreferrer"&gt;eejdoowad&lt;/a&gt; recognized that users search for tabs the same way they search bookmarks and history. This was an important insight and it has helped make Saka a valuable productivity tool.&lt;/p&gt;

&lt;p&gt;When I became the maintainer I was surprised at the absence of tests in the project. There were several components with complicated logic but no tests to be found anywhere. One of the most important things I have learned as a developer is that tests are the easiest ways to write reliable, easy to refactor code. Was the old maintainer just lazy? Did he simply not care about the quality of his code? No. The opposite in fact, he cared a lot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ficotq046zi7xn58vhn31.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ficotq046zi7xn58vhn31.gif" alt="Saka used to switch between tabs" width="640" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The issue is that the lack of documentation on the topic means that almost no one is able to test their extension. Having no confidence in my ability to make changes without breaking the code, this was a big problem. But as fate would have it after trying a dozen different approaches I ended up finding a solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why We Test
&lt;/h3&gt;

&lt;p&gt;As developers we want to be sure that the code we write today is not going to become a burden to maintain later in the lifetime of the application. One way we avoid creating these burdens is by writing tests. The great thing about tests is that outside of just verifying the behavior of functions, tests allow us to provide documentation for future developers. For example by creating unit tests we declare the valid inputs and outputs for a given function. This makes it easier to refactor code because we can have confidence that our code is working correctly when all our tests pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Testing Approach
&lt;/h3&gt;

&lt;p&gt;This post will focus on setting up the environment and writing some basic unit tests. I do not have a solution to perform Integration Testing on browser extensions as there are issues with attempting to access WebExtension APIs from a webpage when running in Chrome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;In my search for a solution to testing Saka, I went through several different testing libraries like Jest, Mocha and Jasmine. One of the biggest challenges for me was that Saka is written using Preact, which causes compatibility issues with other libraries. But after following several examples online, I was finally able to put together a solution using Karma and Jasmine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;In order to use this solution, your project should use Webpack. The example uses version 4 but this may still work with older versions. While I have not tried, it should be possible to make this work with Gulp after some configuration to make sure everything is bundled properly. You can find a sample webpack config &lt;a href="https://github.com/pureooze/extension-testing-example/blob/37e5a82cc436fc8256110600255145ad347340f1/webpack.config.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F95124nbr9e5k8vmuvwj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F95124nbr9e5k8vmuvwj8.png" title="Karma, Jasmine and Chrome" alt="Karma, Jasmine and Chrome logos" width="703" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Karma + Jasmine
&lt;/h3&gt;

&lt;p&gt;If you are not already familiar with it, &lt;a href="https://github.com/karma-runner/karma" rel="noopener noreferrer"&gt;Karma&lt;/a&gt; is a tool that allows executing JavaScript code in a browser for testing purposes. While it can execute code, it is not capable of testing the code and instead relies on third party libraries like &lt;a href="https://jasmine.github.io/" rel="noopener noreferrer"&gt;Jasmine&lt;/a&gt; and &lt;a href="https://mochajs.org/" rel="noopener noreferrer"&gt;Mocha&lt;/a&gt;. When developing Saka I chose Jasmine because I had previous experience using it in other projects.&lt;/p&gt;

&lt;p&gt;The first step to getting Karma and Jasmine setup is to install them:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add jasmine karma karma-chrome-launcher karma-jasmine karma-spec-reporter karma-webpack babel-loader --dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Before Karma can start running tests it needs to know what configuration parameters to use. In order to provide these, create a karma.conf.js file in the root of the project. I have provided a sample config &lt;a href="https://github.com/pureooze/extension-testing-example/blob/37e5a82cc436fc8256110600255145ad347340f1/karma.conf.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Note that Karma is capable of running Jasmine on its own, it just needs to be told to use it via the frameworks configuration property.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chrome
&lt;/h3&gt;

&lt;p&gt;Those of you who actually read the karma config may notice that it specifies Chrome as a requirement:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;browsers: ["ChromeHeadless"]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, Karma requires an actual browser to run the JavaScript code. This line tells Karma that it should look for Chrome on the system it is running on and launch it in &lt;a href="https://developers.google.com/web/updates/2017/06/headless-karma-mocha-chai" rel="noopener noreferrer"&gt;headless mode&lt;/a&gt;. The benefits of using headless mode are that you can use the system when the tests are running, instead of being interrupted every 2 seconds when a new test starts to run. Seemed like an obvious win to me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding A Test
&lt;/h3&gt;

&lt;p&gt;To start adding tests, create a JavaScript module using the code in &lt;a href="https://github.com/pureooze/extension-testing-example/blob/4f047127a0735c5d97f3b4c6f2b46b063de61d55/src/simpleModule.js" rel="noopener noreferrer"&gt;this example&lt;/a&gt; under the src directory of your project. As the name suggests the sum function will simply add up all values passed to it and return the sum.&lt;/p&gt;

&lt;p&gt;Create a test directory in the root of your project - this is where all the tests will live. Take a look at the karma config file and note &lt;a href="https://github.com/pureooze/extension-testing-example/blob/4f047127a0735c5d97f3b4c6f2b46b063de61d55/karma.conf.js#L4" rel="noopener noreferrer"&gt;this line&lt;/a&gt;. It tells karma that to load the tests it must use the test/index.test.js file as the entry point. In the index.test.js file add &lt;a href="https://github.com/pureooze/extension-testing-example/blob/4f047127a0735c5d97f3b4c6f2b46b063de61d55/test/index.test.js" rel="noopener noreferrer"&gt;the following code&lt;/a&gt; to import all files inside the test directory ending in .test.js.&lt;/p&gt;

&lt;p&gt;With the config out of the way, add a new file simpleModule.test.js in the test directory &lt;a href="https://github.com/pureooze/extension-testing-example/blob/4f047127a0735c5d97f3b4c6f2b46b063de61d55/test/simpleModule.test.js" rel="noopener noreferrer"&gt;like this&lt;/a&gt;. This file will house the tests for all the functions in the simpleModule.js file. The describe blocks are used to categorize the tests in the Jasmine logs so that it is easier to tell which modules have failures. Individual tests are located within the it() function which needs a description as the first argument and the test function as the second argument. To learn more about how to write tests using Jasmine you can consult &lt;a href="https://jasmine.github.io/api/3.0/global" rel="noopener noreferrer"&gt;the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running Tests
&lt;/h3&gt;

&lt;p&gt;In order to run tests the karma executable can be called directly with the path to the config file passed in as an argument. While this works, a more elegant solution is to add the command to the npm scripts in the package.json file &lt;a href="https://github.com/pureooze/extension-testing-example/blob/4f047127a0735c5d97f3b4c6f2b46b063de61d55/package.json#L7" rel="noopener noreferrer"&gt;like this&lt;/a&gt;. You should now be able to just run yarn test and see the output from Karma like below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fej9aoz0sbledxm5ro8e5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fej9aoz0sbledxm5ro8e5.png" title="Screenshot of result after the tests ran" alt="Screenshot of result after the tests ran" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing With WebExtension APIs
&lt;/h3&gt;

&lt;p&gt;The problem that developers run into when attempting to test extensions is having to deal with the WebExtension APIs in tests. The problem is that the environment the tests run in - that is as a webpage in chrome - does not have access to the APIs. This becomes an issue as Jasmine will throw an error because anything with browser.* will be undefined.&lt;/p&gt;

&lt;p&gt;To overcome this issue you need to install &lt;a href="https://github.com/acvetkov/sinon-chrome" rel="noopener noreferrer"&gt;sinon-chrome&lt;/a&gt;, a library which enables mocking out these APIs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add sinon-chrome --dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a new module in the src directory called popup.js with &lt;a href="https://github.com/pureooze/extension-testing-example/blob/master/src/popup.js" rel="noopener noreferrer"&gt;the following code&lt;/a&gt;. Notice how the getUrl function relies on the browser.runtime.getURL API. We are going to use sinon-chrome to mock the response the browser would return.&lt;/p&gt;

&lt;p&gt;Create a new file called popup.test.js in the test directory to store all the tests for the popup.js file you just created. Add &lt;a href="https://github.com/pureooze/extension-testing-example/blob/master/test/popup.test.js" rel="noopener noreferrer"&gt;the following code&lt;/a&gt; to the test file and notice how the browser API is mocked by sinon-chrome. For every test that uses the WebExtension APIs, you must specify what each API should return when Jasmine encounters it, allowing you to bypass the issue with the APIs not being defined.&lt;/p&gt;

&lt;p&gt;Run yarn test and you should see the following results from the tests:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkzwn4tdhtmhmgsb1ww16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkzwn4tdhtmhmgsb1ww16.png" title="Screenshot of successful test run with sinon-chrome" alt="Screenshot of successful test run with sinon-chrome ran" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you are, free to test your chrome extension without having to fear the extension APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Work
&lt;/h2&gt;

&lt;p&gt;While this setup with Karma, Jasmine and Chrome works, it is not an ideal solution. There are some benefits in using Jest, a modern testing library that runs entirely in Node thus eliminating the need for a test runner and browser. Unfortunately, Jest has some compatibility issues with Preact so for the time being I have put it on the back burner. Hopefully I can find some time to migrate the tests to use Jest because I think it will make for a good blog post.&lt;/p&gt;

&lt;p&gt;You can download Saka for Chrome &lt;a href="https://chrome.google.com/webstore/detail/saka/nbdfpcokndmapcollfpjdpjlabnibjdi" rel="noopener noreferrer"&gt;here&lt;/a&gt; and for Firefox &lt;a href="https://addons.mozilla.org/firefox/addon/saka/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>mocking</category>
      <category>testing</category>
      <category>chrome</category>
    </item>
  </channel>
</rss>
