<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Andy Robinson</title>
    <description>The latest articles on Forem by Andy Robinson (@freshcaffeine).</description>
    <link>https://forem.com/freshcaffeine</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%2F2081107%2F2e2972d2-af5d-4853-b418-098e9c384f3d.png</url>
      <title>Forem: Andy Robinson</title>
      <link>https://forem.com/freshcaffeine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/freshcaffeine"/>
    <language>en</language>
    <item>
      <title>Is AI Turning Software into flat-pack Furniture?</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Wed, 01 Apr 2026 14:59:00 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/is-ai-turning-software-into-flat-pack-furniture-452a</link>
      <guid>https://forem.com/freshcaffeine/is-ai-turning-software-into-flat-pack-furniture-452a</guid>
      <description>&lt;p&gt;AI-assisted development is incredible. Tools like Claude, Copilot and Warp are helping us to move faster, reduce friction and understand complex systems more easily.&lt;/p&gt;

&lt;p&gt;In an increasing number of teams using them isn’t optional, it’s expected. The results speak for themselves. Productivity is up. Delivery is faster. Barriers are lower.&lt;/p&gt;

&lt;p&gt;But there’s a trade-off I don’t see discussed enough - Coding is starting to feel different. What was a craft is now a process:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Plan → Refine → Generate → Review → Adjust → Generate Commit message → AI-Assisted Peer Review → Ship&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s less time spent exploring the problem space. Less trial and error. Less of that moment where a solution finally “clicks” - for me, the best bit!&lt;/p&gt;

&lt;p&gt;It reminds me of the flat-pack furniture you get from Ikea. AI gives you all the pieces and instructions and then it'll even assembly it for you (like Airtasker or Task Rabbit). But it’s not quite the same as designing and building something yourself.&lt;/p&gt;

&lt;p&gt;So where does that leave the craft of software engineering? Will thoughtful system design, elegant code, and carefully crafted user experiences become the “handmade furniture” of our industry? will it be more rare, but more valuable?&lt;/p&gt;

&lt;p&gt;I don’t think the answer is to stop using AI. But I do think we need to be intentional about how we use it. Because if we outsource too much of the thinking, we risk losing not just skills - but the joy that brought many of us into this field.&lt;/p&gt;

&lt;p&gt;And yes—this post was (appropriately) co-written with AI.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Reflecting on My Time at Kainos</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Wed, 02 Apr 2025 15:40:18 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/reflecting-on-my-time-at-kainos-14of</link>
      <guid>https://forem.com/freshcaffeine/reflecting-on-my-time-at-kainos-14of</guid>
      <description>&lt;p&gt;This Friday marks my last day at Kainos, closing a chapter of six incredible years. As I reflect on my journey, I can’t help but be grateful for the experiences, the lessons learned, and most importantly, the people who made this journey so special.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Day: A Belfast Beginning
&lt;/h2&gt;

&lt;p&gt;I still vividly remember my first day, arriving in Belfast for onboarding and picking up my laptop. The taxi ride from the airport was a mix of excitement and nerves, and I recall pointing out the &lt;a href="https://en.wikipedia.org/wiki/Europa_Hotel,_Belfast" rel="noopener noreferrer"&gt;Europa Hotel&lt;/a&gt; — famously known as Europe’s most bombed hotel, earning the name "the Hardboard Hotel". That moment set the stage for an adventure that would shape my career in ways I couldn't have imagined.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Kainos Annual Kick-Off
&lt;/h2&gt;

&lt;p&gt;A few weeks later, I attended my first Kainos Annual Kick-Off. It was an opportunity to immerse myself in the company’s culture — a culture that encouraged sharing ideas, knowledge, and collaboration. The warmth and openness of the people I met left a lasting impression on me, and it was clear that I had joined a special place. These sadly stopped after the pandemic, I really wish Kainos would start them up again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The NHS App: A Project to Remember
&lt;/h2&gt;

&lt;p&gt;Starting my first project on the NHS App was another unforgettable milestone. I was so nervous on my first day that I lost my wedding ring on the train to Leeds! Despite that shaky start, working on the NHS App was an incredible experience. The team genuinely cared about the product, and that passion shone through in our work.&lt;/p&gt;

&lt;p&gt;I remember the early days of 2020, watching the news as COVID cases spread across Europe, and then the whirlwind that followed. The pandemic tested us in ways we never expected, with the app scaling to handle a million new users every time Boris Johnson made an announcement. It was intense, but it was also inspiring to see the real-world impact of our work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The NHS Wales App: A New Challenge
&lt;/h2&gt;

&lt;p&gt;Starting on the NHS Wales App felt like stepping into a new chapter within Kainos. Introducing a brand-new project team to the code obtained from England was both a challenge and an opportunity. I remember the excitement of seeing the app go live in the app stores and watching the first reviews trickle in. Moments like that remind me why I love building software—seeing the real impact it has on people’s lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parting Thoughts
&lt;/h2&gt;

&lt;p&gt;I will always remember my time at Kainos fondly. The people here are the best I’ve ever worked with, and I will miss you all dearly - from the looks &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7305269972065259520/" rel="noopener noreferrer"&gt;this LinkedIn post&lt;/a&gt; the feeling is mutual. Kainos transformed me — from from what  developer into a talented software engineer and architect.&lt;/p&gt;

&lt;p&gt;Thank you for these last six years. It’s been an unforgettable ride, and I look forward to seeing where our paths cross again in the future!&lt;/p&gt;

</description>
      <category>career</category>
      <category>kainos</category>
    </item>
    <item>
      <title>Why Learn Rust?</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Sat, 22 Mar 2025 09:35:37 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/why-learn-rust-2ipe</link>
      <guid>https://forem.com/freshcaffeine/why-learn-rust-2ipe</guid>
      <description>&lt;p&gt;I’ve been hearing a lot about Rust lately—a fast, safe, and reliable programming language that’s taking the tech world by storm. According to the &lt;strong&gt;Stack Overflow Developer Survey 2024&lt;/strong&gt;, Rust was voted the &lt;strong&gt;most-admired programming language&lt;/strong&gt; with an impressive 83%, holding that title since 2016! It’s used in web development, game development, systems programming, and more. Naturally, I got curious—why is everyone so excited about Rust?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should You Learn Rust?
&lt;/h2&gt;

&lt;p&gt;Rust’s popularity isn’t just hype; there are solid reasons why developers love it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt; – Rust is designed for high performance, making it ideal for systems programming and resource-intensive applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt; – Its strict memory management and borrow checker eliminate common bugs like null pointer dereferences and buffer overflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt; – Rust makes it easier to write multi-threaded programs without the usual race conditions and deadlocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you care about writing fast, efficient, and secure code, Rust is worth learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Rust
&lt;/h2&gt;

&lt;p&gt;If you’re ready to dive in, here are some top resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://doc.rust-lang.org/book/" rel="noopener noreferrer"&gt;The Rust Programming Language&lt;/a&gt;&lt;/strong&gt; (a.k.a. "The Rust Book") – A must-read for beginners.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://doc.rust-lang.org/stable/rust-by-example/" rel="noopener noreferrer"&gt;Rust by Example&lt;/a&gt;&lt;/strong&gt; – Learn through hands-on examples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://users.rust-lang.org/" rel="noopener noreferrer"&gt;The Rust Forum&lt;/a&gt;&lt;/strong&gt; – Join the community and get support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/rust-lang/rustlings" rel="noopener noreferrer"&gt;Rustlings&lt;/a&gt;&lt;/strong&gt; – A great interactive way to practice Rust syntax and concepts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Can You Build with Rust?
&lt;/h2&gt;

&lt;p&gt;Rust is incredibly versatile. Here are some cool things you can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Web Servers&lt;/strong&gt; – Frameworks like Actix and Axum make it easy to build high-performance web applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Game Development&lt;/strong&gt; – Rust’s performance makes it great for game engines, with libraries like Bevy gaining traction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command-Line Tools&lt;/strong&gt; – Create fast, reliable CLI tools with Rust’s strong ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operating Systems &amp;amp; Embedded Systems&lt;/strong&gt; – Rust is even being used in OS development (hello, &lt;strong&gt;Rust in Linux kernel&lt;/strong&gt;!).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rust in Action
&lt;/h2&gt;

&lt;p&gt;Let’s check out a simple Rust program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, Rust!"&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;This basic program prints “Hello, Rust!” to the console. Rust’s syntax is clear, and its compiler provides incredibly helpful error messages, making it a great language for both beginners and experienced developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;If you're excited to try Rust, start with the official documentation and work on a small project. Whether it’s a web app, a command-line tool, or even a game, Rust offers a fantastic blend of speed, safety, and reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Rust isn’t just another programming language—it’s a movement towards safer, more efficient software. Whether you're a systems programmer, a web developer, or just someone who loves exploring new languages, Rust has something for you.&lt;/p&gt;

&lt;p&gt;So, why not give Rust a shot? 🚀&lt;/p&gt;

&lt;p&gt;What are your thoughts on Rust? Have you tried it yet? Let’s chat!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>development</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What Is Three Amigos and Why Do It?</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Fri, 21 Mar 2025 17:15:17 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/what-is-three-amigos-and-why-do-it-39lc</link>
      <guid>https://forem.com/freshcaffeine/what-is-three-amigos-and-why-do-it-39lc</guid>
      <description>&lt;p&gt;If you've ever seen the classic '80s comedy &lt;em&gt;¡Three Amigos!&lt;/em&gt;, you know it’s about three out-of-their-depth actors mistaken for real heroes. In Agile development, our &lt;strong&gt;Three Amigos&lt;/strong&gt; aren’t fighting bandits in a Mexican village—but they are here to save your team from misunderstandings, rework, and bad surprises!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is the Three Amigos?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Three Amigos&lt;/strong&gt; is a short but crucial meeting where three key perspectives align before development starts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Business Rep (Product Owner or Business Analyst)&lt;/strong&gt; – Ensures the feature solves the right problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Developer&lt;/strong&gt; – Figures out how to build it and highlights any tech challenges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Tester (QA Engineer or Test Analyst)&lt;/strong&gt; – Focuses on how we’ll know it actually works.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they hash out the details, clear up confusion, and make sure everyone is on the same page before code starts flying.&lt;/p&gt;

&lt;h2&gt;
  
  
  When (and Why) We Do a Three Amigos
&lt;/h2&gt;

&lt;p&gt;Some teams do this as part of backlog refinement, but our team has found it works best &lt;strong&gt;just after a developer picks up a story&lt;/strong&gt;—but always &lt;strong&gt;before a pull request is raised&lt;/strong&gt;. Here’s why:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Perks of This Timing:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deeper Code Insight&lt;/strong&gt; – The developer has already had a peek at the code, so they can ask smarter questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More Accurate Estimates&lt;/strong&gt; – If it turns out the work is bigger than expected, we can re-point the story before it’s too late.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less Rework&lt;/strong&gt; – Catching issues early means fewer painful surprises during review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Test Coverage&lt;/strong&gt; – The tester can call out sneaky edge cases before they become bugs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How We Run a Three Amigos
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A developer picks up a story&lt;/strong&gt; – They review the requirements and dig into the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We schedule a Three Amigos meeting&lt;/strong&gt; – The developer, business rep, and tester chat about the feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key takeaways from the meeting&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Adjust acceptance criteria if needed.&lt;/li&gt;
&lt;li&gt;Spot any missing edge cases.&lt;/li&gt;
&lt;li&gt;Re-point the story if effort has changed.&lt;/li&gt;
&lt;li&gt;Agree on how to build and test it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development kicks off&lt;/strong&gt; – The dev codes with confidence, knowing there won’t be surprises.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No pull request without a Three Amigos!&lt;/strong&gt; – This ensures we’ve all agreed before code lands in review.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Three Amigos&lt;/strong&gt; meeting is like a safety net for Agile teams—it keeps stories clear, effort realistic, and testing solid. By holding it right after picking up a story, our team has seen fewer blockers, better collaboration, and a lot less "Oh no, we didn’t think of that!" moments. If you’re not doing it yet, give it a shot—your future self (and your testers) will thank you!&lt;/p&gt;

&lt;p&gt;What’s your team’s approach to the Three Amigos? Let’s discuss!&lt;/p&gt;

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

</description>
      <category>agile</category>
      <category>softwareengineering</category>
      <category>refinement</category>
    </item>
    <item>
      <title>Exploring Snapshot Testing in Jest: Pros and Cons</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Thu, 14 Nov 2024 21:28:12 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/exploring-snapshot-testing-in-jest-pros-and-cons-2akj</link>
      <guid>https://forem.com/freshcaffeine/exploring-snapshot-testing-in-jest-pros-and-cons-2akj</guid>
      <description>&lt;p&gt;After years of writing Jest tests, I recently stumbled upon &lt;a href="https://jestjs.io/docs/snapshot-testing" rel="noopener noreferrer"&gt;Snapshot Testing&lt;/a&gt; — a feature in Jest that can streamline testing for certain types of code, particularly UI components. If you are not familiar, snapshot testing is a way to assert that the rendered output of a component hasn’t changed unexpectedly. Jest generates a "snapshot" of the component’s output and stores it. Future tests compare the current output against this snapshot, flagging differences that may indicate unintended changes.&lt;/p&gt;

&lt;p&gt;In this post, I’ll share my experiences so far with snapshot testing in Jest, including the pros and cons I’ve encountered along the way. Let’s dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Snapshot Testing?
&lt;/h2&gt;

&lt;p&gt;Snapshot testing is a testing technique that captures the output of a component or function and saves it as a file. When you run your tests, Jest compares the current output with the saved snapshot to determine if anything has changed.&lt;/p&gt;

&lt;p&gt;Here’s a simple example of snapshot testing in Jest:&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;// myComponent.test.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;renderer&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-test-renderer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Link&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;../Link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders correctly&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="nx"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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;Link&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.facebook.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Facebook&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;)
&lt;/span&gt;    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toJSON&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toMatchSnapshot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this test, Jest renders &lt;code&gt;MyComponent&lt;/code&gt; and saves the output as a snapshot.&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;// myComponent.test.js.snap&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`renders correctly 1`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
&amp;lt;a
  className="normal"
  href="http://www.facebook.com"
  onMouseEnter={[Function]}
  onMouseLeave={[Function]}
&amp;gt;
  Facebook
&amp;lt;/a&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;On subsequent test runs, Jest compares the new output with the saved snapshot to check for any changes. If the output has changed, Jest alerts you so you can review the differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros of Snapshot Testing
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quick and Simple:&lt;/strong&gt; Creating snapshot tests is fast. By running toMatchSnapshot(), Jest automatically saves a snapshot of the component’s current structure, allowing you to focus on functionality. The generated snapshots are stored in .snap files and are versioned with your rest, making changes easy to code review.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduces Boilerplate:&lt;/strong&gt; Snapshot tests can help eliminate repetitive assertions, especially when dealing with complex UI structures. This is particularly helpful in Vue or React, where UI states change frequently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Catching Unexpected Changes:&lt;/strong&gt; Snapshot testing is great for catching unexpected changes in your code. If a UI component’s output changes unexpectedly, Jest will flag it as a failed test, prompting you to review the changes. This can help you catch regressions early and prevent bugs from slipping through the cracks.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cons of Snapshot Testing
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fragile Tests:&lt;/strong&gt; One of the downsides of snapshot testing is that tests could become fragile over time. If your UI components change frequently, snapshots may need to be updated frequently as well. This can lead to a lot of noise in your test results and make it harder to identify real issues. Additionally, large snapshots can lead to a phenomenon called "snapshot blindness," where developers mindlessly approve changes without closely examining them. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of Context:&lt;/strong&gt; When a snapshot test fails, it can be challenging to understand why the output has changed. Jest provides a visual diff of the changes, but it doesn’t always give you the full context of what caused the change. This can make debugging failures more difficult, especially for complex components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Insight:&lt;/strong&gt; While snapshots check that a component’s structure hasn’t changed, they don’t verify behavioural aspects. You might still need unit or integration tests to cover these cases. Snapshot testing is best suited for testing the visual output of components, not their functionality. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Snapshot testing in Jest is a powerful tool for testing UI components and capturing changes in your code. While it offers several benefits, such as easy setup and catching unexpected changes, it also has its drawbacks, like fragile tests and false positives. Perhaps its better to use snap shot tests sparingly, for components that should change infrequently, and therefore have a stable snapshot. It’s also important to remember that snapshot testing is just one piece of the testing puzzle and should be used in conjunction with other testing strategies to ensure comprehensive test coverage.&lt;/p&gt;

&lt;p&gt;Overall, snapshot testing is a useful technique to have in your testing arsenal, but like any tool, it’s essential to use it judiciously and understand its limitations. By weighing the pros and cons of snapshot testing, you can make an informed decision about whether it’s the right choice for your testing workflow.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>jest</category>
      <category>testing</category>
    </item>
    <item>
      <title>Blazor #3 - How to Install Foundation into a Blazor Project</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Sun, 20 Oct 2024 20:13:52 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/blazor-3-how-to-install-foundation-into-a-blazor-project-4ch0</link>
      <guid>https://forem.com/freshcaffeine/blazor-3-how-to-install-foundation-into-a-blazor-project-4ch0</guid>
      <description>&lt;p&gt;If you're working on a Blazor project you'll probably want to use a modern front-end framework, Blazor's starter site already comes shipped with &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt;, which is great, but there are other options out there like Bulma, Tailwind or Material. &lt;/p&gt;

&lt;p&gt;In this blog post, we’ll walk through the steps to install and configure Foundation within your Blazor project, although the concepts will work well with other frameworks too. Foundation is known for its flexibility and robust grid system so offers the tools you need to create responsive, accessible, and visually appealing web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Foundation?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://get.foundation/" rel="noopener noreferrer"&gt;Foundation&lt;/a&gt; is a mobile-first responsive front-end framework that provides a range of CSS and JavaScript components for creating websites quickly. It’s often seen as a competitor to Bootstrap, offering more flexibility and customization options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you start, make sure you have followed my previous post on &lt;a href="https://dev.to/blog/2024/blazor-2-working-with-sass/"&gt;How to work with SASS in Blazor&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install Foundation via npm
&lt;/h2&gt;

&lt;p&gt;First, we need to install Foundation’s CSS and JavaScript assets. To do this, we’ll use npm (Node Package Manager).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initialise npm:&lt;/strong&gt; If your Blazor project doesn't already have a package.json, initialise npm by running the following command in your project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Install Foundation:&lt;/strong&gt; Run the following command to install Foundation along with its 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;npm &lt;span class="nb"&gt;install &lt;/span&gt;foundation-sites &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install Foundation’s assets into the node_modules folder. Now these are added there is nothing stopping us from running our blazor project so we can watch the changes in the full glory of &lt;code&gt;🔥 Hot reload&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Taking off the Bootstaps
&lt;/h2&gt;

&lt;p&gt;Its always good to start with a clean slate, so lets start by removing all the bootstrap nonsense. &lt;/p&gt;

&lt;p&gt;In the App.Razor file, remove &lt;code&gt;&amp;lt;link rel="stylesheet" href="bootstrap/bootstrap.min.css" /&amp;gt;&lt;/code&gt;. Then delete the whole &lt;code&gt;bootstrap&lt;/code&gt; directory from within &lt;code&gt;wwwroot&lt;/code&gt;. In the new world, Foundation will be bundled in the SassCompiler generated &lt;code&gt;css/styles.css&lt;/code&gt;, &lt;/p&gt;

&lt;p&gt;Right now, you're site should look a bit like in the image below. What remains, is the from styles we migrated to Sass in the last post. Lets clear all of that too. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finmpyjcizrctqut3e59b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finmpyjcizrctqut3e59b.png" alt="Partly broken Blazor site" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Delete the following scss files, as they are no longer needed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/Styles/Components/Layout/_mainLayout.scss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/Styles/Components/Layout/_navMenu.scss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/Styles/Components/_blazor.scss&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And empty the contents of the following, we may need these later&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/Styles/_components.scss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/Styles/_mixins.scss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/Styles/_variables.scss&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, create a new file &lt;code&gt;/Styles/Components/_blazor.scss&lt;/code&gt; with the following styles; adding the &lt;code&gt;@import&lt;/code&gt; in &lt;code&gt;/Styles/_components.scss&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nn"&gt;#blazor-error-ui&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#ffffe0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;.dismiss&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="mi"&gt;.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you're site should look even more basic&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxrza0w44ji97yp01ocf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxrza0w44ji97yp01ocf.png" alt="A very unstyled Blazor site" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Add Foundation the to the styles.scss
&lt;/h2&gt;

&lt;p&gt;Add a new scss file in &lt;code&gt;/Styles/Components/&lt;/code&gt;  called &lt;code&gt;_foundation.scss&lt;/code&gt;, and import it the&lt;code&gt;/Styles/_components.scss&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'Components/blazor-error'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'Components/foundation'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now import the the foundation Sass from the &lt;code&gt;node-modules&lt;/code&gt; that was installed in Step 1, with Foundation, you also need to initialise the styles with &lt;code&gt;@include foundation-everything;&lt;/code&gt;; or nothing would show.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s2"&gt;"../node_modules/foundation-sites/scss/foundation.scss"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@include&lt;/span&gt; &lt;span class="nd"&gt;foundation-everything&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Each Foundation component has an export mixin which prints out the CSS for that component. For simplicity I'm including everything, but in a production site, you can pick and choose what you need. See the &lt;a href="https://get.foundation/sites/docs/sass.html#adjusting-css-output" rel="noopener noreferrer"&gt;Adjusting CSS Output documentation&lt;/a&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now your website should be running on Foundation, and look a little better (well, the fonts and colours anyhow)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0yyx2gcbk1btvy8ztz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0yyx2gcbk1btvy8ztz3.png" alt="A slightly styled Blazor site" width="692" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait, I'm getting the following error
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1unlhz2f9d7na3iga6dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1unlhz2f9d7na3iga6dc.png" alt="Ohh no, Scss error!" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I got stuck on this for a while, and almost decided to go for another framework because of it. It turns out that the &lt;code&gt;color.channel()&lt;/code&gt; Scss function is only included in newer version of the &lt;code&gt;AspNetCore.SassCompiler&lt;/code&gt; nuget package, upgrade to the newest release and you'll be fine. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Start adding some Foundation components
&lt;/h2&gt;

&lt;p&gt;Now that you have Foundation installed, you can start using its components in your Blazor project. Here are a few examples to get you started:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Top Bar
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://get.foundation/sites/docs/top-bar.html" rel="noopener noreferrer"&gt;Top Bar&lt;/a&gt; is a responsive navigation bar that adapts to different screen sizes. It’s a great way to create a consistent navigation experience across your site. &lt;/p&gt;

&lt;p&gt;Create a new file &lt;code&gt;/Components/TopBar.razor&lt;/code&gt; and add the following code:&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"top-bar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"top-bar-left"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dropdown menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"menu-text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Fresh Caffeine - Blazor Demo&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"top-bar-right"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;NavLink&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;Match=&lt;/span&gt;&lt;span class="s"&gt;"NavLinkMatch.All"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Home
        &lt;span class="nt"&gt;&amp;lt;/NavLink&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;NavLink&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Counter
        &lt;span class="nt"&gt;&amp;lt;/NavLink&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;NavLink&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"weather"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          Weather
        &lt;span class="nt"&gt;&amp;lt;/NavLink&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, update your &lt;code&gt;MainLayout.razor&lt;/code&gt; file with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@inherits LayoutComponentBase

&lt;span class="nt"&gt;&amp;lt;TopBar&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;main&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"grid-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    @Body
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"blazor-error-ui"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    An unhandled error has occurred.
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"reload"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Reload&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"dismiss"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;times;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;TopBar /&amp;gt;&lt;/code&gt; is a new component that we created in the previous step. It will render the Foundation Top Bar in your Blazor project.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; tag is wrapped in a &lt;code&gt;grid-container&lt;/code&gt; class, which is a Foundation class that creates a responsive grid layout.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;div id="blazor-error-ui"&amp;gt;&lt;/code&gt; is the error message that appears when there’s an unhandled error in your Blazor project. We’re keeping it here for consistency with the default Blazor template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, when you run your Blazor project, you should see the Foundation Top Bar in action.&lt;/p&gt;

&lt;p&gt;Now all that's left to do is to delete the old &lt;code&gt;navMenu&lt;/code&gt; component, and you're all set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22absonvtuqaf8jhgtbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22absonvtuqaf8jhgtbr.png" alt="Home page" width="800" height="272"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95rnxm4u01t5fqhy1ij1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F95rnxm4u01t5fqhy1ij1.png" alt="Counter page" width="800" height="428"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnfz2rxyrjtphfgeamer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnfz2rxyrjtphfgeamer.png" alt="Weather page" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;And that's it! You've successfully installed Foundation into your Blazor project. You can now start using Foundation’s components to build responsive and visually appealing web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample code
&lt;/h2&gt;

&lt;p&gt;I've uploaded the code related to this post to a &lt;a href="https://github.com/fresh-caffeine/BlazorDemo/tree/blog-post/switching-to-foundation" rel="noopener noreferrer"&gt;branch in my Blazor Demo repo in GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>dotnet</category>
      <category>blazor</category>
    </item>
    <item>
      <title>What do story points actually mean?</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Sun, 20 Oct 2024 14:22:32 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/what-do-story-points-actually-mean-25pj</link>
      <guid>https://forem.com/freshcaffeine/what-do-story-points-actually-mean-25pj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the pursuit of better understanding and aligning their estimation process, my team conducted an informal workshop to delve into the meaning of story points during their refinement ceremonies. I feel its good to hold these informal workshops after big team changes to ensure the team are all considering similar elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  How did we do this
&lt;/h2&gt;

&lt;p&gt;Quite simply, we put stickies on a whiteboard. I asked everyone to create a sticky for each thing they consider. Grouping similar ones together we found that they comfortably fit into 5 distinct themes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0mflzec0wyqvuqeimro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0mflzec0wyqvuqeimro.png" alt="Screenshot of stickies on a virtual whiteboard" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 Themes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Evaluate the complexity of the task. Consider how many components or moving parts are involved, how interrelated they are, and how difficult it would be to implement the changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effort&lt;/strong&gt;: Estimate the effort required to complete the task. Take into account the time and resources needed to implement the task, including development, testing, and any potential roadblocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risks and Uncertainties&lt;/strong&gt;: Assess any potential risks or uncertainties associated with the task. Tasks with higher uncertainty may warrant higher story points to account for the additional effort required to handle unforeseen challenges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies&lt;/strong&gt;: Consider whether the task has dependencies on other tasks, teams, or external factors. Dependencies can add complexity and may impact the overall effort needed to complete the task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experience and Expertise&lt;/strong&gt;: Factor in the experience and expertise of the development team. If the team is experienced with similar tasks, they may be able to handle it more efficiently and require fewer story points.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;By identifying these five themes, the team has paved the way for a more structured and cohesive estimation process. They can now approach their refinement ceremonies with a clearer understanding of story points, fostering better collaboration and more accurate project planning. As they continue to refine and improve their estimation practices, the team will likely enhance their overall productivity and deliver successful outcomes in their projects.&lt;/p&gt;

</description>
      <category>agile</category>
      <category>refinement</category>
      <category>scrum</category>
      <category>storypoints</category>
    </item>
    <item>
      <title>iTerm on steroids: Why I've Switched to Warp</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Wed, 25 Sep 2024 13:12:33 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/iterm-on-steroids-why-ive-switched-to-warp-jai</link>
      <guid>https://forem.com/freshcaffeine/iterm-on-steroids-why-ive-switched-to-warp-jai</guid>
      <description>&lt;p&gt;As a long-time iTerm user, I never thought I'd find a terminal that could tempt me away. But after discovering Warp, I’ve not only made the switch, but also enthusiastically deleted my old favorite, iTerm. Here’s why Warp has won me over, and why I think it’s worth considering for anyone who spends a lot of time in the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Advanced Search and Filter Tools: A Lifesaver for Docker Logs
&lt;/h2&gt;

&lt;p&gt;One of Warp's standout features is its powerful search and filter tools. These capabilities are especially handy when dealing with extensive and complex outputs like Docker logs. In the past, I often found myself sifting through lines and lines of data, trying to pinpoint specific information. Warp makes this process a breeze with its intuitive filtering options, allowing you to quickly narrow down logs by keywords or patterns. This feature alone has saved me countless hours and made troubleshooting much more efficient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwq8y8ec6ubc3vt8vr5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwq8y8ec6ubc3vt8vr5w.png" alt="Screenrecording of Search and Filter" width="600" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Warp Drive: The Notebook Feature for Coders
&lt;/h2&gt;

&lt;p&gt;Warp Drive is another innovation that has quickly become indispensable for some of my team. It acts as a notebook right within the terminal, where you can save commands, scripts, and any other useful snippets of code. This is particularly useful for tracking frequently used commands or documenting complex procedures, making them easily accessible whenever you need them. For someone learing commands for the first time, or like me who often revisits old commands and scripts - Warp Drive has been a game-changer.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://www.youtube.com/watch?si=s1fX5iDqmPiBoOk1&amp;amp;v=8UmreUTTrkg&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;
      youtube.com
    &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  3. Block Sharing: Perfect for Blog Posts like this
&lt;/h2&gt;

&lt;p&gt;A feature that stands out for content creators is Warp's Block Sharing. This allows you to easily share terminal outputs as individual blocks, which can be embedded into blog posts or shared with team members. It’s perfect for posts like this one, where I can demonstrate specific commands or outputs directly. No more clunky screenshots or lengthy copy-pasting; Warp lets you share clean, formatted blocks that are easy to read and follow.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://app.warp.dev/block/OAoH6561JnPYjda8ugOjGB" rel="noopener noreferrer"&gt;
      app.warp.dev
    &lt;/a&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  4. Streamlined Workflows
&lt;/h2&gt;

&lt;p&gt;Warp isn't just a terminal; it's a productivity enhancer. Its workflows feature allows you to automate and streamline repetitive tasks. Whether you're setting up a new development environment, deploying a project, or just running regular maintenance scripts, Warp's workflows can simplify these processes. The ability to bundle commands and scripts into reusable workflows not only saves time but also reduces the likelihood of errors, as you can standardise your processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Built-in AI: Your Intelligent Assistant
&lt;/h2&gt;

&lt;p&gt;Last but not least, Warp comes with built-in AI capabilities. This isn't just a gimmick; the AI can assist with command suggestions, syntax corrections, and even contextual information. For instance, if you're stuck trying to remember a complex command or its options, Warp's AI can provide suggestions based on the context of your work. This feature is incredibly helpful for both beginners and seasoned developers, enhancing productivity and reducing the learning curve for complex tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Cool Features in Warp
&lt;/h2&gt;

&lt;p&gt;In addition to the core features that made me switch, Warp is packed with other innovative tools that enhance the terminal experience. Here are a few more cool things you might want to explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.warp.dev/features/command-palette" rel="noopener noreferrer"&gt;Command Palette&lt;/a&gt;: Similar to what you'd find in modern code editors, Warp’s command palette allows you to quickly access commands, settings, and other functionality without leaving the terminal. It's a huge productivity boost for those who prefer keyboard-driven workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.warp.dev/features/command-completions/autosuggestions" rel="noopener noreferrer"&gt;Autosuggestions&lt;/a&gt;: Warp’s smart Autosuggestions offers suggestions as you type, making it easier to write commands quickly and accurately.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.warp.dev/features/entry/command-history" rel="noopener noreferrer"&gt;Command History&lt;/a&gt;: Warp's command history isn't just a simple list—it's fully searchable and filterable, allowing you to find and reuse previous commands with ease. You can also navigate through your history with a modern UI, making it easier to manage long command sequences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.warp.dev/appearance/themes" rel="noopener noreferrer"&gt;Theme Customization&lt;/a&gt;: Warp offers extensive theme customization options, allowing you to personalize the look and feel of your terminal. Whether you prefer a light theme for daylight hours or a dark mode for late-night sessions, Warp has you covered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.warp.dev/features/teams" rel="noopener noreferrer"&gt;Collaboration Features&lt;/a&gt;: If you work in a team, Warp’s collaboration features will be particularly appealing. You can &lt;a href="https://docs.warp.dev/features/session-sharing" rel="noopener noreferrer"&gt;share terminal sessions&lt;/a&gt; in real-time, making pair programming or collaborative debugging a seamless experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Switching from iTerm to Warp wasn't an easy decision, but it's one that has significantly improved my workflow. Warp's advanced features, like the powerful search and filter tools, Warp Drive, Block Sharing, streamlined workflows, and built-in AI, provide a modern, efficient, and user-friendly experience. If you're looking for a terminal that offers more than just a command line, Warp is definitely worth a try.&lt;/p&gt;

&lt;p&gt;If you haven't tried Warp yet, go and download it! &lt;a href="https://app.warp.dev/referral/846E4E" rel="noopener noreferrer"&gt;Use this referral link&lt;/a&gt;, and you'll get an exclusive theme (and help me earn some Warp swag). &lt;/p&gt;

</description>
      <category>warp</category>
      <category>iterm</category>
      <category>macos</category>
    </item>
    <item>
      <title>Why I don't include 404's when designing API's</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Wed, 25 Sep 2024 00:00:00 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/why-i-dont-include-404s-when-designing-apis-hli</link>
      <guid>https://forem.com/freshcaffeine/why-i-dont-include-404s-when-designing-apis-hli</guid>
      <description>&lt;p&gt;When designing APIs, one of the most common status codes you’ll come across is &lt;code&gt;404 Not Found&lt;/code&gt;. On the surface, it seems like the perfect way to tell clients that the resource they’re looking for doesn’t exist. But here’s the thing: I don’t use &lt;code&gt;404&lt;/code&gt; responses in my API designs. It might sound odd, but in my experience, relying on &lt;code&gt;404&lt;/code&gt; creates more confusion than clarity. Let me explain why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with 404 Not Found
&lt;/h2&gt;

&lt;p&gt;At its core, &lt;code&gt;404&lt;/code&gt; represents something that isn’t there. Whether it’s a webpage that no longer exists or a broken link, the &lt;code&gt;404&lt;/code&gt; is synonymous with "not found." But when it comes to APIs, &lt;code&gt;404&lt;/code&gt; can actually conflate two different situations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A typo or invalid URL&lt;/strong&gt;: If the API endpoint is incorrect, such as a typo in the URL, the server will return a &lt;code&gt;404&lt;/code&gt;, because it literally can't find the resource you're asking for. This makes sense, right? But it’s often unclear to the developer what exactly went wrong.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The resource doesn’t exist&lt;/strong&gt;: This is the case where a resource (like a user, product, or store) simply doesn’t exist in the database. You hit the right URL, but the server can’t find the resource because it’s not there.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s the problem: &lt;strong&gt;both cases return the same &lt;code&gt;404&lt;/code&gt; response&lt;/strong&gt;, which makes it difficult for the client to distinguish between an incorrect URL and a valid URL where the resource is missing. This ambiguity can lead to a lot of confusion and wasted time trying to debug issues, especially when it’s just a simple typo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Creates Friction for Clients
&lt;/h2&gt;

&lt;p&gt;When your API returns a &lt;code&gt;404&lt;/code&gt; for both invalid URLs and non-existent resources, clients have to dig deeper to understand what went wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was the URL incorrect?&lt;/li&gt;
&lt;li&gt;Is the endpoint broken?&lt;/li&gt;
&lt;li&gt;Does the resource just not exist?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the client doesn’t know which situation they’re dealing with, debugging becomes a guessing game. It’s especially frustrating when the problem is something simple, like a typo, but the &lt;code&gt;404&lt;/code&gt; gives no indication of what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Better Approach: Clear and Specific Responses
&lt;/h2&gt;

&lt;p&gt;Instead of lumping everything under &lt;code&gt;404&lt;/code&gt;, I prefer to offer more precise status codes and responses, depending on the situation. Here’s what I do instead:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Use 400 - Bad Request for Invalid URLs
&lt;/h3&gt;

&lt;p&gt;If there’s a typo in the URL or the endpoint itself doesn’t exist, I return a &lt;code&gt;400 Bad Request&lt;/code&gt;. This tells the client right away that something is wrong with the request they made—not the resource itself. You can also include a detailed message in the response body, making it clear why the request is invalid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;400 - Bad Request

{
  "error": "bad_request",
  "message": "The URL or endpoint you are trying to access is invalid."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is way more helpful than a generic &lt;code&gt;404&lt;/code&gt; because it gives the client a clear direction: “Check your URL, something’s off.”&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use 204 - No Content When Resources Are Missing
&lt;/h3&gt;

&lt;p&gt;For cases where the resource simply doesn’t exist (like a user or store isn’t found), I recommend using a &lt;code&gt;204 No Content&lt;/code&gt;. Why? Because this scenario isn’t necessarily an "error." The API processed the request successfully, but there’s no content to return. This fits perfectly with what &lt;code&gt;204&lt;/code&gt; is meant for: successful requests with no data to send back.&lt;/p&gt;

&lt;p&gt;For example, if a client searches for stores near a postcode and no stores are found, a &lt;code&gt;204&lt;/code&gt; response makes sense:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;204 - No Content

// No body (since `204` doesn’t allow it)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This response tells the client that the request was successful, but there’s simply nothing to show. It’s clean, efficient, and avoids the implication of something being broken.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use 200 OK with Clear Responses When It Makes Sense
&lt;/h3&gt;

&lt;p&gt;In some cases, I’ll return a &lt;code&gt;200 OK&lt;/code&gt; with an empty dataset or a clear message when no resources are found. This works well when the client might expect a body, even if it’s empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;200 - OK

{
  "status": "success",
  "message": "No stores found near the postcode 12345.",
  "data": []
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives the client more feedback while keeping things clear: the request was successful, there’s no error, and here’s an empty array to show the absence of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Avoid &lt;code&gt;404&lt;/code&gt; Altogether
&lt;/h2&gt;

&lt;p&gt;At the end of the day, the reason I don’t use &lt;code&gt;404 - Not Found&lt;/code&gt; in my API designs is simple: it causes confusion and conflates two very different scenarios. Instead, by using more specific status codes like &lt;code&gt;400 - Bad Request&lt;/code&gt;, &lt;code&gt;204 - No Content&lt;/code&gt;, and &lt;code&gt;200 - OK&lt;/code&gt; with empty results, I can give clients a clearer picture of what’s actually going on with their requests.&lt;/p&gt;

&lt;p&gt;This approach reduces debugging headaches, improves the client experience, and keeps the API behaviour more predictable.&lt;/p&gt;

</description>
      <category>api</category>
      <category>apidesign</category>
      <category>statuscodes</category>
      <category>404</category>
    </item>
    <item>
      <title>Blazor #2 - How to work with SASS in Blazor</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Mon, 02 Sep 2024 20:21:58 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/blazor-2-how-to-work-with-sass-in-blazor-ghh</link>
      <guid>https://forem.com/freshcaffeine/blazor-2-how-to-work-with-sass-in-blazor-ghh</guid>
      <description>&lt;p&gt;CSS isolation in Blazor was introduced as a way to encapsulate component styles, preventing them from leaking into other components or the global scope. While this feature has its advantages, it might not align with everyone’s development style, especially if you’re used to the flexibility and power of SASS.&lt;/p&gt;

&lt;p&gt;In this post, I’ll explain why I’m not a fan of CSS isolation in Blazor, and I’ll walk you through how to implement SASS using the &lt;code&gt;AspNetCore.SassCompiler&lt;/code&gt; NuGet package instead of relying on Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Don’t Like CSS Isolation in Blazor
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Reusability&lt;/strong&gt;: CSS isolation scopes styles to individual components, which is great for preventing style leaks, but it also limits the reusability of styles across different components. This often leads to duplication or the need to create global styles anyway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased Complexity&lt;/strong&gt;: For complex projects, especially those with themes or shared styles, CSS isolation can introduce unnecessary complexity. Managing both isolated and global styles can be confusing and error-prone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Native Support for SASS&lt;/strong&gt;: CSS isolation does not natively support SASS, making it difficult to use features like variables, nesting, and mixins that are essential for maintaining clean and scalable styles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging Challenges&lt;/strong&gt;: Isolated styles can make debugging more difficult, especially in large projects where tracking down the source of a particular style issue can be time-consuming.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Styles Still Necessary&lt;/strong&gt;: Even with isolation, you’ll often need global styles for things like layout, typography, and theming, leading to a hybrid approach that can be harder to manage.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Implement SASS in Blazor Using AspNetCore.SassCompiler
&lt;/h2&gt;

&lt;p&gt;To bypass the limitations of CSS isolation and utilize SASS in your Blazor project, you can use the &lt;a href="https://www.nuget.org/packages/AspNetCore.SassCompiler/" rel="noopener noreferrer"&gt;&lt;code&gt;AspNetCore.SassCompiler&lt;/code&gt; NuGet package&lt;/a&gt;. Here’s how:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install the &lt;code&gt;AspNetCore.SassCompiler&lt;/code&gt; NuGet Package
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open your Blazor project in Visual Studio or your preferred IDE.&lt;/li&gt;
&lt;li&gt;Install the &lt;code&gt;AspNetCore.SassCompiler&lt;/code&gt; package via the NuGet Package Manager or by running the following command in the Package Manager Console:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  dotnet add package AspNetCore.SassCompiler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This package automatically compiles your Sass styles from the Source (defaults to: &lt;code&gt;Styles&lt;/code&gt;) will automatically be compiled into .css files in the TargetFolder (defaults to: &lt;code&gt;wwwroot\css&lt;/code&gt;) on build. You can also adjust the default configuration in the &lt;code&gt;appsettings.json&lt;/code&gt; or &lt;code&gt;sasscompiler.json&lt;/code&gt;, &lt;a href="https://www.nuget.org/packages/AspNetCore.SassCompiler/" rel="noopener noreferrer"&gt;you can read more about this in the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Set Up Your SASS File Structure
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;Styles&lt;/code&gt; folder in your Blazor project. Inside this folder, create a &lt;code&gt;main.scss&lt;/code&gt; file. This will serve as your main SASS file where you can import other partials.&lt;/p&gt;

&lt;p&gt;Example file structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;BlazorApp/
└── Styles/
    ├── _component.scss
    ├── _mixins.scss
    ├── _variables.scss
    └── main.scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rebuild/serve the project and a &lt;code&gt;css&lt;/code&gt; directory will appear under &lt;code&gt;wwwroot&lt;/code&gt; with a main.css and a main.css.map file. As these files are generated with every build, you'll want to add them into your projects &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p56g9vsea8k5suny3na.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p56g9vsea8k5suny3na.png" alt="Screenshot of generated file in folder tree" width="708" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Enable the Sass Watcher
&lt;/h3&gt;

&lt;p&gt;If you want the css to be rebuilt automagically, add this to the Programme.cs and the Sass watcher will be enabled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Add the Sass Watcher  &lt;/span&gt;
&lt;span class="cp"&gt;#if DEBUG
&lt;/span&gt;    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSassCompiler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding the &lt;code&gt;#if DEBUG&lt;/code&gt; statement to ensures the watcher is only used during debug mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Include the Compiled CSS in Your Blazor Project
&lt;/h3&gt;

&lt;p&gt;Reference the compiled CSS file in your App.razor file with the below snippet.&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;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"css/styles.css"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove the other stylesheet references, as we don't need them any more.&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"app.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"[ProjectName].styles.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: For the purposes of this tutorial I'm keeping the bootstrap styles, in a production project this would be removed too and replaced with this week favourite SASS framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Migrate the Blazor styles to SASS
&lt;/h3&gt;

&lt;p&gt;If you run the project now, you should see something that looks a lot like the following image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cafkisef0hu0hu4392c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cafkisef0hu0hu4392c.png" alt="Screenshot of a site with missing styles" width="800" height="663"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to migrate the styles we've removed and migrate them over to SASS. At the same time we can now take advantage of SASS features like variables, mixins, nesting, and inheritance to keep your styles DRY (Don't Repeat Yourself) and maintainable.&lt;/p&gt;

&lt;p&gt;Typically, I would do this in the following order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy the contents of the app.css files in a _blazor.scss under components directory. Reference the new file in _component.scss.&lt;/li&gt;
&lt;li&gt;Copy the contents of any isolated CSS files (ComponentName.razor.css) into their own scss files, try to follow the existing directory structure. Again referencing the new files in _component.scss&lt;/li&gt;
&lt;li&gt;Go through the colours and create them as variables in _variables.scss. Its quite fun seeing the mixed uses of colour types used in the blazor sample, i converted them all to hex as I went along.&lt;/li&gt;
&lt;li&gt;Do the same with any widths used in media-queries, or fonts.&lt;/li&gt;
&lt;li&gt;Test and refactoring; Do all my styles look right? Can I nest some styles for better structure? &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With a little work, my folder structure looked a little like this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;BlazorApp/
└── Styles/
    ├── Components/
    │   ├── Layout/
    │   │   ├── _mainLayout.scss
    │   │   └── _navManu.scss
    │   └── _blazor.scss
    ├── _component.scss
    ├── _mixins.scss
    ├── _variables.scss
    └── main.scss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, the site should look exactly like it did previously, but now you can go wild and add SASS to all your new features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftho1at8f2vvw5uw01tc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftho1at8f2vvw5uw01tc3.png" alt="Screenshot of the site, after converting to SASS" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;CSS isolation in Blazor has its benefits, particularly for small projects or simple component-based styling. However, for more complex applications, especially those that require advanced styling techniques and reusability, implementing SASS using the AspNetCore.SassCompiler package offers a fantastic alternative. This approach streamlines your styling process, allows you to use modern CSS features, and integrates smoothly with your Blazor project without needing to rely on external tools like Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample code
&lt;/h2&gt;

&lt;p&gt;I've uploaded the code related to this post to a &lt;a href="https://github.com/fresh-caffeine/BlazorDemo/tree/blog-post/add-sass-to-your-blazor" rel="noopener noreferrer"&gt;branch in my Blazor Demo repo in GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>dotnet</category>
      <category>blazor</category>
    </item>
    <item>
      <title>Blazor #1 - What is this Blazor thing all about?</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Fri, 30 Aug 2024 20:21:58 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/blazor-1-what-is-this-blazor-thing-all-about-1l99</link>
      <guid>https://forem.com/freshcaffeine/blazor-1-what-is-this-blazor-thing-all-about-1l99</guid>
      <description>&lt;p&gt;Earlier this year, I was lucky enough to work on a couple of small Blazor based projects. I promised some of my colleagues at Kainos that I would share some of my learnings - I'm sorry its taken so long, but here is my first in what I hope will become a beautiful little series of posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Blazor?
&lt;/h2&gt;

&lt;p&gt;Blazor is a frontend framework from Microsoft that you can use to build interactive client-side Web UIs with C# instead of JavaScript. It supports both server-side rendering and client interactivity in a single programming model. &lt;/p&gt;

&lt;p&gt;Blazor comes in 2 main hosting models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blazor Server&lt;/li&gt;
&lt;li&gt;Blazor WebAssembly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blazor Hybrid is also an option, where it can be used to build native client apps using a hybrid approach. Hybrid apps are native apps that leverage web technologies for their functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Blazor?
&lt;/h2&gt;

&lt;p&gt;Using .NET for client-side web development offers some interesting advantages to .Net developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C# developers write in a language already familiar to them, which can improve productivity in app development and maintenance.&lt;/li&gt;
&lt;li&gt;Projects can leverage the well established .NET ecosystem of .NET libraries.&lt;/li&gt;
&lt;li&gt;Projects benefit from .NET's performance, reliability, and security.&lt;/li&gt;
&lt;li&gt;Development can develop on any environment of their choosingL macOS, Linux, or Windows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is the difference between Blazor Server and Blazor WebAssembly?
&lt;/h2&gt;

&lt;p&gt;Blazor Server and Blazor WebAssembly are both options for building client-side applications in C#. They differ in a few key ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blazor Server:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs on the server in ASP.NET Core&lt;/li&gt;
&lt;li&gt;UI interactions are handled over a SignalR connection&lt;/li&gt;
&lt;li&gt;UI is rendered on the server in a headless browser&lt;/li&gt;
&lt;li&gt;Code is executed on the server&lt;/li&gt;
&lt;li&gt;Requires a connection to the server&lt;/li&gt;
&lt;li&gt;Works with any browser that supports SignalR&lt;/li&gt;
&lt;li&gt;Supports scenarios where the app needs to access existing web apps or web APIs running on the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Blazor WebAssembly:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs in the browser on a WebAssembly-based .NET runtime (Mono)&lt;/li&gt;
&lt;li&gt;UI interactions are handled directly in the browser&lt;/li&gt;
&lt;li&gt;UI is rendered directly in the browser&lt;/li&gt;
&lt;li&gt;Code is executed in the browser&lt;/li&gt;
&lt;li&gt;Works with all modern browsers&lt;/li&gt;
&lt;li&gt;Supports scenarios where the app needs to be a fully client-side experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generally speaking, Blazor Server apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have lower bandwidth usage&lt;/li&gt;
&lt;li&gt;Have lower latency&lt;/li&gt;
&lt;li&gt;Have faster UI updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meanwhile, Blazor WebAssembly apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have smaller download sizes&lt;/li&gt;
&lt;li&gt;Have faster startup times&lt;/li&gt;
&lt;li&gt;Can run in the browser without a connection to the server&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting started with Blazor
&lt;/h2&gt;

&lt;p&gt;There are plenty of resources out there to get started with Blazor. I would recommend the following as a great starting point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dotnet.microsoft.com/en-us/learn/aspnet/blazor-tutorial/intro" rel="noopener noreferrer"&gt;Microsoft Blazor tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blazor-university.com/" rel="noopener noreferrer"&gt;Blazor University&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is next?
&lt;/h2&gt;

&lt;p&gt;I am going to start a series of posts to share my learnings. I will be covering the following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/blog/2024/blazor-2-working-with-sass/"&gt;Working with Sass in a Blazor project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Creating custom form components&lt;/li&gt;
&lt;li&gt;Creating nested components&lt;/li&gt;
&lt;li&gt;Better form validation with FluentValidation&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Simple Mocks With Mockaco</title>
      <dc:creator>Andy Robinson</dc:creator>
      <pubDate>Mon, 03 Apr 2023 22:16:15 +0000</pubDate>
      <link>https://forem.com/freshcaffeine/simple-mocks-with-mockaco-ik3</link>
      <guid>https://forem.com/freshcaffeine/simple-mocks-with-mockaco-ik3</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/natenho/Mockaco" rel="noopener noreferrer"&gt;Mockaco&lt;/a&gt; is a simple yet powerful mocking framework for .NET that allows you to easily create and configure mock objects for your tests. It's designed to be lightweight and easy to use, with a simple syntax that makes it a breeze to set up your tests.&lt;/p&gt;

&lt;p&gt;One of the things that sets Mockaco apart is its flexibility. It allows you to create mocks for any class or interface, and you can customise the behaviour of those mocks using a variety of methods. For example, you can set up a mock to return a specific value when a certain method is called, or you can throw an exception to simulate an error condition.&lt;/p&gt;

&lt;p&gt;But Mockaco isn't just about making it easy to create mock objects. It also includes a variety of features to make your tests more powerful and flexible. For example, you can use Mockaco to verify that a specific method was called on a mock object, or to verify that a mock object was used in a specific way.&lt;/p&gt;

&lt;p&gt;In one of my teams projects, we're using a Mockaco in a Docker container to mock an external API so we can run some &lt;a href="https://en.wikipedia.org/wiki/Integration_testing" rel="noopener noreferrer"&gt;integration tests&lt;/a&gt; in the ADO build pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me some code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  docker-compose.yaml
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.4"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mockaco.fresh-caffeine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;natenho/mockaco&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;5000:5000'&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./mockaco/mocks:/app/Mocks'&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This Docker Compose file uses the &lt;code&gt;natenho/mockaco&lt;/code&gt; image to create a container.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ports&lt;/code&gt; section maps the container's port 5000 to the host's port 5000. This allows you to access the Mockaco web interface from your host machine.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;networks&lt;/code&gt; section specifies that the container should be attached to the default Docker network.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;volumes&lt;/code&gt; section mounts the &lt;code&gt;./mockaco/mocks&lt;/code&gt; directory on the host to the &lt;code&gt;/app/Mocks&lt;/code&gt; directory inside the container. This allows you to store your mock object files on the host machine and access them from within the container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  And now for some simple mocks
&lt;/h3&gt;

&lt;p&gt;This is a mock for a messaging api &lt;code&gt;/v1/api/users/{loginId}/messages&lt;/code&gt;, where &lt;code&gt;{loginId}&lt;/code&gt; can be any string. &lt;/p&gt;

&lt;h4&gt;
  
  
  Happy path mock
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/v1/api/users/{loginId}/messages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;#= 
      !String.IsNullOrEmpty(Request.Header["&lt;/span&gt;&lt;span class="err"&gt;x-api-key&lt;/span&gt;&lt;span class="s2"&gt;"]?.ToString()) &amp;amp;&amp;amp;
      !String.IsNullOrEmpty(Request.Body["&lt;/span&gt;&lt;span class="err"&gt;sender&lt;/span&gt;&lt;span class="s2"&gt;"]?.ToString()) &amp;amp;&amp;amp;
      !String.IsNullOrEmpty(Request.Body["&lt;/span&gt;&lt;span class="err"&gt;body&lt;/span&gt;&lt;span class="s2"&gt;"]?.ToString()) 
    #&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
      &lt;/span&gt;&lt;span class="nl"&gt;"messageId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;#= Faker.Random.Guid() #&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our happy path mock, we have three conditions set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We require the request header to have an &lt;code&gt;x-api-key&lt;/code&gt; and for it to be populated &lt;/li&gt;
&lt;li&gt;We require the request body to include &lt;code&gt;sender&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt; and for them to be populated
In return, we get a 201 (Created) response with a body containing a randomly generated &lt;code&gt;messageId&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Unauthorized path mock
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/v1/api/users/{loginId}/messages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;#= 
      String.IsNullOrEmpty(Request.Header["&lt;/span&gt;&lt;span class="err"&gt;x-api-key&lt;/span&gt;&lt;span class="s2"&gt;"]?.ToString())
    #&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unauthorized"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the unauthorized mock, we catch requests where the header is missing a value for the &lt;code&gt;x-api-key&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
In return, we get a 401 (Unauthorized) response&lt;/p&gt;

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

&lt;p&gt;As you can see, the setup is pretty simple. So if you're tired of manually creating and setting up mock objects for your .NET projects, give Mockaco a try! It's simple, flexible, and powerful, and it can help you write better tests in less time.&lt;/p&gt;

&lt;p&gt;Go ready more about &lt;a href="https://github.com/natenho/Mockaco" rel="noopener noreferrer"&gt;Mockaco on the GitHub repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>mockaco</category>
      <category>mocks</category>
      <category>integrationtesting</category>
    </item>
  </channel>
</rss>
