<?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: Jon Major Condon</title>
    <description>The latest articles on DEV Community by Jon Major Condon (@jonmajorc).</description>
    <link>https://dev.to/jonmajorc</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%2F121410%2Ff5aafdc6-1c12-4f6d-98d2-c2d9c8030042.jpg</url>
      <title>DEV Community: Jon Major Condon</title>
      <link>https://dev.to/jonmajorc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonmajorc"/>
    <language>en</language>
    <item>
      <title>Build Reusable Testing Queries </title>
      <dc:creator>Jon Major Condon</dc:creator>
      <pubDate>Tue, 11 Jun 2019 13:51:42 +0000</pubDate>
      <link>https://dev.to/jonmajorc/build-reusable-testing-queries-27m1</link>
      <guid>https://dev.to/jonmajorc/build-reusable-testing-queries-27m1</guid>
      <description>&lt;p&gt;This post is inspired by a problem I had about two weeks ago; I wrote brittle tests that interacted with the &lt;code&gt;Select&lt;/code&gt; component from React Material UI. After a bunch of time spent that day attempting many solutions, I landed on one that I am satisfied with... That solution is what I am sharing today!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR;&lt;/strong&gt; Keep a testbase maintainable and less brittle by sharing reusable DOM queries. The patterns for accessing "abstraction details" of a third-party component can change over time, but updates can be made in a single spot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I want to write tests that are maintainable and resemble the way my software is used. This means I need to simulate user interaction within components, including any third-party component. However...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Data attributes may not appear in a third-party component.&lt;/li&gt;
&lt;li&gt;Data attributes may not appear on the intended element inside a third-party component.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;I am a huge fan of data-testids, but I can't always rely upon them when working with a third-party component.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Aside: The Material &lt;code&gt;Select&lt;/code&gt; component uses &lt;code&gt;react-select&lt;/code&gt;. This post will only use &lt;code&gt;react-select&lt;/code&gt; in a contrived example...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After some debugging, I discovered an &lt;code&gt;id&lt;/code&gt; on the &lt;code&gt;input&lt;/code&gt; tag inside &lt;code&gt;react-select&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
  &lt;span class="na"&gt;aria&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;autocomplete&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"list"&lt;/span&gt;
  &lt;span class="na"&gt;autocapitalize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
  &lt;span class="na"&gt;autocomplete&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt;
  &lt;span class="na"&gt;autocorrect&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"react-select-2-input"&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* That's helpful! */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;spellcheck&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"box-sizing: content-box; width: 2px; border: 0px; font-size: inherit; opacity: 1; outline: 0; padding: 0px;"&lt;/span&gt;
  &lt;span class="na"&gt;tabindex&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After testing by querying for the &lt;code&gt;id&lt;/code&gt;, I discovered that it increments based on the amount of rendered Select components on the page. I wouldn't trust this as a test id! This can potentially change at anytime causing cascading test failures. A good rule of thumb is to have a reserved id for testing. However, we don't have access to use data attributes or this &lt;code&gt;id&lt;/code&gt; on input anymore... I would rather have an &lt;code&gt;id&lt;/code&gt; on the root tag of the component anyways; then I can query anything scoped inside the component... Turns out, I can do this!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Here is a hot take"&lt;/em&gt;, if a component package does not allow data attributes, read the documentation and learn what can be passed as a substitute. There may be an &lt;code&gt;id&lt;/code&gt; or something that can be rebranded as a test id. In my case, I can do exactly that. In my contrived example, I can create my own internal &lt;code&gt;Select&lt;/code&gt; component that reintroduces &lt;code&gt;react-select&lt;/code&gt; with a required &lt;code&gt;dataTestId&lt;/code&gt; prop. Now I can use my internal component that has a &lt;strong&gt;trusted&lt;/strong&gt; test id.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Select.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactSelect&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;react-select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&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;prop-types&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;dataTestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReactSelect&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dataTestId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;propTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dataTestId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRequired&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="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Select&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Let's carry on with some good old fashion “acceptance criteria.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I see my selected value in the input field of the &lt;code&gt;Select&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;I see my selected value in the &lt;code&gt;span&lt;/code&gt; &lt;strong&gt;directly below&lt;/strong&gt; the &lt;code&gt;Select&lt;/code&gt; component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the working contrived example that meets the acceptance criteria, but we need tests to &lt;strong&gt;ensure we avoid regression in production!&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Select&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;./Select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chocolate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chocolate&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strawberry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strawberry&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vanilla&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vanilla&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;selectedOption&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSelectedOption&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useState&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Select&lt;/span&gt;
        &lt;span class="na"&gt;dataTestId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"select-ice-cream"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selectedOption&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;valSelected&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setSelectedOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valSelected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;testid&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"select-ice-cream-selected"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;You selected &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selectedOption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we were to inspect the third-party component, there's a lot of &lt;code&gt;div&lt;/code&gt;s and stuff within it. A lot of "abstraction details" that we don't care about. It can be rather difficult testing an unmocked third-party component, but doing so gives me better confidence that the application works correctly. Alright, since we are not using &lt;code&gt;data-testid&lt;/code&gt;, we cannot use the &lt;code&gt;queryByTestId&lt;/code&gt; selector from React Testing Library. I am going to use the DOM &lt;code&gt;querySelector&lt;/code&gt; instead...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders without crashing&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;debug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[id="select-ice-cream"] input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputEl&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;em&gt;I don't know of a React Testing Library query available to us that queries for an attribute. That's why we're using the DOM &lt;code&gt;querySelector&lt;/code&gt;.&lt;/em&gt; We can do better though, we can turn the above into a custom query! And even better, I will return an object with elements that are needed for fulfilling the acceptance criteria!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shows selected value in input field and right below select&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;querySelectComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;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;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;querySelectComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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;rootEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&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="na"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] input`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;spanEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s2"&gt;`div[id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] + span[data-testid='&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-selected']`&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rootEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spanEl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;querySelectComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;select-ice-cream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strawberry&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;// change input value to strawberry&lt;/span&gt;
  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tab&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// select what the input value has as the selected value&lt;/span&gt;

  &lt;span class="c1"&gt;//Assertions!&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spanEl&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveTextContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/strawberry/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strawberry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toHaveTextContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strawberry&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test block now covers the acceptance criteria! And yes, we have a very specific selector containing abstraction details. &lt;code&gt;div[id=${id}] + span[data-testid='${id}-selected']&lt;/code&gt;. That selector is to make sure that the span appears directly below &lt;code&gt;Select&lt;/code&gt; as the Acceptance Criteria describes. &lt;em&gt;The user should select a value and see the selected value in the input field of &lt;code&gt;Select&lt;/code&gt; and within the &lt;code&gt;span&lt;/code&gt; &lt;strong&gt;directly below&lt;/strong&gt; &lt;code&gt;Select&lt;/code&gt;.&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;The current test block has queries to abstract the details of component selectors. It is ideal having the queries reusable inside any test block. Anyone who needs to interact with the &lt;code&gt;Select&lt;/code&gt; component, can use the same selector patterns within their tests. Every test can reuse the same pattern for accessing abstraction details of a third-party component, or possibly an internal component. But when &lt;code&gt;react-select&lt;/code&gt; updates, I can update my queries from a single spot!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//testUtils.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectComponentQueries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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;rootEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&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="na"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] input`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;spanEl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`div[id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] + span[data-testid='&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-selected']`&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//App.test.js&lt;/span&gt;
&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shows selected value in input field and right below select&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rootEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spanEl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectComponentQueries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;select-ice-cream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strawberry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tab&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spanEl&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveTextContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/strawberry/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootEl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strawberry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toHaveTextContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strawberry&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Abstraction details of components can change. Keep a testbase maintainable and less brittle with shareable test utils for something like queries. That way, all tests use the same reusable code. Having queries in a single source will allow change to come much easier.&lt;/p&gt;




&lt;p&gt;Hello! I'm &lt;a href="https://jonmajorc.me/"&gt;Jon Major Condon&lt;/a&gt;. I am a Senior Software Farmer that tends to client codebases at &lt;a href="https://bendyworks.com/"&gt;Bendyworks&lt;/a&gt;. As a farmer of software, I focus on anything web, but my curiosity usually leads me down rabbit holes... &lt;em&gt;"Jon Major just fell down another rabbit hole… Stay tuned for the next blog post! 👋"&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>testing</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Gaining Followers. I must not know what I am talking about.</title>
      <dc:creator>Jon Major Condon</dc:creator>
      <pubDate>Mon, 27 May 2019 16:34:37 +0000</pubDate>
      <link>https://dev.to/jonmajorc/gaining-followers-i-must-not-know-what-i-am-talking-about-4789</link>
      <guid>https://dev.to/jonmajorc/gaining-followers-i-must-not-know-what-i-am-talking-about-4789</guid>
      <description>&lt;p&gt;I want to gain followers, but how? It's interesting, I have been asked this question a few times already this year. Do you want to know the unique thing about being asked this question? Me telling you will probably have you close this blog, but I am going to tell you anyways... Ready? Twitter is my social account with the most followers. I have less than 700 followers on Twitter... Twitter and Instagram combined I have less than 900 followers! Bye 😉 &lt;/p&gt;

&lt;p&gt;Okay, I am sure 90-ish% closed this blog. The rest of you, let's continue. Those who stuck around are probably super curious to why I am writing this blog with a follower count so little. Well, two reasons: I have been asked on occasion "how to gain followers" and writing this is me leading by example. There's no silver bullet, so here are some thoughts I remind myself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discover your passion/niche and create!
&lt;/h3&gt;

&lt;p&gt;Publish content to a niche. You may not think you have a niche, but you probably do. It may be hard to see at the moment, but go and find it! If you don't have a niche, start with finding a passion. Your niche and passion are subject to change and that's life. Let's say you enjoy the latest and greatest mobile framework, Flutter. Go and write about it, Vlog about it, Instagram about it, sing about it, and get really weird about it...&lt;/p&gt;

&lt;h3&gt;
  
  
  Storytelling
&lt;/h3&gt;

&lt;p&gt;It's a Journey to where you're going in life. People like me want to hear more about the journey! So whatever your passion is, I want to hear from you. I want to know the mistakes, struggles, and processes your passion is leading you down. The destination cares little about that stuff and cares more about "look at me -- I did it." Get used to talking about the journey.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get used to talking to a wall
&lt;/h3&gt;

&lt;p&gt;A lot of publishing when you have no followers is basically talking to a wall. The cool thing about social media is, it's socially acceptable. Don’t go talking to a real wall; we have social media now. Your content can have zero meaningful interactions and you shouldn't feel lesser about yourself. Keep talking to the wall we call social media. Eventually, you'll get a crowd. &lt;em&gt;SNAP CRACKLE POP... Could it be why Facebook named where your posts go “the wall...”&lt;/em&gt; 🤔😂&lt;/p&gt;

&lt;h3&gt;
  
  
  Interact with your community
&lt;/h3&gt;

&lt;p&gt;If it feels too much like you’re talking to a wall, interact with others. We can’t all be just posting and not engaging with others!  Enter into a thread and share your passion, opinions, and be sure to ask questions before you just waltz in and share your opinions and tell everyone on that thread they’re wrong. Get more context so you can be thoughtful with your responses. That way your responses are actually helpful. &lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-publish to Cross-Promote
&lt;/h3&gt;

&lt;p&gt;Be everywhere! Saturate the internet along with everyone else. You're probably talking about something that's already in the ether, and that's okay. Folks like me will still read it and will begin to look at you as an expert. After cross-publishing awhile you may want to scale back and cross-promote. Basically, draw attention to one source, like your personal site, instead of a dozen sites.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quantity will lead to Quality
&lt;/h3&gt;

&lt;p&gt;I believe quantity will lead to quality. I tell myself this all the time. And it's okay if you suck, I do too. We all suck at some point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Have Empathy
&lt;/h3&gt;

&lt;p&gt;Most importantly, have empathy. There are a lot of haters out there. Don't hate back. You can turn a hater into a lover by just loving on them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't aim for a "Following" count
&lt;/h3&gt;

&lt;p&gt;Just create content, and folks will come. &lt;/p&gt;

&lt;h3&gt;
  
  
  Whatever it is, share it!
&lt;/h3&gt;

&lt;p&gt;Share it. Share it. Share it. I know you know something that I don't, and you probably don't know what that something is. You only know what you know, so publish it. Let others find it and find either value or no value in it. Maybe no one finds value in it today or tomorrow, but maybe a month from now! &lt;em&gt;"HA. A month from now. As we know, technology does move fast...”&lt;/em&gt; Okay, maybe it becomes outdated, but there is someone working on outdated software somewhere. I am positive whatever you publish, someone will find value in it at some point in time.&lt;/p&gt;

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

&lt;p&gt;I, of course, have no idea what I am talking about because I don't have many followers. Good luck!&lt;/p&gt;




&lt;p&gt;Hello! I'm &lt;a href="https://jonmajorc.me"&gt;Jon Major Condon&lt;/a&gt;. I am a Senior Software Farmer that tends to client codebases at &lt;a href="https://bendyworks.com/"&gt;Bendyworks&lt;/a&gt;. As a farmer of software, I focus on anything web, but my curiosity usually leads me down rabbit holes... &lt;em&gt;"Jon Major just fell down another rabbit hole… Stay tuned for the next blog post! 👋"&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>BEM in React</title>
      <dc:creator>Jon Major Condon</dc:creator>
      <pubDate>Mon, 27 May 2019 13:01:12 +0000</pubDate>
      <link>https://dev.to/jonmajorc/semantic-class-names-with-react-bem-2e79</link>
      <guid>https://dev.to/jonmajorc/semantic-class-names-with-react-bem-2e79</guid>
      <description>&lt;p&gt;I default to SCSS without modules for styling React applications. Therefore willingly my styles cascade. You're probably thinking, Eek! That means potential specificity wars ahead. Although there technically could be, each component uses a naming convention for class names.&lt;/p&gt;

&lt;p&gt;Traditional BEM naming convention for class names is &lt;code&gt;block__element--modifier&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;block&lt;/code&gt; is the element in your React component that wraps all other elements. There is only one block per component.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;Element&lt;/code&gt; is within the Block. &lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Modifier&lt;/code&gt; represents behavior on an Element or Block.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pretty simple right? Here is a start to a component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Counter"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Start of an amazing counter component&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;strong&gt;&lt;i&gt;Notice: The class name is the name of the component with the same casing.&lt;/i&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's extend that example so we can see more of BEM in action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Counter"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Counter__inc"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Counter__count"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Counter__dec"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click me!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;strong&gt;&lt;i&gt;Notice: The class name for elements are prefixed with the Block class name followed by a double underscore.&lt;/i&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's add a modifier to this component!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;const Counter = () =&amp;gt; {
&lt;/span&gt;  return (
    &amp;lt;div className="Counter"&amp;gt;
&lt;span class="gd"&gt;-      &amp;lt;button className="Counter__inc"&amp;gt;Click me!&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+      &amp;lt;button className="Counter__inc Counter__inc--disabled" disabled&amp;gt;
&lt;/span&gt;        up
      &amp;lt;/button&amp;gt;
      &amp;lt;span className="Counter__count"&amp;gt;0&amp;lt;/span&amp;gt;
&lt;span class="gd"&gt;-      &amp;lt;button className="Counter__dec"&amp;gt;Click me!&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+      &amp;lt;button className="Counter__dec Counter__dec--disabled" disabled&amp;gt;
&lt;/span&gt;        down
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  )
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;i&gt;Notice: The original class name for an element is cloned, along with a double dash, followed by a modifier.&lt;/i&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The buttons are now disabled. If you noticed, the buttons are missing click events anyways. For this demonstration, we don't really care to have a working example; we just want to see BEM. Theoretically, this application is looking good 🙃 We should have more confidence that styles are scoped to &lt;code&gt;&amp;lt;Counter /&amp;gt;&lt;/code&gt; when it mounts!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Post was growing too large. To keep it small and concise, and hopefully still digestible, I started with introducing BEM. I hope to move on to how I use BEM with 7-1 sass architecture and some other principles to create modular and maintainable style sheets! ...BEM is only part of the equation.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Hello! I'm &lt;a href="https://jonmajorc.me"&gt;Jon Major Condon&lt;/a&gt;. I am a Senior Software Farmer that tends to client codebases at &lt;a href="https://bendyworks.com/"&gt;Bendyworks&lt;/a&gt;. As a farmer of software, I focus on anything web, but my curiosity usually leads me down rabbit holes... &lt;em&gt;"Jon Major just fell down another rabbit hole… Stay tuned for the next blog post! 👋"&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>scss</category>
      <category>bem</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My "lightbulb" Moment!</title>
      <dc:creator>Jon Major Condon</dc:creator>
      <pubDate>Wed, 30 Jan 2019 02:01:57 +0000</pubDate>
      <link>https://dev.to/jonmajorc/my-lightbulb-moment-32cj</link>
      <guid>https://dev.to/jonmajorc/my-lightbulb-moment-32cj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;No matter how you started coding, you have had formative moments when learning. Reflect on one of your “lightbulb” moments when things started to “click." ~ Tea Break Challenge, Day #29&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Almost six years ago... The beginning of my career, during college, I was hired as a part-time Mobile Software Developer consultant. I was hired with little to no knowledge on how to do the job — but, I was so determined... I went the entire first year without really understanding how to read API documentation; however, I was able to build my first production mobile application for a client within this first year! Although the app was a success, I really was still unsure about myself and how I was able to build it. The company I was working for then hired a new developer who was also aspiring to be a software developer, and it was me assigned to teach him "how to build mobile applications." — Whelp, so I did! I taught him how to read API documentation, And you know what...? That's when it clicked! I won't forget that "lightbulb!" moment, because I looked at him like... **** I know what I am talking about after all!&lt;/p&gt;

&lt;p&gt;Teach and you will learn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's a lightbulb moment of yours?&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Hello! I'm Jon Major Condon. I spend my days as a Software Farmer, tending to client codebases at Bendyworks. As a farmer of software, I focus on Javascript, CSS, and mainly React. That's not all though; I love spending my time with my wife and kids and focusing on my growth as a developer and helping others grow too! This year I am working to grow my writing skills, so I hope to publish some of my "Tea Break Challenge" responses and other posts involving anything life and dev related. I hope you enjoy!&lt;/p&gt;

&lt;p&gt;What's the &lt;a href="https://www.teabreakchallenge.com/"&gt;Tea break Challenge&lt;/a&gt;? Every day there is a new challenge to help developers connect with their inner-self. The Tea Break Challenge is also done by a phenomenal dev podcast called &lt;a href="https://developertea.simplecast.fm/"&gt;DeveloperTea&lt;/a&gt;&lt;/p&gt;

</description>
      <category>teabreakchallenge</category>
      <category>webdev</category>
      <category>motivation</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Teabreak Challenge #22</title>
      <dc:creator>Jon Major Condon</dc:creator>
      <pubDate>Wed, 23 Jan 2019 01:22:20 +0000</pubDate>
      <link>https://dev.to/jonmajorc/teabreak-challenge-22-3o8i</link>
      <guid>https://dev.to/jonmajorc/teabreak-challenge-22-3o8i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The ability to focus is paramount to developer success. Determine your biggest enemy of focus today, and be aware of it as you take on your work. ~ Tea Break Challenge #22&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The Enemy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Although "focus is paramount to developer success", it can be a wrecking ball to your productivity. Just because you're focused, does not mean you're being productive! Today, my "biggest enemy of focus" was having &lt;strong&gt;too much&lt;/strong&gt; focus. I had a problem to solve and I was spinning my wheels, but I was too focused; I was unwilling to take a break... If you're like me, you do this far too often. You need to learn when to take a break.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take more breaks so I am accustomed to not being at the keyboard all day.&lt;/li&gt;
&lt;li&gt;After spinning my wheels, start a timer and continue work until it ends. (Then take a break.)&lt;/li&gt;
&lt;li&gt;Ask for another set of eyes.&lt;/li&gt;
&lt;li&gt;Maintain productivity by taking breaks and working on meta tasks to keep me distracted from the original problem I was attempting to solve. (i.g. Slack, email, bathroom break, lunch, snack, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Maybe, just maybe... I need more coffee. Then I should be able to brute force my way to the solution! 🤔&lt;/p&gt;

&lt;p&gt;What was the enemy blocking you from being focused today? Also, please help me out by suggesting any possible solutions for fighting my enemy!&lt;/p&gt;




&lt;p&gt;Hello! I'm Jon Major Condon. I spend my days as a Software Farmer, tending to client codebases through Bendyworks. As a farmer of software, I focus on Javascript, CSS, and mainly React. That's not all though; I love spending my time with my wife and kids and focusing on my growth as a developer and helping others grow too! This year I am working to grow my writing skills, so I hope to publish some of my "Tea Break Challenge" responses and other posts involving anything life and dev related. I hope you enjoy!&lt;/p&gt;

&lt;p&gt;What's the &lt;a href="https://www.teabreakchallenge.com/"&gt;Tea break Challenge&lt;/a&gt;? Every day there is a new challenge to help developers connect with their inner-self. The Tea Break Challenge is also done by a phenomenal dev podcast called &lt;a href="https://developertea.simplecast.fm/"&gt;DeveloperTea&lt;/a&gt;&lt;/p&gt;

</description>
      <category>teabreakchallenge</category>
      <category>softskills</category>
      <category>career</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
