<?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: EHUB IT Web Solution</title>
    <description>The latest articles on DEV Community by EHUB IT Web Solution (ehub).</description>
    <link>https://dev.to/ehub</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.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F15607%2F65ae5f13-8746-470e-9716-8171884fc0cf.png</url>
      <title>DEV Community: EHUB IT Web Solution</title>
      <link>https://dev.to/ehub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ehub"/>
    <language>en</language>
    <item>
      <title>Test a Shopify Store as an Order Workflow, Not a Collection of Screens</title>
      <dc:creator>Nehal Gulati</dc:creator>
      <pubDate>Mon, 26 Oct 2026 10:12:54 +0000</pubDate>
      <link>https://dev.to/ehub/test-a-shopify-store-as-an-order-workflow-not-a-collection-of-screens-55ba</link>
      <guid>https://dev.to/ehub/test-a-shopify-store-as-an-order-workflow-not-a-collection-of-screens-55ba</guid>
      <description>&lt;p&gt;A storefront review often starts with screenshots: the homepage, a collection grid, and a product page. Those screens matter, but a customer buys through a sequence. A release needs to be reviewed as that sequence, including the work that happens after checkout.&lt;/p&gt;

&lt;p&gt;The useful question is not simply whether each page loads. It is whether a person can choose the right item, understand the total, complete checkout, and receive the information the merchant needs to fulfil the order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a small test matrix before reviewing the theme
&lt;/h2&gt;

&lt;p&gt;Choose representative products rather than testing only the easiest item. A compact matrix might include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Case&lt;/th&gt;
&lt;th&gt;What to inspect&lt;/th&gt;
&lt;th&gt;Evidence to retain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Product with variants&lt;/td&gt;
&lt;td&gt;Selected option, image, price, availability&lt;/td&gt;
&lt;td&gt;Variant and resulting cart line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unavailable item&lt;/td&gt;
&lt;td&gt;Purchase controls and availability message&lt;/td&gt;
&lt;td&gt;Product state and storefront result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-item cart&lt;/td&gt;
&lt;td&gt;Quantities, discounts, shipping eligibility&lt;/td&gt;
&lt;td&gt;Cart and checkout totals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supported destination&lt;/td&gt;
&lt;td&gt;Applicable shipping options&lt;/td&gt;
&lt;td&gt;Test destination and options shown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unsupported destination&lt;/td&gt;
&lt;td&gt;Clear delivery restriction&lt;/td&gt;
&lt;td&gt;Expected message&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cancelled checkout&lt;/td&gt;
&lt;td&gt;A safe route back to the store&lt;/td&gt;
&lt;td&gt;Customer-visible result&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use the merchant's actual rules to decide expected results. Do not label a behaviour a bug merely because another store handles it differently.&lt;/p&gt;

&lt;p&gt;Record the theme version or release identifier, device, browser, test data, expected behaviour, and observed behaviour. A screenshot with no product, variant, or release context is difficult to reproduce later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate visual review from purchasing review
&lt;/h2&gt;

&lt;p&gt;During visual review, inspect product imagery, readable pricing, variant labels, focus states, and mobile overflow. Then repeat the journey using a keyboard and a real mobile device where available.&lt;/p&gt;

&lt;p&gt;During purchasing review, check that the chosen option survives into the cart. Change quantities, remove an item, return to a product, and try the drawer and full-cart page if both exist. Confirm that the final price, delivery information, and applicable discounts match the agreed business rules.&lt;/p&gt;

&lt;p&gt;Avoid measuring success through a single ideal journey. A product that behaves correctly on its own may expose a different shipping or discount outcome when combined with another item.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify the order after the confirmation screen
&lt;/h2&gt;

&lt;p&gt;Shopify provides supported ways to simulate payment. Its &lt;a href="https://help.shopify.com/en/manual/checkout-settings/test-orders" rel="noopener noreferrer"&gt;test-order documentation&lt;/a&gt; explains the available options and requirements. Customers cannot place live orders through a payment provider while it is in test mode, so coordinate testing and restore the live configuration deliberately.&lt;/p&gt;

&lt;p&gt;For each representative test, inspect the resulting order, variant details, shipping selection, notification content, and operational handoff. Where an inventory or fulfilment integration is involved, use its sandbox or the provider's agreed testing process. A storefront confirmation does not establish that an external warehouse received the order correctly.&lt;/p&gt;

&lt;p&gt;Keep simulated orders clearly labelled. They are QA records, not revenue, customers acquired, or evidence of a successful advertising campaign.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat migration URLs as a separate release item
&lt;/h2&gt;

&lt;p&gt;Before changing URLs, export or document important existing paths and map each retired path to a relevant destination. Test the mapping after deployment rather than assuming a completed import means the redirects work.&lt;/p&gt;

&lt;p&gt;Shopify's built-in redirects have limitations: a source that still resolves to an active page will not behave like a broken URL, and certain reserved paths cannot be redirected. Consult the &lt;a href="https://help.shopify.com/en/manual/online-store/menus-and-links/url-redirect" rel="noopener noreferrer"&gt;current redirect documentation&lt;/a&gt; for the paths involved in your migration.&lt;/p&gt;

&lt;p&gt;For each important mapping, capture the old URL, response status, and final destination. Look for loops and unnecessary chains. Test market-specific routes individually when language or regional paths are in use. Do not send every retired product to the homepage simply to avoid a visible error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the merchant a release decision they can understand
&lt;/h2&gt;

&lt;p&gt;Use three outcomes: passed, failed, and not tested. Assign an owner and a next action to unresolved items. A test that could not run is not a pass.&lt;/p&gt;

&lt;p&gt;Before launch, agree which failures prevent release and which can be scheduled later. Broken purchasing, incorrect totals, or a missing operational handoff need a different response from a minor spacing issue. Preserve a known working theme and record the recovery steps, but remember that reverting a theme does not automatically undo order, app, or configuration changes.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ehub.co.in/blog/shopify-store-launch-checklist" rel="noopener noreferrer"&gt;EHUB Shopify store launch checklist&lt;/a&gt; provides additional context for agreeing catalogue and market requirements before this test plan is written.&lt;/p&gt;

&lt;p&gt;A release becomes easier to support when its acceptance evidence describes an entire order journey, with clear limits on what was actually verified.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Published by EHUB. Prepared with AI assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>shopify</category>
    </item>
    <item>
      <title>A Mobile Enquiry Form Is a Small State Machine</title>
      <dc:creator>Nehal Gulati</dc:creator>
      <pubDate>Mon, 26 Oct 2026 10:11:43 +0000</pubDate>
      <link>https://dev.to/ehub/a-mobile-enquiry-form-is-a-small-state-machine-kkj</link>
      <guid>https://dev.to/ehub/a-mobile-enquiry-form-is-a-small-state-machine-kkj</guid>
      <description>&lt;p&gt;A form can look finished while its most important behaviour is still undefined. What happens when the network fails? What does a second tap do? Does the success message mean the server accepted the enquiry, or only that JavaScript ran?&lt;/p&gt;

&lt;p&gt;Treating the form as a small state machine makes those questions easier to answer. This walkthrough covers a contact form, but the same approach works for demo requests and project enquiries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with four states
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;idle&lt;/code&gt;, &lt;code&gt;submitting&lt;/code&gt;, &lt;code&gt;success&lt;/code&gt;, and &lt;code&gt;error&lt;/code&gt;. Browser validation happens before the submit handler runs. The handler then moves into &lt;code&gt;submitting&lt;/code&gt;; only the server response determines whether it can move into &lt;code&gt;success&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Submit button&lt;/th&gt;
&lt;th&gt;Message&lt;/th&gt;
&lt;th&gt;User input&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Idle&lt;/td&gt;
&lt;td&gt;Available&lt;/td&gt;
&lt;td&gt;Brief instructions&lt;/td&gt;
&lt;td&gt;Editable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Submitting&lt;/td&gt;
&lt;td&gt;Disabled&lt;/td&gt;
&lt;td&gt;Sending&lt;/td&gt;
&lt;td&gt;Preserved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Success&lt;/td&gt;
&lt;td&gt;Available&lt;/td&gt;
&lt;td&gt;Request accepted&lt;/td&gt;
&lt;td&gt;Clear only after acceptance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error&lt;/td&gt;
&lt;td&gt;Available&lt;/td&gt;
&lt;td&gt;Actionable retry message&lt;/td&gt;
&lt;td&gt;Preserved&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A disabled button reduces accidental double taps. It does not provide server-side duplicate protection: that requires an idempotency mechanism or another deliberate backend rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the HTML useful before JavaScript
&lt;/h2&gt;

&lt;p&gt;Give every field a visible label. Use autocomplete tokens to make mobile input less tedious. A telephone field helps the keyboard, but it does not establish that a number is valid or reachable.&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;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/enquiries"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"enquiry-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"contact-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Your name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"contact-name"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;
         &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;maxlength=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"contact-phone"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Phone number&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"contact-phone"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"phone"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"tel"&lt;/span&gt;
         &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"tel"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;maxlength=&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"project"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;What would you like to build?&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"project"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"project"&lt;/span&gt;
            &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;maxlength=&lt;/span&gt;&lt;span class="s"&gt;"2000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Send enquiry&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt; &lt;span class="na"&gt;aria-live=&lt;/span&gt;&lt;span class="s"&gt;"polite"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"form-status"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The action is illustrative: a real application needs a matching server route. That route should support ordinary form submission as well as the enhanced JSON response. Add the application's CSRF protection, server validation, abuse controls, and appropriate privacy information before deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define what acceptance means
&lt;/h2&gt;

&lt;p&gt;For an enhanced request, establish a response contract such as:&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;"accepted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;The server should return this only after it has durably recorded or queued the enquiry according to the application's design. An accepted enquiry is not proof that an email reached an inbox, a salesperson responded, or a sale occurred.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#enquiry-form&lt;/span&gt;&lt;span class="dl"&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;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button[type="submit"]&lt;/span&gt;&lt;span class="dl"&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;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#form-status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;submitting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;submitting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;submitting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sending your enquiry…&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accepted&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enquiry was not accepted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your enquiry has been received.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;We could not confirm receipt. Please check your connection or contact us.&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="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;submitting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;&lt;code&gt;fetch()&lt;/code&gt; does not reject just because the server returns an HTTP error. The explicit &lt;code&gt;response.ok&lt;/code&gt; check matters. Malformed or unexpected JSON also goes through the error path here.&lt;/p&gt;

&lt;p&gt;A lost response creates an awkward case: the server might have accepted the request even though the browser cannot confirm it. Preserve the input and use honest wording. For stronger retry guarantees, implement a server-recognised idempotency key rather than assuming a second request is safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the unsuccessful paths too
&lt;/h2&gt;

&lt;p&gt;Before launch, check an empty submission, invalid input, a slow response, a server error, and a rapid double tap. Verify keyboard navigation, visible focus, readable labels, and a success message announced without moving focus unexpectedly. Use synthetic contact details in a test environment.&lt;/p&gt;

&lt;p&gt;If analytics is added, place the enquiry event after confirmed acceptance and honour the site's measurement preferences. Do not put contact details or the free-text message into an analytics payload. A button click should remain a separate interaction event.&lt;/p&gt;

&lt;p&gt;For the business-side decisions behind the fields, the &lt;a href="https://ehub.co.in/blog/mobile-website-enquiry-form-guide" rel="noopener noreferrer"&gt;EHUB mobile enquiry-form planning guide&lt;/a&gt; covers what to agree before implementation.&lt;/p&gt;

&lt;p&gt;Technical references: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/form" rel="noopener noreferrer"&gt;HTML forms&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;Fetch response handling&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Published by EHUB. Prepared with AI assistance.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
