<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kudasov Dmitriy</title>
    <description>The latest articles on DEV Community by Kudasov Dmitriy (@rusedev).</description>
    <link>https://dev.to/rusedev</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%2F3840760%2Ff9814ecc-f748-4ace-a491-2afb3592dcfe.jpeg</url>
      <title>DEV Community: Kudasov Dmitriy</title>
      <link>https://dev.to/rusedev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rusedev"/>
    <language>en</language>
    <item>
      <title>Why URL-Only API Mocks Break Down in Real Frontend Work</title>
      <dc:creator>Kudasov Dmitriy</dc:creator>
      <pubDate>Tue, 02 Jun 2026 19:43:34 +0000</pubDate>
      <link>https://dev.to/rusedev/why-url-only-api-mocks-break-down-in-real-frontend-work-595m</link>
      <guid>https://dev.to/rusedev/why-url-only-api-mocks-break-down-in-real-frontend-work-595m</guid>
      <description>&lt;p&gt;Frontend mocks often start with a URL.&lt;/p&gt;

&lt;p&gt;That makes sense.&lt;/p&gt;

&lt;p&gt;You see a request like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/orders
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you create a mock for &lt;code&gt;/api/orders&lt;/code&gt;, return a response, reload the page, and check the UI.&lt;/p&gt;

&lt;p&gt;For simple cases, that works well.&lt;/p&gt;

&lt;p&gt;But real frontend work gets messy quickly, because the URL is often not the full state.&lt;/p&gt;

&lt;h2&gt;
  
  
  One endpoint can mean many states
&lt;/h2&gt;

&lt;p&gt;A single endpoint can represent many different product situations.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /api/orders?status=failed&amp;amp;page=1
GET /api/orders?status=paid&amp;amp;page=1
GET /api/orders?status=pending&amp;amp;page=3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of these may hit the same path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;/api/orders
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the UI states can be completely different.&lt;/p&gt;

&lt;p&gt;One response may show a full list.&lt;br&gt;
One may show an empty state.&lt;br&gt;
One may show a warning.&lt;br&gt;
One may trigger a pagination bug.&lt;br&gt;
One may expose a permissions issue.&lt;/p&gt;

&lt;p&gt;The endpoint path is the same, but the frontend state is not.&lt;/p&gt;

&lt;p&gt;That is where URL-only mocks start to feel too thin.&lt;/p&gt;
&lt;h2&gt;
  
  
  Request bodies make this even harder
&lt;/h2&gt;

&lt;p&gt;The problem becomes more visible with &lt;code&gt;POST&lt;/code&gt; requests.&lt;/p&gt;

&lt;p&gt;A lot of modern APIs reuse one endpoint and put the important state inside the request body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /api/integration/list
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"documentType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accountId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"includeArchived"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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;Change one field and the response may represent a different UI state.&lt;/p&gt;

&lt;p&gt;Maybe &lt;code&gt;documentType&lt;/code&gt; changes the schema.&lt;br&gt;
Maybe &lt;code&gt;accountId&lt;/code&gt; changes permissions.&lt;br&gt;
Maybe &lt;code&gt;includeArchived&lt;/code&gt; changes whether the list is empty.&lt;br&gt;
Maybe &lt;code&gt;page&lt;/code&gt; exposes a pagination edge case.&lt;/p&gt;

&lt;p&gt;If a mock only matches the URL, it cannot distinguish these states.&lt;/p&gt;

&lt;p&gt;It can say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mock &lt;code&gt;/api/integration/list&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But it cannot say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mock &lt;code&gt;/api/integration/list&lt;/code&gt; only when &lt;code&gt;documentType&lt;/code&gt; is &lt;code&gt;invoice&lt;/code&gt; and &lt;code&gt;accountId&lt;/code&gt; is &lt;code&gt;acme&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That difference matters when you are trying to test a specific frontend behavior.&lt;/p&gt;
&lt;h2&gt;
  
  
  Staging data does not always help
&lt;/h2&gt;

&lt;p&gt;One common answer is: "Use staging."&lt;/p&gt;

&lt;p&gt;Staging is useful. It catches integration problems and gives teams a shared environment.&lt;/p&gt;

&lt;p&gt;But staging is not always good at giving you the exact state you need at the exact time you need it.&lt;/p&gt;

&lt;p&gt;Maybe staging has data, but you need an empty list.&lt;/p&gt;

&lt;p&gt;Maybe the backend is healthy, but you need to test a &lt;code&gt;500&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Maybe the response is fast, but you need to inspect a loading state.&lt;/p&gt;

&lt;p&gt;Maybe you need a specific permission failure, but nobody wants to mutate a test account for one UI check.&lt;/p&gt;

&lt;p&gt;Maybe a QA edge case disappears because someone else changed shared test data.&lt;/p&gt;

&lt;p&gt;None of this means staging is bad.&lt;/p&gt;

&lt;p&gt;It means staging is not always the fastest tool for small frontend state work.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mock servers are powerful, but sometimes heavy
&lt;/h2&gt;

&lt;p&gt;Mock servers are also useful.&lt;/p&gt;

&lt;p&gt;Tools like MSW, Mockoon, WireMock, Postman mocks, Playwright route interception, and Cypress intercepts all have valid places in the stack.&lt;/p&gt;

&lt;p&gt;They are especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repeatable test suites&lt;/li&gt;
&lt;li&gt;shared API contracts&lt;/li&gt;
&lt;li&gt;backend-independent development&lt;/li&gt;
&lt;li&gt;team-wide fake environments&lt;/li&gt;
&lt;li&gt;CI workflows&lt;/li&gt;
&lt;li&gt;larger mocking strategies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But sometimes the task is smaller.&lt;/p&gt;

&lt;p&gt;You are not trying to design an entire fake backend.&lt;/p&gt;

&lt;p&gt;You are staring at one screen and thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I need this one browser request to return this one response so I can see this one UI state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For that kind of work, a full mock-server setup can be more structure than the problem needs.&lt;/p&gt;
&lt;h2&gt;
  
  
  The useful mock starts from the real request
&lt;/h2&gt;

&lt;p&gt;This is the product direction behind Ruse.&lt;/p&gt;

&lt;p&gt;Ruse is a Chrome extension for local-first API mocking inside the browser.&lt;/p&gt;

&lt;p&gt;The current public version, Ruse v0.2.0, is already live in the Chrome Web Store.&lt;/p&gt;

&lt;p&gt;Today, the workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the app you are testing.&lt;/li&gt;
&lt;li&gt;Open Ruse on the working tab.&lt;/li&gt;
&lt;li&gt;Capture a real browser request.&lt;/li&gt;
&lt;li&gt;Create a local mock rule.&lt;/li&gt;
&lt;li&gt;Organize rules into local collections.&lt;/li&gt;
&lt;li&gt;Reload the UI and inspect the state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No account is required for the current local workflow.&lt;/p&gt;

&lt;p&gt;The next quality pass, v0.3.0, is focused on making HTTP rule creation more request-aware.&lt;/p&gt;

&lt;p&gt;The goal is not to build a huge platform immediately.&lt;/p&gt;

&lt;p&gt;The goal is to make the core browser loop stronger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;capture request -&amp;gt; inspect request -&amp;gt; edit response -&amp;gt; save local mock -&amp;gt; reload UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Matching the state, not only the path
&lt;/h2&gt;

&lt;p&gt;A better local mock should understand more than the endpoint path.&lt;/p&gt;

&lt;p&gt;For many frontend cases, you want to start from the request that actually happened in the browser and decide which parts should matter.&lt;/p&gt;

&lt;p&gt;For example, if the captured request body is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"documentType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accountId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"includeArchived"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clientRequestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"temporary-random-value"&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;You may want the mock to care about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"documentType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accountId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme"&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;But not care about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clientRequestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"temporary-random-value"&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;That is the difference between mocking an endpoint and mocking a state.&lt;/p&gt;

&lt;p&gt;The request fields that define the UI state should matter.&lt;/p&gt;

&lt;p&gt;The noisy fields should not.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is not about replacing every testing tool
&lt;/h2&gt;

&lt;p&gt;I do not think browser-level local mocks replace proper tests.&lt;/p&gt;

&lt;p&gt;They do not replace contract testing.&lt;/p&gt;

&lt;p&gt;They do not replace backend integration testing.&lt;/p&gt;

&lt;p&gt;They do not replace staging.&lt;/p&gt;

&lt;p&gt;They do not replace a serious mock-server setup when a team needs one.&lt;/p&gt;

&lt;p&gt;The value is narrower:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When you need to reproduce one frontend API state quickly, inside Chrome, starting from real browser traffic, local browser-level mocking can be the fastest path.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the lane Ruse is being built for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical examples
&lt;/h2&gt;

&lt;p&gt;Here are the kinds of states where URL-only mocks can be too limited:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same endpoint, different filters&lt;/li&gt;
&lt;li&gt;Same endpoint, different account&lt;/li&gt;
&lt;li&gt;Same endpoint, different user role&lt;/li&gt;
&lt;li&gt;Same endpoint, different document type&lt;/li&gt;
&lt;li&gt;Same endpoint, different request body&lt;/li&gt;
&lt;li&gt;Same endpoint, different pagination state&lt;/li&gt;
&lt;li&gt;Same endpoint, different feature flag&lt;/li&gt;
&lt;li&gt;Same endpoint, different permission result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frontend does not care that the path is the same.&lt;/p&gt;

&lt;p&gt;The frontend cares what state the response represents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Ruse is going next
&lt;/h2&gt;

&lt;p&gt;Ruse v0.2.0 is live now.&lt;/p&gt;

&lt;p&gt;The next development focus is v0.3.0, which is planned as a quality pass around HTTP rule creation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Builder-first selected request workflow&lt;/li&gt;
&lt;li&gt;request parameter/body subset matching&lt;/li&gt;
&lt;li&gt;cleaner response body editing&lt;/li&gt;
&lt;li&gt;response status/type/delay controls&lt;/li&gt;
&lt;li&gt;response header cleanup&lt;/li&gt;
&lt;li&gt;clearer mocked logs&lt;/li&gt;
&lt;li&gt;a tighter working-tab permission model, once final QA confirms it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am deliberately keeping this scoped.&lt;/p&gt;

&lt;p&gt;No accounts in v0.3.0.&lt;/p&gt;

&lt;p&gt;No billing.&lt;/p&gt;

&lt;p&gt;No teams.&lt;/p&gt;

&lt;p&gt;No cloud sync.&lt;/p&gt;

&lt;p&gt;No dedicated GraphQL or WebSocket editor yet.&lt;/p&gt;

&lt;p&gt;The point is to make the core HTTP workflow feel right before expanding the product surface area.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try the current workflow
&lt;/h2&gt;

&lt;p&gt;If you build frontend against APIs that are hard to control on demand, try Ruse v0.2.0 on one real screen.&lt;/p&gt;

&lt;p&gt;Pick one API state that usually slows you down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;empty list&lt;/li&gt;
&lt;li&gt;&lt;code&gt;500&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;slow response&lt;/li&gt;
&lt;li&gt;malformed JSON&lt;/li&gt;
&lt;li&gt;permission denied&lt;/li&gt;
&lt;li&gt;filtered result&lt;/li&gt;
&lt;li&gt;pagination edge case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then see whether controlling that state locally in Chrome helps your UI loop move faster.&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://ruse.dev" rel="noopener noreferrer"&gt;https://ruse.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chrome Web Store: &lt;a href="https://chromewebstore.google.com/detail/becjmbgcgfddoahaoigeeogohpbcmgic?utm_source=item-share-cb" rel="noopener noreferrer"&gt;https://chromewebstore.google.com/detail/becjmbgcgfddoahaoigeeogohpbcmgic?utm_source=item-share-cb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>testing</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Test Frontend Error States Without Breaking Your Backend</title>
      <dc:creator>Kudasov Dmitriy</dc:creator>
      <pubDate>Fri, 29 May 2026 13:30:00 +0000</pubDate>
      <link>https://dev.to/rusedev/how-to-test-frontend-error-states-without-breaking-your-backend-bpi</link>
      <guid>https://dev.to/rusedev/how-to-test-frontend-error-states-without-breaking-your-backend-bpi</guid>
      <description>&lt;p&gt;Frontend teams are usually pretty good at testing the happy path.&lt;/p&gt;

&lt;p&gt;The API returns &lt;code&gt;200&lt;/code&gt;. The response shape is correct. The list has data. The network is fast enough. The user sees the page we designed.&lt;/p&gt;

&lt;p&gt;Great.&lt;/p&gt;

&lt;p&gt;But products do not live only in the happy path.&lt;/p&gt;

&lt;p&gt;They live in all the awkward states around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the endpoint returns &lt;code&gt;500&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the list is empty&lt;/li&gt;
&lt;li&gt;the request is slow&lt;/li&gt;
&lt;li&gt;the response is malformed&lt;/li&gt;
&lt;li&gt;the token expired&lt;/li&gt;
&lt;li&gt;the user has no permissions&lt;/li&gt;
&lt;li&gt;staging data changed again&lt;/li&gt;
&lt;li&gt;the backend endpoint is not ready yet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These states are often where the UI becomes the most important. They are also the states that are hardest to reproduce on demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with relying on staging
&lt;/h2&gt;

&lt;p&gt;A lot of teams treat staging as the place where frontend edge cases should be tested.&lt;/p&gt;

&lt;p&gt;In theory, that makes sense.&lt;/p&gt;

&lt;p&gt;In practice, staging is rarely in the exact state you need.&lt;/p&gt;

&lt;p&gt;Maybe you need an empty list, but staging has 400 items.&lt;/p&gt;

&lt;p&gt;Maybe you need the API to return a &lt;code&gt;500&lt;/code&gt;, but the backend is currently healthy.&lt;/p&gt;

&lt;p&gt;Maybe you need a slow response to test loading behavior, but the request is too fast.&lt;/p&gt;

&lt;p&gt;Maybe you need a specific permission error, but nobody wants to mutate test data or add a temporary backend flag just so you can check one UI state.&lt;/p&gt;

&lt;p&gt;So the frontend workaround begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common workarounds
&lt;/h2&gt;

&lt;p&gt;There are a few common ways to deal with this.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Mock servers
&lt;/h3&gt;

&lt;p&gt;Mock servers are powerful. They are great when you need shared contracts, stable fake environments, or a full backend replacement during development.&lt;/p&gt;

&lt;p&gt;But they can also be heavy when the task is small.&lt;/p&gt;

&lt;p&gt;Sometimes you do not need a full mock environment. You just need this one request to return an empty array for ten minutes while you fix a UI.&lt;/p&gt;

&lt;p&gt;Setting up a mock server for that can feel like too much ceremony.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Local fixtures
&lt;/h3&gt;

&lt;p&gt;Local fixtures are fast and simple.&lt;/p&gt;

&lt;p&gt;You create a JSON file, import it somewhere, and render the UI against that data.&lt;/p&gt;

&lt;p&gt;This works well for isolated components. But it gets harder when the behavior depends on the actual network flow of the app: auth, routing, loading states, retries, request timing, headers, or runtime conditions.&lt;/p&gt;

&lt;p&gt;Fixtures can also drift from real API responses over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Backend flags or test endpoints
&lt;/h3&gt;

&lt;p&gt;Sometimes the backend team can add a flag, seed special data, or expose a test endpoint.&lt;/p&gt;

&lt;p&gt;That can be useful, especially in mature teams.&lt;/p&gt;

&lt;p&gt;But it also creates coordination overhead. The frontend developer has to ask for the state, wait for it, and hope it still exists when QA or design tries to reproduce the same thing later.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Browser hacks
&lt;/h3&gt;

&lt;p&gt;We have all done some version of this.&lt;/p&gt;

&lt;p&gt;Add a temporary &lt;code&gt;throw&lt;/code&gt;. Edit code in DevTools. Comment out a fetch call. Hardcode a response. Change a local branch just to force an error state.&lt;/p&gt;

&lt;p&gt;It works, but it is fragile. It is also easy to forget, hard to share, and not something you want to rely on for repeatable testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  A lighter workflow: override the response locally
&lt;/h2&gt;

&lt;p&gt;For many frontend tasks, the ideal workflow is smaller:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the app.&lt;/li&gt;
&lt;li&gt;See the real request the app is making.&lt;/li&gt;
&lt;li&gt;Choose the request you want to control.&lt;/li&gt;
&lt;li&gt;Return the response you need.&lt;/li&gt;
&lt;li&gt;Reload and test the UI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No backend change. No proxy setup. No full mock server. No app code changes.&lt;/p&gt;

&lt;p&gt;Just one local override for one real browser request.&lt;/p&gt;

&lt;p&gt;That is the workflow I have been thinking about while building Ruse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example states worth testing
&lt;/h2&gt;

&lt;p&gt;Here are a few states I think every production UI should be easy to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Empty list
&lt;/h3&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;"items"&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;Does the UI show a thoughtful empty state? Is the CTA correct? Does the layout collapse awkwardly? Does pagination disappear?&lt;/p&gt;

&lt;h3&gt;
  
  
  Server error
&lt;/h3&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;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Internal server error"&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;Does the page recover? Can the user retry? Is the message useful? Does the app accidentally show a blank screen?&lt;/p&gt;

&lt;h3&gt;
  
  
  Slow response
&lt;/h3&gt;

&lt;p&gt;A slow API often reveals problems that fast local development hides.&lt;/p&gt;

&lt;p&gt;Do loading indicators appear? Do buttons stay disabled? Does the page jump when data arrives? Can the user trigger duplicate actions?&lt;/p&gt;

&lt;h3&gt;
  
  
  Malformed response
&lt;/h3&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;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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;This is where defensive UI code gets tested.&lt;/p&gt;

&lt;p&gt;Does the app fail gracefully, or does one unexpected value take down the entire screen?&lt;/p&gt;

&lt;h3&gt;
  
  
  Permission error
&lt;/h3&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;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You do not have access to this resource"&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;Permission states are product states too. They need design, copy, and behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why browser-level mocking is useful
&lt;/h2&gt;

&lt;p&gt;Mocking at the browser level is interesting because it starts from what your app is actually doing.&lt;/p&gt;

&lt;p&gt;You are not inventing a request from memory. You are not manually recreating the URL, method, and response shape from scratch. You are looking at real traffic and deciding: "for this request, return this instead."&lt;/p&gt;

&lt;p&gt;That makes the loop feel more natural for frontend work.&lt;/p&gt;

&lt;p&gt;It is especially useful when you are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building UI before the backend is complete&lt;/li&gt;
&lt;li&gt;testing error states&lt;/li&gt;
&lt;li&gt;preparing stable demos&lt;/li&gt;
&lt;li&gt;reproducing QA bugs&lt;/li&gt;
&lt;li&gt;checking loading behavior&lt;/li&gt;
&lt;li&gt;designing empty states&lt;/li&gt;
&lt;li&gt;working against flaky staging data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Ruse fits
&lt;/h2&gt;

&lt;p&gt;I am building Ruse as a Chrome extension for this workflow.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inspect browser requests&lt;/li&gt;
&lt;li&gt;create local mock rules&lt;/li&gt;
&lt;li&gt;return custom responses&lt;/li&gt;
&lt;li&gt;test the UI state you need&lt;/li&gt;
&lt;li&gt;keep everything local in the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ruse is intentionally small and local-first. It is not trying to be a full API platform. It is focused on making the first useful mock fast.&lt;/p&gt;

&lt;p&gt;Ruse v0.2.0 is now published in the Chrome Web Store, with a cleaner working-tab flow and local collections for organizing mock rules.&lt;/p&gt;

&lt;p&gt;If this workflow sounds useful, install Ruse and send feedback from a real frontend workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruse.dev" rel="noopener noreferrer"&gt;https://ruse.dev&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Frontend edge cases should not require a backend meeting.&lt;/p&gt;

&lt;p&gt;Sometimes you need a full mock server. Sometimes you need contract testing. Sometimes you need proper seeded environments.&lt;/p&gt;

&lt;p&gt;But sometimes you just need one request to return one different response so you can finish the UI in front of you.&lt;/p&gt;

&lt;p&gt;That small loop is worth making better.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>testing</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Ruse v0.2.0 Is Live: Local Collections and a Cleaner Working-Tab Flow</title>
      <dc:creator>Kudasov Dmitriy</dc:creator>
      <pubDate>Wed, 27 May 2026 13:30:00 +0000</pubDate>
      <link>https://dev.to/rusedev/ruse-v020-is-live-local-collections-and-a-cleaner-working-tab-flow-4hj9</link>
      <guid>https://dev.to/rusedev/ruse-v020-is-live-local-collections-and-a-cleaner-working-tab-flow-4hj9</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Ruse v0.2.0 is live in the Chrome Web Store.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is not a huge platform release, and that is intentional. The goal of this version is simple: make the first real browser API mocking workflow feel less clumsy.&lt;/p&gt;

&lt;p&gt;When you are building frontend UI, the problem is often not that you need an entire fake backend. Sometimes the problem is much smaller:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the API returns a happy path, but you need an error state&lt;/li&gt;
&lt;li&gt;staging has data, but you need an empty state&lt;/li&gt;
&lt;li&gt;the backend is healthy, but you need to test a 500&lt;/li&gt;
&lt;li&gt;the request is fast, but you need to inspect a loading state&lt;/li&gt;
&lt;li&gt;the endpoint exists, but the exact QA state keeps disappearing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ruse is being built for that kind of moment: one real browser request, one local mock rule, one UI state you need to control.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in v0.2.0
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Ruse now starts from your working tab&lt;/strong&gt;&lt;br&gt;
The old tab selector flow is gone.&lt;/p&gt;

&lt;p&gt;In v0.2.0, Ruse attaches to the current tab when the side panel opens. That sounds small, but it matters because the tool should follow the workflow you already have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the app you are testing.&lt;/li&gt;
&lt;li&gt;Open the Ruse side panel.&lt;/li&gt;
&lt;li&gt;Capture a real request.&lt;/li&gt;
&lt;li&gt;Create a local mock rule.&lt;/li&gt;
&lt;li&gt;Reload and inspect the UI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is less setup before the first useful action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Local collections for mock rules&lt;/strong&gt;&lt;br&gt;
Ruse v0.2.0 adds local collections so rules do not become one long, messy list. The current limits are intentionally small:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;up to 20 local rules&lt;/li&gt;
&lt;li&gt;up to 3 local collections&lt;/li&gt;
&lt;li&gt;each rule can belong to one collection or stay ungrouped&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is enough structure for the current product without pretending Ruse is already a full team platform.&lt;/p&gt;

&lt;p&gt;Example collections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checkout errors&lt;/li&gt;
&lt;li&gt;Dashboard empty states&lt;/li&gt;
&lt;li&gt;Slow API demos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Assign rules while creating or editing&lt;/strong&gt;&lt;br&gt;
Rules can now be assigned to a collection in the create and edit flows. This is useful when you are already thinking in scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"this rule belongs to the billing screen"&lt;/li&gt;
&lt;li&gt;"this one is for a demo"&lt;/li&gt;
&lt;li&gt;"these three are all empty-state cases"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rule organization happens close to the moment where the rule is created, instead of becoming cleanup work later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Drag-and-drop between collections&lt;/strong&gt;&lt;br&gt;
You can move rules between collections and ungrouped rules with drag and drop.&lt;/p&gt;

&lt;p&gt;This is a small interaction detail, but it keeps the local workflow fast. Ruse should feel like a tool you can use while thinking about the product state, not like another admin panel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Rename and delete collections safely&lt;/strong&gt;&lt;br&gt;
Collections can be renamed or deleted. Deleting a collection does not delete its rules. The rules move back to ungrouped. That behavior is deliberate. In a local testing tool, destructive organization actions should not quietly destroy the mock rules you made while debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  What v0.2.0 is not
&lt;/h2&gt;

&lt;p&gt;This release does not add cloud sync, auth, team workspaces, billing, shared collections, or rule version history. Those are bigger product directions, but they are not the current promise. The current promise is narrower:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make browser-level local API mocks easier for frontend developers and QA engineers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That means the product should stay honest about what it does today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this release matters
&lt;/h2&gt;

&lt;p&gt;The first version proved the basic idea: Ruse can help turn browser requests into local mock rules.&lt;/p&gt;

&lt;p&gt;v0.2.0 is about making that idea easier to use once you have more than one rule.&lt;/p&gt;

&lt;p&gt;One rule is a demo.&lt;br&gt;
Several rules are a workflow.&lt;br&gt;
Once you start testing a real screen, you quickly need more than one state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;normal data&lt;/li&gt;
&lt;li&gt;empty data&lt;/li&gt;
&lt;li&gt;loading&lt;/li&gt;
&lt;li&gt;server error&lt;/li&gt;
&lt;li&gt;malformed response&lt;/li&gt;
&lt;li&gt;permission error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Collections make that local workflow easier to keep in your head.&lt;/p&gt;

&lt;p&gt;The working-tab behavior also matters because a browser extension should feel attached to the thing you are testing. If you are already in the right tab, Ruse should not ask you to solve a tab-selection puzzle before you can work.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical v0.2.0 workflow
&lt;/h2&gt;

&lt;p&gt;Try this with a real frontend screen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the page you are building or testing.&lt;/li&gt;
&lt;li&gt;Open Ruse on that tab.&lt;/li&gt;
&lt;li&gt;Capture the request for the data you want to control.&lt;/li&gt;
&lt;li&gt;Create a local mock rule.&lt;/li&gt;
&lt;li&gt;Make one response return an empty list.&lt;/li&gt;
&lt;li&gt;Make another response return an error.&lt;/li&gt;
&lt;li&gt;Put both rules into a collection named after the screen or scenario.&lt;/li&gt;
&lt;li&gt;Reload the UI and test the states intentionally.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is where Ruse should be useful: when you need a fast local testing loop without asking the backend, staging, or a mock server to change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Ruse goes next
&lt;/h2&gt;

&lt;p&gt;The next active development focus is v0.3.0.&lt;/p&gt;

&lt;p&gt;The current plan is another quality pass around HTTP rule creation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;safer create-from-log drafts&lt;/li&gt;
&lt;li&gt;better response body editing&lt;/li&gt;
&lt;li&gt;JSON validation and formatting&lt;/li&gt;
&lt;li&gt;response header editing&lt;/li&gt;
&lt;li&gt;noisy header sanitization&lt;/li&gt;
&lt;li&gt;investigation into permission reduction where it is safe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The direction is still the same: make the local browser mocking loop feel faster, safer, and more predictable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;br&gt;
Ruse v0.2.0 is available now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruse.dev" rel="noopener noreferrer"&gt;https://ruse.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you try it, the most useful feedback is specific:&lt;/p&gt;

&lt;p&gt;Was the working-tab flow obvious?&lt;br&gt;
Did collections help organize real testing work?&lt;br&gt;
Where did creating a mock rule still feel slow?&lt;br&gt;
Which API state do you still find painful to reproduce?&lt;br&gt;
That feedback is exactly what should shape the next release.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>testing</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ruse Is Live: Mock API Responses in Chrome Without a Mock Server</title>
      <dc:creator>Kudasov Dmitriy</dc:creator>
      <pubDate>Mon, 25 May 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/rusedev/ruse-is-live-mock-api-responses-in-chrome-without-a-mock-server-55p3</link>
      <guid>https://dev.to/rusedev/ruse-is-live-mock-api-responses-in-chrome-without-a-mock-server-55p3</guid>
      <description>&lt;p&gt;Ruse is now live in the Chrome Web Store.&lt;/p&gt;

&lt;p&gt;It is a Chrome extension for frontend developers and QA engineers who need to test API states that are hard to reproduce on demand.&lt;br&gt;
The first version is intentionally small:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capture a real browser request&lt;/li&gt;
&lt;li&gt;turn it into a local mock rule&lt;/li&gt;
&lt;li&gt;change the response&lt;/li&gt;
&lt;li&gt;reload your app&lt;/li&gt;
&lt;li&gt;test the UI state you actually need&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No mock server.&lt;/p&gt;

&lt;p&gt;No proxy setup.&lt;/p&gt;

&lt;p&gt;No app-code changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Frontend development often gets blocked by API states that are technically possible, but practically annoying to reproduce.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maybe the backend endpoint is not ready yet.&lt;/li&gt;
&lt;li&gt;Maybe staging has the wrong data.&lt;/li&gt;
&lt;li&gt;Maybe you need the API to return a 500, but the backend is healthy.&lt;/li&gt;
&lt;li&gt;Maybe you need an empty list, but the shared environment has 400 records.&lt;/li&gt;
&lt;li&gt;Maybe QA found a bug in a permission state that nobody can reproduce anymore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These situations are not rare edge cases. They are normal frontend work. The annoying part is that the usual workarounds can be heavier than the task itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common workarounds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mock servers&lt;/strong&gt;&lt;br&gt;
Mock servers are powerful. They are useful when a team needs a shared fake backend, stable contracts, or a full development environment. But sometimes you do not need a whole mock environment. Sometimes you just need one request to return one specific response for ten minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local fixtures&lt;/strong&gt;&lt;br&gt;
Fixtures are fast for isolated components, but they do not always match the real network flow of the app.&lt;/p&gt;

&lt;p&gt;Authentication, request timing, retries, headers, routing, and runtime conditions can all matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend flags or special test data&lt;/strong&gt;&lt;br&gt;
This can work in mature teams, but it creates coordination overhead. You have to ask someone to create the state, wait for it, and hope it still exists when QA or design tries to reproduce the same screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temporary code hacks&lt;/strong&gt;&lt;br&gt;
We have all done this.&lt;/p&gt;

&lt;p&gt;Add a temporary throw. Hardcode a response. Comment out a fetch call. Edit something in DevTools. Change a local branch just to force the UI into one state.&lt;/p&gt;

&lt;p&gt;It works, but it is fragile and easy to forget.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Ruse does
&lt;/h2&gt;

&lt;p&gt;Ruse takes a smaller approach. Instead of starting with a mock server or a config file, it starts with the request your app is already making in the browser.&lt;/p&gt;

&lt;p&gt;The workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your app in Chrome.&lt;/li&gt;
&lt;li&gt;Open Ruse.&lt;/li&gt;
&lt;li&gt;See browser requests in the request log.&lt;/li&gt;
&lt;li&gt;Pick the request you want to control.&lt;/li&gt;
&lt;li&gt;Create a local mock rule.&lt;/li&gt;
&lt;li&gt;Change the response body, status, headers, or delay.&lt;/li&gt;
&lt;li&gt;Reload and test the UI state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is the core loop.&lt;br&gt;
Real request -&amp;gt; local mock -&amp;gt; controlled UI state.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can use it for
&lt;/h2&gt;

&lt;p&gt;Ruse is useful when you need to test states like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;empty lists&lt;/li&gt;
&lt;li&gt;500 errors&lt;/li&gt;
&lt;li&gt;404 states&lt;/li&gt;
&lt;li&gt;slow responses&lt;/li&gt;
&lt;li&gt;malformed JSON&lt;/li&gt;
&lt;li&gt;permission errors&lt;/li&gt;
&lt;li&gt;expired sessions&lt;/li&gt;
&lt;li&gt;missing backend endpoints&lt;/li&gt;
&lt;li&gt;stable demo data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is not to replace every other API mocking tool. The point is to make one browser-level override fast enough that you actually use it during normal frontend work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What v0.1.0 is not&lt;/strong&gt;&lt;br&gt;
The first version is not trying to be a full API platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is not an API client.&lt;/li&gt;
&lt;li&gt;It is not a complete mock server replacement.&lt;/li&gt;
&lt;li&gt;It is not a team collaboration suite yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is intentional. The first version focuses on one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can a frontend developer control a real browser request locally, quickly enough to test the UI state they need right now?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If that loop is useful, the product can grow from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why local-first matters
&lt;/h2&gt;

&lt;p&gt;For v0.1.0, Ruse is local-first. That means the first useful version should not require a complex account setup just to mock one API response in your browser.&lt;/p&gt;

&lt;p&gt;The goal is to keep the initial workflow lightweight:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install extension&lt;/li&gt;
&lt;li&gt;open app&lt;/li&gt;
&lt;li&gt;capture request&lt;/li&gt;
&lt;li&gt;create rule&lt;/li&gt;
&lt;li&gt;test state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Future versions can add better organization, sync, teams, and more advanced workflows. But the first version should earn trust by being simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who should try it
&lt;/h2&gt;

&lt;p&gt;Ruse is probably useful if you are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a frontend developer building against incomplete APIs&lt;/li&gt;
&lt;li&gt;a QA engineer testing edge cases&lt;/li&gt;
&lt;li&gt;a full-stack developer building frontend and backend in parallel&lt;/li&gt;
&lt;li&gt;a developer preparing a demo that needs stable data&lt;/li&gt;
&lt;li&gt;someone who keeps hardcoding API responses just to test UI states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is especially useful if you have ever said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I just need this one request to return something different for a few minutes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What feedback would help most
&lt;/h2&gt;

&lt;p&gt;The best feedback right now is specific and practical.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Which request did you try to mock?&lt;/li&gt;
&lt;li&gt;Did the request log make sense?&lt;/li&gt;
&lt;li&gt;Was the rule editor clear?&lt;/li&gt;
&lt;li&gt;Did a permission feel scary or unclear?&lt;/li&gt;
&lt;li&gt;Did a mock fail where you expected it to work?&lt;/li&gt;
&lt;li&gt;Which API state did you want but could not create easily?&lt;/li&gt;
&lt;li&gt;What felt slower than it should?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That kind of feedback is more useful than generic praise.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;The next version is already in motion.&lt;/p&gt;

&lt;p&gt;The focus is on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lighter permissions&lt;/li&gt;
&lt;li&gt;better rule organization&lt;/li&gt;
&lt;li&gt;cleaner local workflows&lt;/li&gt;
&lt;li&gt;faster request-log-to-rule flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The product is live now, but it is still early enough that real user feedback can shape the next release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you build frontend against unstable APIs, try Ruse and send feedback.&lt;/p&gt;

&lt;p&gt;Website: &lt;a href="https://ruse.dev" rel="noopener noreferrer"&gt;https://ruse.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chrome Web Store: use the install link on the Ruse website after the production landing update is live.&lt;/p&gt;

&lt;p&gt;If you test it on a real frontend workflow, I would love to hear what breaks, what feels unclear, and what should be easier.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>testing</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Test Frontend Error States Without Breaking Your Backend</title>
      <dc:creator>Kudasov Dmitriy</dc:creator>
      <pubDate>Thu, 21 May 2026 16:32:31 +0000</pubDate>
      <link>https://dev.to/rusedev/how-to-test-frontend-error-states-without-breaking-your-backend-1ojd</link>
      <guid>https://dev.to/rusedev/how-to-test-frontend-error-states-without-breaking-your-backend-1ojd</guid>
      <description>&lt;p&gt;Frontend teams are usually pretty good at testing the happy path. The API returns 200. The response shape is correct. The list has data. The network is fast enough. The user sees the page we designed.&lt;/p&gt;

&lt;p&gt;Great.&lt;/p&gt;

&lt;p&gt;But products do not live only in the happy path.&lt;br&gt;
They live in all the awkward states around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the endpoint returns 500&lt;/li&gt;
&lt;li&gt;the list is empty&lt;/li&gt;
&lt;li&gt;the request is slow&lt;/li&gt;
&lt;li&gt;the response is malformed&lt;/li&gt;
&lt;li&gt;the token expired&lt;/li&gt;
&lt;li&gt;the user has no permissions&lt;/li&gt;
&lt;li&gt;staging data changed again&lt;/li&gt;
&lt;li&gt;the backend endpoint is not ready yet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These states are often where the UI becomes the most important. They are also the states that are hardest to reproduce on demand.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem with relying on staging
&lt;/h2&gt;

&lt;p&gt;A lot of teams treat staging as the place where frontend edge cases should be tested. In theory, that makes sense. In practice, staging is rarely in the exact state you need.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maybe you need an empty list, but staging has 400 items.&lt;/li&gt;
&lt;li&gt;Maybe you need the API to return a 500, but the backend is currently healthy.&lt;/li&gt;
&lt;li&gt;Maybe you need a slow response to test loading behavior, but the request is too fast.&lt;/li&gt;
&lt;li&gt;Maybe you need a specific permission error, but nobody wants to mutate test data or add a temporary backend flag just so you can check one UI state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the frontend workaround begins.&lt;/p&gt;
&lt;h2&gt;
  
  
  Common workarounds
&lt;/h2&gt;

&lt;p&gt;There are a few common ways to deal with this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Mock servers&lt;/strong&gt;&lt;br&gt;
Mock servers are powerful. They are great when you need shared contracts, stable fake environments, or a full backend replacement during development. But they can also be heavy when the task is small.&lt;/p&gt;

&lt;p&gt;Sometimes you do not need a full mock environment. You just need this one request to return an empty array for ten minutes while you fix a UI. Setting up a mock server for that can feel like too much ceremony.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Local fixtures&lt;/strong&gt;&lt;br&gt;
Local fixtures are fast and simple.&lt;/p&gt;

&lt;p&gt;You create a JSON file, import it somewhere, and render the UI against that data.&lt;/p&gt;

&lt;p&gt;This works well for isolated components. But it gets harder when the behavior depends on the actual network flow of the app: auth, routing, loading states, retries, request timing, headers, or runtime conditions.&lt;/p&gt;

&lt;p&gt;Fixtures can also drift from real API responses over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Backend flags or test endpoints&lt;/strong&gt;&lt;br&gt;
Sometimes the backend team can add a flag, seed special data, or expose a test endpoint. That can be useful, especially in mature teams. But it also creates coordination overhead. The frontend developer has to ask for the state, wait for it, and hope it still exists when QA or design tries to reproduce the same thing later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Browser hacks&lt;/strong&gt;&lt;br&gt;
We have all done some version of this. Add a temporary throw. Edit code in DevTools. Comment out a fetch call. Hardcode a response. Change a local branch just to force an error state.&lt;/p&gt;

&lt;p&gt;It works, but it is fragile. It is also easy to forget, hard to share, and not something you want to rely on for repeatable testing.&lt;/p&gt;
&lt;h2&gt;
  
  
  A lighter workflow: override the response locally
&lt;/h2&gt;

&lt;p&gt;For many frontend tasks, the ideal workflow is smaller:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the app.&lt;/li&gt;
&lt;li&gt;See the real request the app is making.&lt;/li&gt;
&lt;li&gt;Choose the request you want to control.&lt;/li&gt;
&lt;li&gt;Return the response you need.&lt;/li&gt;
&lt;li&gt;Reload and test the UI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;No backend change. No proxy setup. No full mock server. No app code changes.&lt;/strong&gt;&lt;br&gt;
Just one local override for one real browser request.&lt;br&gt;
That is the workflow I have been thinking about while building Ruse.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example states worth testing
&lt;/h2&gt;

&lt;p&gt;Here are a few states I think every production UI should be easy to test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Empty list&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&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;Does the UI show a thoughtful empty state? Is the CTA correct? Does the layout collapse awkwardly? Does pagination disappear?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server error&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Internal server error"&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;Does the page recover? Can the user retry? Is the message useful? Does the app accidentally show a blank screen?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slow response&lt;/strong&gt;&lt;br&gt;
A slow API often reveals problems that fast local development hides.&lt;/p&gt;

&lt;p&gt;Do loading indicators appear? Do buttons stay disabled? Does the page jump when data arrives? Can the user trigger duplicate actions?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Malformed response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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;This is where defensive UI code gets tested.&lt;/p&gt;

&lt;p&gt;Does the app fail gracefully, or does one unexpected value take down the entire screen?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Permission error&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You do not have access to this resource"&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;Permission states are product states too. They need design, copy, and behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why browser-level mocking is useful
&lt;/h2&gt;

&lt;p&gt;Mocking at the browser level is interesting because it starts from what your app is actually doing.&lt;/p&gt;

&lt;p&gt;You are not inventing a request from memory. You are not manually recreating the URL, method, and response shape from scratch. You are looking at real traffic and deciding: "for this request, return this instead."&lt;/p&gt;

&lt;p&gt;That makes the loop feel more natural for frontend work.&lt;/p&gt;

&lt;p&gt;It is especially useful when you are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building UI before the backend is complete&lt;/li&gt;
&lt;li&gt;testing error states&lt;/li&gt;
&lt;li&gt;preparing stable demos&lt;/li&gt;
&lt;li&gt;reproducing QA bugs&lt;/li&gt;
&lt;li&gt;checking loading behavior&lt;/li&gt;
&lt;li&gt;designing empty states&lt;/li&gt;
&lt;li&gt;working against flaky staging data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Ruse fits
&lt;/h2&gt;

&lt;p&gt;I am building Ruse as a Chrome extension for this workflow.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inspect browser requests&lt;/li&gt;
&lt;li&gt;create local mock rules&lt;/li&gt;
&lt;li&gt;return custom responses&lt;/li&gt;
&lt;li&gt;test the UI state you need&lt;/li&gt;
&lt;li&gt;keep everything local in the browser
The first release is intentionally small and local-first. It is not trying to be a full API platform. It is focused on making the first useful mock fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ruse is currently in alpha and going through Chrome Web Store review.&lt;/p&gt;

&lt;p&gt;If this workflow sounds useful, I am looking for early testers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruse.dev/support?topic=early-access" rel="noopener noreferrer"&gt;https://ruse.dev/support?topic=early-access&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Frontend edge cases should not require a backend meeting.&lt;/p&gt;

&lt;p&gt;Sometimes you need a full mock server. Sometimes you need contract testing. Sometimes you need proper seeded environments.&lt;/p&gt;

&lt;p&gt;But sometimes you just need one request to return one different response so you can finish the UI in front of you.&lt;/p&gt;

&lt;p&gt;That small loop is worth making better.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>testing</category>
      <category>webdev</category>
      <category>api</category>
    </item>
  </channel>
</rss>
