<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Untitled Publication]]></title><description><![CDATA[Untitled Publication]]></description><link>https://blog.nolanphillips.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 08:52:02 GMT</lastBuildDate><atom:link href="https://blog.nolanphillips.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Can we make  a grammar for our design system?]]></title><description><![CDATA[As the only person building HeartPayroll I find myself needing to wear two hats: developer and designer. This is fun, but it means I don't have a lot of time to really think about the visual design of the application. Instead, I've spent a little tim...]]></description><link>https://blog.nolanphillips.com/design-system-grammar</link><guid isPermaLink="true">https://blog.nolanphillips.com/design-system-grammar</guid><category><![CDATA[Design]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Design Systems]]></category><dc:creator><![CDATA[Nolan Phillips]]></dc:creator><pubDate>Wed, 22 Jun 2022 12:08:41 GMT</pubDate><content:encoded><![CDATA[<p>As the only person building <a target="_blank" href="https://heartpayroll.com">HeartPayroll</a> I find myself needing to wear two hats: developer and designer. This is fun, but it means I don't have a lot of time to really think about the visual design of the application. Instead, I've spent a little time building out a <strong>design system</strong> that takes care of most of these thoughts for me. </p>
<p>Much of what I've read and built around design systems has been about the individual components. These rules of thumb have helped make components that are easily reused in a variety of context. While this has been massive benefit, I still find myself struggling to consistently answer questions at the page level:</p>
<ul>
<li>How much padding should be on the page?</li>
<li>How much big should the gap be between the Heading and Headline?</li>
<li>Should those Cards be grouped together?</li>
<li>Does the submit button float left or right in the Card?</li>
</ul>
<p>I have been struggling with these questions because <strong>what I have is a language without a grammar</strong>. A bunch of words with definitions, but with no syntax to bind them together.</p>
<p>This question has really interested me, so I've started to define a <a target="_blank" href="https://en.wikipedia.org/wiki/Formal_grammar">Formal grammar</a> for my design system.</p>
<pre><code><span class="hljs-comment"># ======</span>
<span class="hljs-comment"># Legend</span>
<span class="hljs-comment"># ======</span>
<span class="hljs-comment"># Anything: .</span>
<span class="hljs-comment"># Optional: ?</span>
<span class="hljs-comment"># Any number of: *</span>
<span class="hljs-comment"># At least 1: +</span>
<span class="hljs-comment"># Or: ||</span>

Page –&gt; 
  Title 
  Layout

Layout –&gt; 
  Navigation? 
  Main 
  Footer?

Main –&gt; 
  Header
  Content

Header –&gt; 
  Backlink? 
  Heading 
  Headline?

Content –&gt; 
  Card*

Card –&gt; 
  Heading 
  .*

Form –&gt; 
  Fieldset+  
  FormResponse

Fieldset –&gt; 
  Legend? 
  Field+

FormActions –&gt; 
  Submit 
  Cancel?

FormResponse –&gt; 
  SuccessResponse <span class="hljs-params">||</span> FailureResponse
</code></pre><p>So with this grammar I have a couple follow up questions:</p>
<p>How can I express it in code so that it is easy to adhere to?</p>
<p>Can I ensure that any valid "sentences" provide a visually consistent UI?</p>
<p>I'll find out</p>
]]></content:encoded></item><item><title><![CDATA[How to Mock ActionMailer]]></title><description><![CDATA[The Rails ActionMailer is a pretty useful tool. 
Unfortunately, it's extremely awkward to mock for tests.
Since these emails are critical to our business I spent some time looking at how to write clean test to make sure my mailers are called when the...]]></description><link>https://blog.nolanphillips.com/how-to-mock-actionmailer</link><guid isPermaLink="true">https://blog.nolanphillips.com/how-to-mock-actionmailer</guid><category><![CDATA[Ruby]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Testing]]></category><category><![CDATA[bdd]]></category><dc:creator><![CDATA[Nolan Phillips]]></dc:creator><pubDate>Fri, 13 May 2022 15:35:14 GMT</pubDate><content:encoded><![CDATA[<p>The Rails <code>ActionMailer</code> is a pretty useful tool. </p>
<p>Unfortunately, it's extremely awkward to mock for tests.</p>
<p>Since these emails are critical to our business I spent some time looking at how to write clean test to make sure my mailers are called when they should be. </p>
<h2 id="heading-the-business-case">The Business Case</h2>
<p>So we're working on a Point of Sale for the the <a target="_blank" href="https://www.frostytreat.ca/">Frosty Treat</a> in Kengsington PEI. The CEO is all about data and dopamine rushes, so they want to get an email <em>every time</em> a banana gets split...for whatever reason. </p>
<p>Here's what our test should roughly look like:</p>
<p><strong>spec/banana_spec.rb</strong></p>
<pre><code class="lang-ruby">it <span class="hljs-string">'sends an :banana_split email after being #split'</span> <span class="hljs-keyword">do</span>
  banana = Banana.new

  <span class="hljs-comment"># expect BananaMailer to send a :banana_split email later</span>

  banana.split
<span class="hljs-keyword">end</span>
</code></pre>
<h2 id="heading-mocking-out-the-bananamailer">Mocking out the BananaMailer</h2>
<p>The ActionMailer API is nice to work with...but involves a lot of weird objects. After a bit of fiddling around and searching through <a target="_blank" href="https://stackoverflow.com/questions/45207926/can-not-test-mailer-action-called-in-rspec-rails">StackOverflow</a> we find the magic spell we need:</p>
<p><strong>spec/banana_spec.rb</strong></p>
<pre><code class="lang-ruby">it <span class="hljs-string">'sends an :banana_split email after being #split'</span> <span class="hljs-keyword">do</span>
  mailer = double(<span class="hljs-symbol">:mailer</span>)
  mail = double(<span class="hljs-symbol">:mail</span>)

  expect(EmployeeOnboardingMailer).to receive(<span class="hljs-symbol">:with</span>).and_return(mailer)
  expect(mailer).to receive(expected_method).and_return(mail)
  expect(mail).to receive(<span class="hljs-symbol">:deliver_later</span>)

  banana = FactoryBot.create(<span class="hljs-symbol">:banana</span>)

  banana.split
<span class="hljs-keyword">end</span>
</code></pre>
<p>Great! It works. </p>
<p>It's a mess though, and the thought of writing that every time I need to test a mailer is enough to keep me from ever writing a mailer test again.</p>
<p>Luckily there's a way around this.</p>
<h2 id="heading-custom-rspec-matchers-to-the-rescue">Custom RSpec matchers to the rescue</h2>
<p>RSpec makes it easy to create <a target="_blank" href="https://relishapp.com/rspec/rspec-expectations/v/2-3/docs/custom-matchers/define-matcher">custom matchers</a> for your tests.</p>
<p>Let's build a super simple example:</p>
<p><strong>spec/action_mailer_helper.rb</strong></p>
<pre><code class="lang-ruby">RSpec::Matchers.define <span class="hljs-symbol">:deliver_later</span> <span class="hljs-keyword">do</span> <span class="hljs-params">|expected_method|</span>
  match <span class="hljs-keyword">do</span> <span class="hljs-params">|mailer_class|</span>
    mailer = double(<span class="hljs-symbol">:mailer</span>)
    mail = double(<span class="hljs-symbol">:mail</span>)

    expect(mailer_class).to receive(<span class="hljs-symbol">:with</span>).and_return(mailer)
    expect(mailer).to receive(expected_method).and_return(mail)
    expect(mail).to receive(<span class="hljs-symbol">:deliver_later</span>)
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>And don't forget to add it to your <code>rails_helper</code> to make it available.</p>
<p><strong>spec/rails_helper.rb</strong></p>
<pre><code class="lang-diff">require 'rails_helper'
<span class="hljs-addition">+ require 'action_mailer_helper'</span>
</code></pre>
<h2 id="heading-simplifying-our-test">Simplifying our test</h2>
<p>With our new helper added we can really clean things up in our tests:</p>
<p><strong>spec/banana_spec.rb</strong></p>
<pre><code class="lang-ruby">it <span class="hljs-string">'sends an :banana_split email after being #split'</span> <span class="hljs-keyword">do</span>
  expect(BananaMailer).to deliver_later(<span class="hljs-symbol">:banana_split</span>)

  banana = Banana.new

  banana.split
<span class="hljs-keyword">end</span>
</code></pre>
<p>Voila! </p>
<p>A clear spec to make sure the Frosty Treat CEO will be happy for a long time.</p>
]]></content:encoded></item><item><title><![CDATA[Testing for Change]]></title><description><![CDATA[Writing tests that check that a value you don't control has changed is a weird thing. 
To help out, RSpec provides a change matcher that can help make things easier.
Let's look at an example of how we can use the change matcher to create more robust ...]]></description><link>https://blog.nolanphillips.com/testing-for-change</link><guid isPermaLink="true">https://blog.nolanphillips.com/testing-for-change</guid><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Testing]]></category><category><![CDATA[TDD (Test-driven development)]]></category><category><![CDATA[Ruby]]></category><dc:creator><![CDATA[Nolan Phillips]]></dc:creator><pubDate>Tue, 10 May 2022 15:05:09 GMT</pubDate><content:encoded><![CDATA[<p>Writing tests that check that a value you don't control has changed is a weird thing. </p>
<p>To help out, RSpec provides a <a target="_blank" href="https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/change-matcher">change matcher</a> that can help make things easier.</p>
<p>Let's look at an example of how we can use the <a target="_blank" href="https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/change-matcher">change matcher</a> to create more robust tests for our Rails app. </p>
<h2 id="heading-the-problem-tracking-changes-to-our-models">The Problem: Tracking Changes to our Models</h2>
<p>We have a <code>User</code> model and want to make sure that anytime it's changed, a <code>Trail</code> is created to record that change. Here are the models:</p>
<p><strong>app/models/user.rb</strong></p>
<pre><code class="lang-ruby"><span class="hljs-comment"># == Schema Information</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment"># Table name: users</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment">#  id                     :bigint           not null, primary key</span>
<span class="hljs-comment">#  first_name             :string           not null</span>
<span class="hljs-comment">#  last_name              :string           not null</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> &lt; ApplicationRecord</span>
  has_many <span class="hljs-symbol">:trails</span>, <span class="hljs-symbol">as:</span> <span class="hljs-symbol">:origin</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p><strong>app/models/trail.rb</strong></p>
<pre><code class="lang-ruby"><span class="hljs-comment"># == Schema Information</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment"># Table name: trails</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment">#  id           :bigint           not null, primary key</span>
<span class="hljs-comment">#  attr_changed :string           not null</span>
<span class="hljs-comment">#  changed_from :string</span>
<span class="hljs-comment">#  changed_to   :string</span>
<span class="hljs-comment">#  origin_id    :bigint           not null</span>
<span class="hljs-comment">#  origin_type  :string           not null</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Trail</span> &lt; ApplicationRecord</span>
  belongs_to <span class="hljs-symbol">:origin</span>, <span class="hljs-symbol">polymorphic:</span> <span class="hljs-literal">true</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h2 id="heading-making-trails-after-update">Making Trails after update</h2>
<p>Our first goal, is to make it so a <code>Trail</code> record is created anytime a user's first name is changed. </p>
<p><strong>spec/models/user_spec.rb</strong></p>
<pre><code class="lang-ruby">describe User <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'creates a trail when the first_name is changed'</span> <span class="hljs-keyword">do</span>
    user = FactoryBot.create(<span class="hljs-symbol">:user</span>)

    user.update(<span class="hljs-symbol">first_name:</span> <span class="hljs-string">'Something New'</span>)

    expect(user.trails.where(<span class="hljs-symbol">attr_changed:</span> <span class="hljs-string">'first_name'</span>).count ).to be(<span class="hljs-number">1</span>)
  <span class="hljs-keyword">end</span> 
<span class="hljs-keyword">end</span>
</code></pre>
<p>One way to  make <em>only</em> this test pass would be to add callback to our <code>User</code> model:</p>
<p><strong>app/models/user.rb</strong></p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> &lt; ApplicationRecord</span>
  has_many <span class="hljs-symbol">:trails</span>, <span class="hljs-symbol">as:</span> <span class="hljs-symbol">:origin</span>
  after_update <span class="hljs-symbol">:create_trail</span>

  private

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_trail</span></span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> first_name_previously_changed?

    Trail.create(
      <span class="hljs-symbol">origin:</span> <span class="hljs-keyword">self</span>, 
      <span class="hljs-symbol">attr_changed:</span> <span class="hljs-string">'first_name'</span>, 
      <span class="hljs-symbol">from:</span> first_name_previously_was,
      <span class="hljs-symbol">to:</span> first_name,
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>This is great! </p>
<p>Our tests passes. It's easy to read. What could go wrong? If we change the requirements so that a trail is made when we create the <code>User</code> then 
things get a little funny. </p>
<h2 id="heading-making-trails-after-create">Making Trails after create</h2>
<p>After adding a new spec to make sure trails are made on create:</p>
<p><strong>spec/models/user_spec.rb</strong></p>
<pre><code class="lang-ruby">  it <span class="hljs-string">'creates first_name trail when the user is created '</span> <span class="hljs-keyword">do</span>
    user = FactoryBot.build(<span class="hljs-symbol">:user</span>)

    user.save

    expect(user.trails.count).to be(<span class="hljs-number">1</span>)
  <span class="hljs-keyword">end</span>
</code></pre>
<p>We update our callback to run more generally:</p>
<p><strong>app/models/user.rb</strong></p>
<pre><code class="lang-diff">class User &lt; ApplicationRecord
  has_many :trails, as: :origin
<span class="hljs-deletion">-  after_update :create_trail</span>
<span class="hljs-addition">+  after_save :create_trail</span>
</code></pre>
<p>We'll see that our new spec passes (woo!) but our first spec fails (boo!).</p>
<h2 id="heading-magic-numbers">Magic Numbers</h2>
<p>The problem with our specs is they rely on magic numbers. We've made too hard of a rule: there must be precisely <code>1</code> trail for our user after we've changed it's first_name. </p>
<p>How do we fix this weirdness?</p>
<h2 id="heading-option-1-more-setup">Option 1: More Setup</h2>
<p>A little more setup could get us what we needed. By recording the previous count, we calculate the next count and match against that. </p>
<p><strong>spec/models/user_spec.rb</strong></p>
<pre><code class="lang-ruby">describe User <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'creates first_name trail when the user is created '</span> <span class="hljs-keyword">do</span>
    previous_trails_count = <span class="hljs-number">0</span>
    next_trails_count = previous_trails_count + <span class="hljs-number">1</span>
    user = FactoryBot.create(<span class="hljs-symbol">:user</span>)

    expect(user.trails.where(<span class="hljs-symbol">attr_changed:</span> <span class="hljs-string">'first_name'</span>).count ).to be(next_trails_count)
  <span class="hljs-keyword">end</span> 

  it <span class="hljs-string">'creates a trail when the first_name is changed'</span> <span class="hljs-keyword">do</span>
    user = FactoryBot.create(<span class="hljs-symbol">:user</span>)
    previous_trails_count = user.trails.count
    next_trails_count = previous_trails_count + <span class="hljs-number">1</span>

    user.update(<span class="hljs-symbol">first_name:</span> <span class="hljs-string">'Something New'</span>)

    expect(user.trails.where(<span class="hljs-symbol">attr_changed:</span> <span class="hljs-string">'first_name'</span>).count).to be(next_trails_count)
  <span class="hljs-keyword">end</span> 
<span class="hljs-keyword">end</span>
</code></pre>
<p>No more magic numbers!</p>
<p>Unfortunately it is a lot more to read and our specs are not as straight-forward as they once were. </p>
<h2 id="heading-option-2-expecting-change">Option 2: Expecting Change</h2>
<p>RSpec's <code>change</code> matcher is meant for situations just like these. When we pass a block to both the <code>expect</code> and <code>change</code> methods it we can hide all the setup we had to define explicitly in the examples above. Here's what those two tests would look like re-written with <code>change</code>:</p>
<p><strong>spec/models/user_spec.rb</strong></p>
<pre><code class="lang-ruby">describe User <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'creates first_name trail when the user is created '</span> <span class="hljs-keyword">do</span>
    user = FactoryBot.build(<span class="hljs-symbol">:user</span>)

    expect { user.save }.to(
      change { user.trails.where(<span class="hljs-symbol">attr_changed:</span> <span class="hljs-string">'first_name'</span>).count }
    )
  <span class="hljs-keyword">end</span> 

  it <span class="hljs-string">'creates a trail when the first_name is changed'</span> <span class="hljs-keyword">do</span>
    user = FactoryBot.create(<span class="hljs-symbol">:user</span>)

    expect { user.update(<span class="hljs-symbol">first_name:</span> <span class="hljs-string">'Something New'</span>) }.to(
      change { user.trails.where(<span class="hljs-symbol">attr_changed:</span> <span class="hljs-string">'first_name'</span>).count }
    )
  <span class="hljs-keyword">end</span> 
<span class="hljs-keyword">end</span>
</code></pre>
<h3 id="heading-how-to-read-a-change-expectation">How to read a <code>change</code> expectation</h3>
<p>These <code>change</code> expectations are a bit confusing at first glance, so let's try to break it down.</p>
<p>Here is the basic structure</p>
<pre><code class="lang-ruby">expect(block_that_does_something).to change(block_that_gets_value)
</code></pre>
<p>A rough re-write of this execution path might look like this:</p>
<pre><code class="lang-ruby">previous_value = block_that_gets_value.call()

block_that_does_something.call()

next_value = block_that_gets_value.call()

expect(next_value).to_not be(previous_value)
</code></pre>
<h2 id="heading-expecting-more">Expecting more</h2>
<p>There's more to the <code>change</code> matcher then I've shown here. Auxiliary methods allow us to specify by how much the value should change, exactly what it should change too, and also assert that it did <em>not</em> change.</p>
<p>To learn more about these methods you can visit the <a target="_blank" href="https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/change-matcher">RSpec Documentation</a></p>
]]></content:encoded></item><item><title><![CDATA[An Introduction to Contract Testing in Rails]]></title><description><![CDATA[After years of listening to J.B. Rainsberger tell me Contract tests are great, I finally started listening. 
I always assumed they were confusing or hard for some reason. Turns out I was really wrong. To help you along I've written this short tutoria...]]></description><link>https://blog.nolanphillips.com/contract-testing-in-rails</link><guid isPermaLink="true">https://blog.nolanphillips.com/contract-testing-in-rails</guid><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Testing]]></category><category><![CDATA[Ruby]]></category><dc:creator><![CDATA[Nolan Phillips]]></dc:creator><pubDate>Tue, 03 May 2022 19:58:28 GMT</pubDate><content:encoded><![CDATA[<p>After years of listening to <a target="_blank" href="https://twitter.com/jbrains">J.B. Rainsberger</a> tell me Contract tests are great, I finally started listening. </p>
<p>I always assumed they were confusing or hard for some reason. Turns out I was <em>really</em> wrong. To help you along I've written this short tutorial on how to write Contract Tests in Rails with RSPec.</p>
<h2 id="heading-duck-typing">Duck Typing</h2>
<p>One of the great things about dynamic languages is <a target="_blank" href="https://realpython.com/lessons/duck-typing/#:~:text=Duck%20typing%20is%20a%20concept,a%20given%20method%20or%20attribute.">Duck Typing</a>. This allows us to define methods that aren't fussy about the type of objects they're given. As long as it has the methods we need and they work roughly how we expect, we'll take it!</p>
<h2 id="heading-a-problem-with-duck-typing">A Problem with Duck Typing</h2>
<p>How can we be really confident that our objects behave correctly?</p>
<p>You <em>could</em> write two separate test suites that essentially have duplicate tests. Unfortunately, as time passes those test suites will almost certainly drift apart. As your team grows, and more objects are added that should fit the contract, the likelihood of forgetting to sync changes rises.</p>
<p>Instead we can write a Contract.</p>
<h2 id="heading-what-is-a-contract">What is a Contract?</h2>
<p>A Contract is simply a description of how to work with an object.</p>
<p>In theory, Contracts are similar to Interfaces. Like an Interface, a Contract tells you what methods an object should have. <strong>But unlike an Interface, a Contract <em>also</em> tells you how an object should behave.</strong></p>
<p>In practice, Contracts are shareable test suites. They are written to test any type of object. By adding them to your object's test suite you can ensure that it properly adheres to the contract. Better yet, it will be fully covered by tests without having to write any duplicate test code.</p>
<h2 id="heading-example-writing-contracts-in-rspec">Example: Writing Contracts in RSPec</h2>
<p>RSpec has a feature called <a target="_blank" href="https://relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples"><code>shared_examples</code></a> which lets you include tests into any test suite. We'll look at a real example of a Contract test I added to the codebase at work. </p>
<p>At <a target="_blank" href="https://heartpayroll.com">HeartPayroll</a> (HP) we have two kinds of accounts: <code>Employers</code> and <code>Employees</code>. These are separate tables, with a lot of difference, but they do have some things in common. For example, they both have first and last names and convenience methods for displaying them (e.g. <code>account.full_name</code>, <code>account.last_name_first_name</code>)</p>
<p>In essence, the <code>Employee</code> and <code>Employer</code> classes share a "Contract". Anytime we're looking to display information about an account, we expect to be given either class. </p>
<p>To ensure these classes behave as expected, I created a new contract in the spec folder:</p>
<p><strong>spec/contracts/nameable.rb</strong></p>
<pre><code class="lang-ruby">RSpec.shared_examples <span class="hljs-string">'nameable'</span> <span class="hljs-keyword">do</span> <span class="hljs-params">|nameable_factory|</span>
  describe <span class="hljs-string">'#full_name'</span> <span class="hljs-keyword">do</span>
    it <span class="hljs-string">'returns full name'</span> <span class="hljs-keyword">do</span>
      nameable = FactoryBot.build(nameable_factory)

      expect(nameable.full_name).to eq([nameable.first_name, nameable.last_name].compact.join(<span class="hljs-string">' '</span>).strip)
    <span class="hljs-keyword">end</span>
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>This spec file is a bit different than the usual spec. </p>
<ul>
<li>It uses <code>RSpec.shared_examples</code> not <code>RSpec.describe</code></li>
<li>It accepts <code>nameable_factory</code></li>
<li>It dynamically constructs it's subject using the passed in <code>nameable_factory</code></li>
</ul>
<p>This is effectively an Abstract Test Suite. It can run on any type of object to ensure it adheres to the "Nameable" Contract. </p>
<p>To include it with our specs, we can use the <a target="_blank" href="https://relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples"><code>include_examples</code> method</a> in both our Employer specs...</p>
<p><strong>spec/models/employer.rb</strong></p>
<pre><code class="lang-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">'contracts/nameable'</span>

RSpec.describe Employer, <span class="hljs-symbol">type:</span> <span class="hljs-symbol">:model</span> <span class="hljs-keyword">do</span>
  include_examples <span class="hljs-string">'nameable'</span>, <span class="hljs-symbol">:employer</span>

  <span class="hljs-comment"># ...rest of Employer tests...</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>And in the Employee specs</p>
<p><strong>spec/models/employee.rb</strong></p>
<pre><code class="lang-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">'contracts/nameable'</span>

RSpec.describe Employee, <span class="hljs-symbol">type:</span> <span class="hljs-symbol">:model</span> <span class="hljs-keyword">do</span>
  include_examples <span class="hljs-string">'nameable'</span>, <span class="hljs-symbol">:employee</span>

  <span class="hljs-comment"># ...rest of Employee tests...</span>
<span class="hljs-keyword">end</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Testing GraphQL in Rails]]></title><description><![CDATA[Goals
When we set out to test our GraphQL API we wanted 3 things:

To write GQL queries as a string
To keep network details out of spec files
To keep GQL queries out of individual tests


Assumptions: This article assumes you have a working Rails app...]]></description><link>https://blog.nolanphillips.com/testing-graphql-in-rails</link><guid isPermaLink="true">https://blog.nolanphillips.com/testing-graphql-in-rails</guid><category><![CDATA[GraphQL]]></category><category><![CDATA[Ruby on Rails]]></category><category><![CDATA[Ruby]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Nolan Phillips]]></dc:creator><pubDate>Wed, 13 Apr 2022 19:06:04 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-goals">Goals</h2>
<p>When we set out to test our GraphQL API we wanted 3 things:</p>
<ol>
<li>To write GQL queries as a string</li>
<li>To keep network details out of spec files</li>
<li>To keep GQL queries out of individual tests</li>
</ol>
<blockquote>
<p><strong>Assumptions:</strong> This article assumes you have a working Rails app with authentication and GraphQL already setup. The examples below are written with <code>devise</code>, <code>rspec</code>, <code>factory-bot</code>, and <code>graphql-ruby</code>.</p>
</blockquote>
<h2 id="heading-writing-queries">Writing Queries</h2>
<p>We needed some help. We want to write our queries as strings, and we don't want our specs to know about network requests. To take care of that, we create a helper method that we will include in all of our Specs.</p>
<p><strong>spec/graphql_helper.rb</strong></p>
<pre><code class="lang-ruby"><span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">GraphqlHelper</span></span>
  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">gql</span><span class="hljs-params">(query)</span></span>
    body = { <span class="hljs-symbol">query:</span> query }

    post <span class="hljs-string">'/api/graphql'</span>, <span class="hljs-symbol">params:</span> body

    JSON.parse(response.body)
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>RSpec let's us add modules at configuration time:</p>
<p><strong>spec/rails_helper.rb</strong></p>
<pre><code class="lang-ruby">RSpec.configure <span class="hljs-keyword">do</span> <span class="hljs-params">|config|</span>
   config.<span class="hljs-keyword">include</span> GraphqlHelper
   <span class="hljs-comment"># ...</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h2 id="heading-what-are-we-testing">What are we testing?</h2>
<p>We're going to write a couple test for querying the currently logged in user.</p>
<p><strong>spec/graph/current_user_spec.rb</strong></p>
<pre><code class="lang-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">'rails_helper'</span>

describe <span class="hljs-string">'Current User Graph'</span>, <span class="hljs-symbol">type:</span> <span class="hljs-symbol">:request</span> <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'is nil when not logged in'</span>
  it <span class="hljs-string">'is the signed in user'</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p><strong>Note:</strong> Make sure to add <code>type: request</code> to the describe block.</p>
<h2 id="heading-define-the-query">Define the Query</h2>
<p>Adding a query method to the test-class helps keep the individual specs clean. Let's add it as a private method so it's clearly separated from the specs:</p>
<p><strong>spec/graph/current_user_spec.rb</strong></p>
<pre><code class="lang-ruby">describe <span class="hljs-string">'Current User Graph'</span>, <span class="hljs-symbol">type:</span> <span class="hljs-symbol">:request</span> <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'is nil when not logged in'</span>
  it <span class="hljs-string">'is the signed in user'</span>

  private

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">query_user</span></span>
    response = gql <span class="hljs-string">&lt;&lt;-GQL
      query CurrentUserSpec {
        user {
          firstName
          lastName
        }
      }
    GQL</span>

    response.dig(<span class="hljs-string">'data'</span>, <span class="hljs-string">'user'</span>)
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<p>It's often useful to dig the value you're interested in out of the response. This really makes checking the data easier. </p>
<h2 id="heading-testing-the-logged-out-state">Testing the logged-out state</h2>
<p>There is no user when we're logged out, so we need to test for that. Thanks to our helpers it is a very small test:</p>
<p><strong>spec/graph/current_user.rb</strong></p>
<pre><code class="lang-ruby">describe <span class="hljs-string">'Current User Graph'</span>, <span class="hljs-symbol">type:</span> <span class="hljs-symbol">:request</span> <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'is nil when not logged in'</span> <span class="hljs-keyword">do</span>
    user_data = query_user

    expect(user_data).to be_nil
  <span class="hljs-keyword">end</span>

  <span class="hljs-comment">#...</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h2 id="heading-testing-the-logged-in-state">Testing the logged-in state</h2>
<p><strong>spec/graph/current_user_spec.rb</strong></p>
<pre><code class="lang-ruby">describe <span class="hljs-string">'Current User Graph'</span>, <span class="hljs-symbol">type:</span> <span class="hljs-symbol">:request</span> <span class="hljs-keyword">do</span>
  <span class="hljs-comment"># ...</span>

  it <span class="hljs-string">'is the signed in user'</span> <span class="hljs-keyword">do</span>
    user = FactoryBot.create(<span class="hljs-symbol">:user</span>)
    sign_in user

    user_data = query_user

    expect(user_data[<span class="hljs-string">'firstName'</span>]).to eq(user.first_name)
    expect(user_data[<span class="hljs-string">'lastName'</span>]).to eq(user.last_name)
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
<h2 id="heading-review">Review</h2>
<p>Here is the end-state of our <code>current_user_spec</code>.</p>
<pre><code class="lang-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">'rails_helper'</span>

describe <span class="hljs-string">'Current User Graph'</span>, <span class="hljs-symbol">type:</span> <span class="hljs-symbol">:request</span> <span class="hljs-keyword">do</span>
  it <span class="hljs-string">'is nil when not logged in'</span> <span class="hljs-keyword">do</span>
    user_data = query_user

    expect(user_data).to be_nil
  <span class="hljs-keyword">end</span>

  it <span class="hljs-string">'is the signed in user'</span> <span class="hljs-keyword">do</span>
    user = FactoryBot.create(<span class="hljs-symbol">:user</span>)
    sign_in user

    user_data = query_user

    expect(user_data[<span class="hljs-string">'firstName'</span>]).to eq(user.first_name)
    expect(user_data[<span class="hljs-string">'lastName'</span>]).to eq(user.last_name)
  <span class="hljs-keyword">end</span>

  private

  <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">query_user</span></span>
    response = gql <span class="hljs-string">&lt;&lt;-GQL
      query CurrentUserSpec {
        user {
          firstName
          lastName
        }
      }
    GQL</span>

    response.dig(<span class="hljs-string">'data'</span>, <span class="hljs-string">'user'</span>)
  <span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[The React Named Children Pattern]]></title><description><![CDATA[Composition
One of the key concepts of React development is composition
Composition is all about making BigThings by combining many SmallThings together.
Let’s look at a few ways to do this.
The Children Pattern
The simplest technique we have is The ...]]></description><link>https://blog.nolanphillips.com/the-react-named-children-pattern</link><guid isPermaLink="true">https://blog.nolanphillips.com/the-react-named-children-pattern</guid><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[design patterns]]></category><dc:creator><![CDATA[Nolan Phillips]]></dc:creator><pubDate>Wed, 12 Aug 2020 11:20:24 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-composition">Composition</h2>
<p>One of the key concepts of React development is composition</p>
<p>Composition is all about making BigThings by combining many SmallThings together.</p>
<p>Let’s look at a few ways to do this.</p>
<h2 id="heading-the-children-pattern">The Children Pattern</h2>
<p>The simplest technique we have is <strong>The Children Pattern</strong>. It is the first pattern you learn in the <a target="_blank" href="https://reactjs.org/docs/introducing-jsx.html">React documentation</a>.</p>
<p>If we wanted to render the text <code>Hello World</code> inside of a <code>&lt;Card&gt;</code> component we would like do it this way:</p>
<pre><code class="lang-JavaScripts">&lt;Card&gt;Hello World&lt;/Card&gt;
</code></pre>
<p>The Children Pattern is about displaying content, but sometimes there are other messages we want to send our component. </p>
<p>If we're looking to make our <code>&lt;Card&gt;</code> component larger, we might tell it that via the <code>size</code> prop. </p>
<pre><code class="lang-javascript">&lt;Card size=<span class="hljs-string">"large"</span>&gt;Hello World&lt;/Card&gt;
</code></pre>
<p>This pattern works if <code>&lt;Card&gt;</code> has just one content section but not if it has many. </p>
<h2 id="heading-the-props-children-pattern">The Props-Children Pattern</h2>
<p>When we have many children, <strong>The Props-Children Pattern</strong> can be useful. </p>
<p>Instead of passing our text in via <code>children</code> we pass it as a <code>prop</code>:</p>
<pre><code class="lang-javascript">&lt;Card
  size=<span class="hljs-string">"large"</span>

  title=<span class="hljs-string">"Hello World"</span>
  subtitle=<span class="hljs-string">"This is a basic example"</span>
  body=<span class="hljs-string">"Here is where a lot more text would go."</span>
/&gt;
</code></pre>
<p>Unfortunately this makes unfamiliar components harder to understand since <strong>its props might set its appearance <em>OR</em> its content</strong>. </p>
<p>It also becomes super ugly when the content is not just plain text:</p>
<pre><code class="lang-javascript">&lt;Card
  size=<span class="hljs-string">"large"</span>
  title=<span class="hljs-string">"Hello World"</span>
  subtitle={
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      This is a basic <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>example<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  }
  body=<span class="hljs-string">"Here is where a lot more text would go."</span>
/&gt;
</code></pre>
<h2 id="heading-the-named-children-pattern">The Named Children Pattern</h2>
<p>The <em>Named Children</em> pattern helps with both the mixing of concerns and (subjectively) the ugliness. </p>
<p>React's <code>children</code> does not need to be a component or even a string, it can be a Plain Old Javascript Object. Because of this we pass <code>children</code> an object that maps section names too different content. </p>
<pre><code class="lang-javascript">&lt;Card size=<span class="hljs-string">"large"</span>&gt;
{{
  <span class="hljs-attr">title</span>: <span class="hljs-string">"Hello World"</span>
  <span class="hljs-attr">subtitle</span>: <span class="xml"><span class="hljs-tag">&lt;&gt;</span>This is a basic <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>example<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/&gt;</span></span>
  body: <span class="hljs-string">"Here is where a lot more text would go."</span>
}}
&lt;/Card&gt;
</code></pre>
<p>This approach separates content from config making it easier to know whether the prop is for changing its appearance or its content. </p>
<h2 id="heading-implementing-the-named-children-pattern">Implementing the Named Children Pattern</h2>
<p>The Named Children Pattern must be hard to implement, right?</p>
<p>Nope! Although <code>children</code> are set differently <em>outside</em> of the component, <em>inside</em> they're treated like any other prop:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Card</span>(<span class="hljs-params">{ size = <span class="hljs-string">"medium"</span>, children }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{size}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{children.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{children.subtitle}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{children.body<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
</code></pre>
<p>The <em>Named Children</em> pattern is a promising approach to <a target="_blank" href="https://en.wikipedia.org/wiki/Separation_of_concerns">separating concerns</a> in React Components making them easier to read and easier to change.</p>
]]></content:encoded></item></channel></rss>